Happy Holidays - Christmas hats for all users
So I made this thing to give all users a random christmas hat out of a set of 8
This is the code of the component (I placed the component in the header quilt)
<#-- custom vfz-js-christmas-hats -->
<@compress single_line=true>
<@liaMarkupCache ttl="60000" variation="node" anonymousOnly="false" />
<#import "theme-lib.common-functions.ftl" as commonUtils />
<#assign query = "SELECT rank.name FROM users WHERE id = '${user.id}' LIMIT 1" />
<#assign result = commonUtils.executeLiQLQuery(query) />
</@compress>
<#if result?has_content>
</#if>
<style>
@media screen and (min-width: 767px) and (max-width: 991px) {
.lia-quilt-row-header-hero-top .custom-community-hero-left .vfz-hat{
margin-top: -156px !important;
}
}
</style>
<script>
window.addEventListener('DOMContentLoaded', (event) => {
function getImageHashAndConvertTo4digits(str) {
const match = str.match(new RegExp(('image-id') + "(.*)" + ('image-dimensions'))) || str.match(new RegExp(('avatar-name') + "(.*)" + ('avatar-theme'))) || str.match(new RegExp(('images') + "(.*)" + ('ziggo'))) || str.match(new RegExp(('avatars') + "(.*)" + ('.')));
var result = match[1].replace('a','0');
result = result.replace('b','1');
result = result.replace(/\D/g,'');
result = result.substr(-4);
result = parseInt(result);
return result;
}
function setHatType(number) { // 5 6 1 2 7 8 3 4
var hatType = 0;
hatType = (number % 2 == 0) ? (hatType + 1) : (hatType + 2);
hatType = ((Math.floor(number / 10)) % 2 == 0) ? (hatType + 3) : (hatType - 1);
hatType = ((Math.floor(number / 1000)) % 2 == 0) ? (hatType + 1) : (hatType + 3);
var transform = ((Math.floor(number / 100)) % 2 == 0) ? "" : 'transform="scale(-1,1)"';
const hatUrl = '/html/assets/christmashat_type'+ hatType +'.svg';
return [hatUrl, transform];
}
function getPosition(target) {
const position = target.getBoundingClientRect();
return {
left: position .left + window.scrollX,
top: position .top + window.scrollY
}
};
function placeHatOnCLass(query_str, parent_str) {
var targetElements = document.querySelectorAll(query_str);
if (targetElements) {
var targetElementsLength = targetElements.length;
while(targetElementsLength--) {
var targetImage = targetElements[targetElementsLength].getElementsByTagName("img")[0];
if (targetImage) {
if (targetImage.className != 'vfz-hat' && targetImage.parentNode.parentNode != 'vfz-hat') {
const imageHash = getImageHashAndConvertTo4digits(targetImage.src);
const hatType = setHatType(imageHash);
var overlay = document.createElement('img');
overlay.className = 'vfz-hat';
overlay.src=hatType[0];
overlay.style.position = 'absolute';
overlay.style.borderRadius = "initial";
overlay.style.objectFit = "initial";
overlay.style.boxShadow = "initial";
overlay.style.zIndex = "2";
targetImageSize = targetImage.offsetWidth;
overlay.style.width = targetImageSize*1.8 + 'px';
overlay.style.maxWidth = targetImageSize*1.8 + 'px';
overlay.style.height = targetImageSize*0.9 + 'px';
overlay.style.maxHeight = targetImageSize*0.9 + 'px';
overlay.style.marginLeft = '-' + targetImageSize/2.4 + 'px';
if (targetImage.parentNode.parentNode.className == 'custom-community-hero-welcome custom-community-hero' && window.innerHeight > 767 && window.innerHeight < 990) {
overlay.style.marginTop = '-' + 0 + 'px';;
} else {
overlay.style.marginTop = '-' + targetImageSize/2.4 + 'px';
}
if (targetImage.parentNode.parentNode.parentNode.parentNode.className == 'lia-quilt-column-alley lia-quilt-column-alley-left' || targetImage.parentNode.parentNode.parentNode.parentNode.className == 'userColumn lia-data-cell-primary lia-data-cell-text') {
targetImage.parentNode.parentNode.parentNode.insertBefore(overlay, targetImage.parentNode.parentNode);
} else {
targetImage.parentNode.insertBefore(overlay, targetImage);
}
}
}
}
}
}
function initiateHats() {
<#--<#if coreNode.id == 'phxsb37772'>placeHatOnCLass('.custom-community-hero-left');</#if>-->
<#if page.name != 'GroupHubPage'>placeHatOnCLass('.lia-message-view-node-activity-message .lia-user-avatar');</#if>
placeHatOnCLass('.lia-avatar-editable .lia-link-navigation');
placeHatOnCLass('.lia-quilt-row-main-top .lia-user-avatar');
placeHatOnCLass('.custom-featured-post-tile .lia-link-navigation');
placeHatOnCLass('.lia-user-info-group .lia-link-navigation');
placeHatOnCLass('.lia-message-view-idea-message-item .lia-user-avatar');
placeHatOnCLass('.lia-thread-reply .lia-user-avatar');
placeHatOnCLass('.lia-quilt-forum-message .lia-user-avatar');
placeHatOnCLass('.UserNavigation .lia-link-navigation');
placeHatOnCLass('.message-list .lia-link-navigation');
placeHatOnCLass('.custom-message-list .lia-link-navigation');
}
function refreshHats() {
placeHatOnCLass('.lia-message-view-node-activity-message .lia-user-avatar');
placeHatOnCLass('.lia-avatar-editable .lia-link-navigation');
placeHatOnCLass('.lia-quilt-row-main-top .lia-user-avatar');
placeHatOnCLass('.custom-featured-post-tile .lia-link-navigation');
placeHatOnCLass('.lia-user-info-group .lia-link-navigation');
placeHatOnCLass('.lia-message-view-idea-message-item .lia-user-avatar');
placeHatOnCLass('.lia-thread-reply .lia-user-avatar');
placeHatOnCLass('.lia-quilt-forum-message .lia-user-avatar');
placeHatOnCLass('.UserNavigation .lia-link-navigation');
placeHatOnCLass('.message-list .lia-link-navigation');
placeHatOnCLass('.custom-message-list .lia-link-navigation');
}
initiateHats();
setTimeout(refreshHats, 1000);
setTimeout(refreshHats, 1300);
setTimeout(refreshHats, 1600);
document.addEventListener('click', function(e) {
if(e.target && e.target.id== 'custom-loader-button') {
//console.log('custom-loader-button pressed');
//refreshHats();
}
});
var observer = new MutationObserver(function (mutations) {
<#if page.name != 'GroupHubPage'>
if (mutations[0].addedNodes[0]) {
if (typeof mutations[0].addedNodes[0].className != "undefined") {
if (mutations[0].addedNodes[0].className != 'vfz-hat') refreshHats();
}
}
if (mutations[0].addedNodes[1]) {
if (typeof mutations[0].addedNodes[1].className != "undefined") {
if (mutations[0].addedNodes[1].classList.contains('custom-message-tile')) refreshHats();
//if (mutations[0].target == 'div.message-list') refreshHats();
}
}
</#if>
<#if page.name == 'GroupHubPage'>
if (mutations[0].addedNodes[0]) {
if (typeof mutations[0].addedNodes[0].className != "undefined") {
if (mutations[0].addedNodes[0].classList.contains('lia-panel-message')) refreshHats();
}
}
</#if>
});
observer.observe(document.body, { childList: true, subtree: true }); //attributes: true, characterData: true
});
</script>
<#-- /custom vfz-js-christmas-hats -->
These are the assets:
https://community.ziggo.nl/html/assets/christmashat_type1.svg
https://community.ziggo.nl/html/assets/christmashat_type2.svg
https://community.ziggo.nl/html/assets/christmashat_type3.svg
https://community.ziggo.nl/html/assets/christmashat_type4.svg
https://community.ziggo.nl/html/assets/christmashat_type5.svg
https://community.ziggo.nl/html/assets/christmashat_type6.svg
https://community.ziggo.nl/html/assets/christmashat_type7.svg
https://community.ziggo.nl/html/assets/christmashat_type6.svg
Feel free to use and improve all of this. Please share improvements as I had to implement a lot of dubious workarounds to get it to work. For instance on the GroupHubPage there is some DOM event listener from Khoros that removes all nodes inside the node of the avatar img. So the hats are removed. I had to make a timer to run the function again after the removal event. Does anyone know why Khoros does this??