Chatwoot/app/javascript/sdk/IFrameHelper.js
Nithin David Thomas 94209d29cb
fix: Fixes widget unread view blocking parent page (#3658)
Co-authored-by: Pranav <pranav@chatwoot.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
2022-01-12 12:27:16 -08:00

243 lines
7 KiB
JavaScript

import Cookies from 'js-cookie';
import {
wootOn,
addClass,
loadCSS,
removeClass,
onLocationChangeListener,
} from './DOMHelpers';
import {
body,
widgetHolder,
createBubbleHolder,
createBubbleIcon,
bubbleImg,
chatBubble,
closeBubble,
bubbleHolder,
createNotificationBubble,
onClickChatBubble,
onBubbleClick,
setBubbleText,
addUnreadClass,
removeUnreadClass,
} from './bubbleHelpers';
import { dispatchWindowEvent } from 'shared/helpers/CustomEventHelper';
const EVENT_NAME = 'chatwoot:ready';
export const IFrameHelper = {
getUrl({ baseUrl, websiteToken }) {
return `${baseUrl}/widget?website_token=${websiteToken}`;
},
createFrame: ({ baseUrl, websiteToken }) => {
if (IFrameHelper.getAppFrame()) {
return;
}
loadCSS();
const iframe = document.createElement('iframe');
const cwCookie = Cookies.get('cw_conversation');
let widgetUrl = IFrameHelper.getUrl({ baseUrl, websiteToken });
if (cwCookie) {
widgetUrl = `${widgetUrl}&cw_conversation=${cwCookie}`;
}
iframe.src = widgetUrl;
iframe.id = 'chatwoot_live_chat_widget';
iframe.style.visibility = 'hidden';
let holderClassName = `woot-widget-holder woot--hide woot-elements--${window.$chatwoot.position}`;
if (window.$chatwoot.hideMessageBubble) {
holderClassName += ` woot-widget--without-bubble`;
}
addClass(widgetHolder, holderClassName);
widgetHolder.appendChild(iframe);
body.appendChild(widgetHolder);
IFrameHelper.initPostMessageCommunication();
IFrameHelper.initWindowSizeListener();
IFrameHelper.preventDefaultScroll();
},
getAppFrame: () => document.getElementById('chatwoot_live_chat_widget'),
getBubbleHolder: () => document.getElementsByClassName('woot--bubble-holder'),
sendMessage: (key, value) => {
const element = IFrameHelper.getAppFrame();
element.contentWindow.postMessage(
`chatwoot-widget:${JSON.stringify({ event: key, ...value })}`,
'*'
);
},
initPostMessageCommunication: () => {
window.onmessage = e => {
if (
typeof e.data !== 'string' ||
e.data.indexOf('chatwoot-widget:') !== 0
) {
return;
}
const message = JSON.parse(e.data.replace('chatwoot-widget:', ''));
if (typeof IFrameHelper.events[message.event] === 'function') {
IFrameHelper.events[message.event](message);
}
};
},
initWindowSizeListener: () => {
wootOn(window, 'resize', () => IFrameHelper.toggleCloseButton());
},
preventDefaultScroll: () => {
widgetHolder.addEventListener('wheel', event => {
const deltaY = event.deltaY;
const contentHeight = widgetHolder.scrollHeight;
const visibleHeight = widgetHolder.offsetHeight;
const scrollTop = widgetHolder.scrollTop;
if (
(scrollTop === 0 && deltaY < 0) ||
(visibleHeight + scrollTop === contentHeight && deltaY > 0)
) {
event.preventDefault();
}
});
},
setFrameHeightToFitContent: (extraHeight, isFixedHeight) => {
const iframe = IFrameHelper.getAppFrame();
const updatedIframeHeight = isFixedHeight ? `${extraHeight}px` : '100%';
if (iframe)
iframe.setAttribute('style', `height: ${updatedIframeHeight} !important`);
},
events: {
loaded: message => {
Cookies.set('cw_conversation', message.config.authToken, {
expires: 365,
sameSite: 'Lax',
});
window.$chatwoot.hasLoaded = true;
IFrameHelper.sendMessage('config-set', {
locale: window.$chatwoot.locale,
position: window.$chatwoot.position,
hideMessageBubble: window.$chatwoot.hideMessageBubble,
showPopoutButton: window.$chatwoot.showPopoutButton,
});
IFrameHelper.onLoad({
widgetColor: message.config.channelConfig.widgetColor,
});
IFrameHelper.toggleCloseButton();
if (window.$chatwoot.user) {
IFrameHelper.sendMessage('set-user', window.$chatwoot.user);
}
dispatchWindowEvent(EVENT_NAME);
},
setBubbleLabel(message) {
if (window.$chatwoot.hideMessageBubble) {
return;
}
setBubbleText(window.$chatwoot.launcherTitle || message.label);
},
toggleBubble: state => {
let bubbleState = {};
if (state === 'open') {
bubbleState.toggleValue = true;
} else if (state === 'close') {
bubbleState.toggleValue = false;
}
onBubbleClick(bubbleState);
},
closeWindow: () => {
onBubbleClick({ toggleValue: false });
removeUnreadClass();
},
onBubbleToggle: isOpen => {
IFrameHelper.sendMessage('toggle-open', { isOpen });
if (isOpen) {
IFrameHelper.pushEvent('webwidget.triggered');
}
},
onLocationChange: ({ referrerURL, referrerHost }) => {
IFrameHelper.sendMessage('change-url', {
referrerURL,
referrerHost,
});
},
updateIframeHeight: message => {
const { extraHeight = 0, isFixedHeight } = message;
IFrameHelper.setFrameHeightToFitContent(extraHeight, isFixedHeight);
},
setUnreadMode: () => {
addUnreadClass();
onBubbleClick({ toggleValue: true });
},
resetUnreadMode: () => removeUnreadClass(),
handleNotificationDot: event => {
if (window.$chatwoot.hideMessageBubble) {
return;
}
const bubbleElement = document.querySelector('.woot-widget-bubble');
if (
event.unreadMessageCount > 0 &&
!bubbleElement.classList.contains('unread-notification')
) {
addClass(bubbleElement, 'unread-notification');
} else if (event.unreadMessageCount === 0) {
removeClass(bubbleElement, 'unread-notification');
}
},
closeChat: () => {
onBubbleClick({ toggleValue: false });
},
},
pushEvent: eventName => {
IFrameHelper.sendMessage('push-event', { eventName });
},
onLoad: ({ widgetColor }) => {
const iframe = IFrameHelper.getAppFrame();
iframe.style.visibility = '';
iframe.setAttribute('id', `chatwoot_live_chat_widget`);
if (IFrameHelper.getBubbleHolder().length) {
return;
}
createBubbleHolder();
onLocationChangeListener();
if (!window.$chatwoot.hideMessageBubble) {
const chatIcon = createBubbleIcon({
className: 'woot-widget-bubble',
src: bubbleImg,
target: chatBubble,
});
const closeIcon = closeBubble;
const closeIconclassName = `woot-elements--${window.$chatwoot.position} woot-widget-bubble woot--close woot--hide`;
addClass(closeIcon, closeIconclassName);
chatIcon.style.background = widgetColor;
closeIcon.style.background = widgetColor;
bubbleHolder.appendChild(chatIcon);
bubbleHolder.appendChild(closeIcon);
bubbleHolder.appendChild(createNotificationBubble());
onClickChatBubble();
}
},
toggleCloseButton: () => {
let isMobile = false;
if (window.matchMedia('(max-width: 668px)').matches) {
isMobile = true;
}
IFrameHelper.sendMessage('toggle-close-button', { isMobile });
},
};