Skip to content

Instantly share code, notes, and snippets.

@annibal
Last active September 26, 2024 18:12
Show Gist options
  • Save annibal/0a852b03d6733d21a2b217c944ef4380 to your computer and use it in GitHub Desktop.
Save annibal/0a852b03d6733d21a2b217c944ef4380 to your computer and use it in GitHub Desktop.
FixColmeiaChat
(function FixColmeiaChatFactory() {
// Will execute the fix, at the end of this script,
// Will assign an object with the props and the methods: window.FixColmeiaChat,
// Will return the object as well.
var props = {
// config max attempts of trying to find the <colmeia-chat> element
retryTimeout: 600,
retryAttempts: 6,
// only for debugging, if necessary
isFixApplied: false,
fixedAt: [],
// configures the behavior of the event handler
// { [EVENT_NAME]: settings }
// will add and remove classes from "<div class="chat-box">", and from "<button class="main-button">".
// also optional flag for preventDefault
stateEventsData: {
ready: {
rootClsAdd: "open",
rootClsRemove: "",
btnClsAdd: "",
btnClsRemove: "",
preventsDefault: false,
},
error: {
rootClsAdd: "",
rootClsRemove: "",
btnClsAdd: "",
btnClsRemove: "",
preventsDefault: false,
},
open: {
rootClsAdd: "open",
rootClsRemove: "is-open",
btnClsAdd: "",
btnClsRemove: "",
preventsDefault: false,
},
close: {
rootClsAdd: "",
rootClsRemove: "open",
btnClsAdd: "",
btnClsRemove: "is-open",
preventsDefault: false,
},
restore: {
rootClsAdd: "open",
rootClsRemove: "is-open",
btnClsAdd: "",
btnClsRemove: "",
preventsDefault: false,
},
minify: {
rootClsAdd: "",
rootClsRemove: "open",
btnClsAdd: "",
btnClsRemove: "is-open",
preventsDefault: false,
},
},
};
function debugLog(logIdx, data) {
var logs = [
// 0
function (_data) {
return [
"<colmeia-chat> not found. ",
"Can retry " + _data[0] + " times, ",
_data[1] ? "will retry in " + _data[2] + "ms" : "aborting",
".",
].join("");
},
// 1
function (_data) {
return [
"Found <colmeia-chat> element in the ",
_data[0],
"th attempt. ",
"Will apply Colmeia Chat fix.",
].join("");
},
// 2
function (_data) {
return [
"Binding listener #",
_data[0],
" to the colmeia-chat's '",
_data[1],
"' event.",
// "' event, which will ",
// _data[2] ? "Open" : "Close",
// " the webchat chat box.",
].join("");
},
// 3
function (_data) {
return [
"chatBox's current classList: '",
_data[0],
"', will run .add('",
_data[1],
"') then .remove('",
_data[2],
"').",
].join("");
},
// 4
function (_data) {
return [
"<colmeia-chat> already has ",
_data[1],
" listeners for '",
_data[0],
"' event, will remove all of them.",
].join("");
},
// 5
function (_data) {
return [
"Handling event '",
_data[0],
_data[1]
? ", Ignoring given no stateEventData exists for this event type"
: "",
".",
].join("");
},
// 6
function (_data) {
return ["Will prevent default for event '", _data[0], "'."];
},
];
try {
var logStr = logs[logIdx](data);
console.debug(">>: FixColmeiaChat: " + logStr);
} catch (e) {
try {
console.error(e);
} catch (e2) {}
}
}
function getElm_ChatRoot() {
return document.querySelector("colmeia-chat");
}
function getElm_ChatBox() {
return getElm_ChatRoot().shadowRoot.querySelector(".chat-box");
}
function getElm_ChatButton() {
return getElm_ChatRoot().shadowRoot.querySelector(".main-button");
}
function setElementClass(elm, clsAdd, clsRemove) {
debugLog(3, [elm.classList, clsAdd, clsRemove]);
if (clsAdd) {
elm.classList.add(clsAdd);
}
if (clsRemove) {
elm.classList.remove(clsRemove);
}
}
// the actual fix
function handleColmeiaChatEvent(event) {
var stateEventData = props.stateEventsData[event.eventType];
debugLog(5, [event.eventType, !stateEventData]);
if (stateEventData) {
setElementClass(
getElm_ChatBox(),
stateEventData.rootClsAdd,
stateEventData.rootClsRemove
);
setElementClass(
getElm_ChatButton(),
stateEventData.btnClsAdd,
stateEventData.btnClsRemove
);
if (stateEventData.preventsDefault) {
debugLog(6, [event.eventType]);
event.preventDefault();
return false;
}
}
}
function applyStateEvents(eventTypes) {
for (var i = 0; i < eventTypes.length; i += 1) {
var eventType = eventTypes[i];
debugLog(2, [i, eventType]);
var allListeners = getElm_ChatRoot().eventListeners(eventType);
if (allListeners.length > 0) {
debugLog(4, [eventType, allListeners.length]);
for (var j = 0; j < allListeners.length; j += 1) {
getElm_ChatRoot().removeEventListener(eventType, allListeners[j]);
}
}
getElm_ChatRoot().addEventListener(eventType, handleColmeiaChatEvent);
}
}
function tryToApplyFix(mRetryCount, eventTypesToFix) {
props.fixedAt.push({ type: "attempt", time: Date.now() });
var elmChatRoot = getElm_ChatRoot();
if (!elmChatRoot) {
var canRetry = mRetryCount > 0;
debugLog(0, [mRetryCount, canRetry, props.retryTimeout]);
if (canRetry) {
setTimeout(function () {
tryToApplyFix(mRetryCount - 1);
}, props.retryTimeout);
return;
} else {
props.fixedAt.push({ type: "fail", time: Date.now() });
throw new ReferenceError(
"Failed to fix Colmeia Chat after " +
props.retryAttempts +
" attempts: 'colmeia-chat' element not found."
);
}
}
debugLog(1, [props.retryAttempts - mRetryCount]);
applyStateEvents(eventTypesToFix);
props.isFixApplied = true;
props.fixedAt.push({ type: "success", time: Date.now() });
}
function fixTheChat(eventTypesToFix) {
setTimeout(function () {
tryToApplyFix(props.retryAttempts, eventTypesToFix);
}, props.retryTimeout);
}
window.FixColmeiaChat = {
data: props,
setElementClass: setElementClass,
handleColmeiaChatEvent: handleColmeiaChatEvent,
applyStateEvents: applyStateEvents,
tryToApplyFix: tryToApplyFix,
};
fixTheChat(["ready", "error", "open", "close", "restore", "minify"]);
return window.FixColmeiaChat;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment