4 const chatWebsiteAddress = new URL('{{{chatWebsiteAddressOrigin}}}');
5 if (chatWebsiteAddress.origin !== window.location.origin){
6 throw new Error(`Domain "${window.location.origin}"" can't load snippet for '{{{chatWebsiteAddressOrigin}}}'. Please check your website domain in the current XCALLY Chat Website settings.`);
9 console.warn(`Domain ${window.location.origin} can't load snippet for '{{{chatWebsiteAddressOrigin}}}'. Please check your website domain in the current XCALLY Chat Website settings.`);
14 const remoteURL = new URL('{{{remote}}}');
15 const chatOrigin = remoteURL.origin;
16 const chatPath = '/snippet/';
17 const chatStylesPath = chatPath + 'styles/';
18 const chatVersion = '{{{chatVersion}}}';
21 const divColor = '<%=div_color%>';
22 const textColor = '<%=text_color%>';
23 const buttonColor = '<%=button_color%>';
24 const backgroungColor = '<%=background_color%>';
25 let alignment = "<%=alignment%>";
26 let verticalAlignment = "<%=verticalAlignment%>";
28 // iframe URL settings
29 const iframeId = 'motion-chat-iframe';
30 const iframeSrcURL = new URL(chatPath, chatOrigin);
31 const iframeSearchParams = new URLSearchParams('{{{query}}}');
32 iframeSearchParams.append('version', chatVersion);
33 iframeSearchParams.append('location', btoa(window.location.host));
34 iframeSrcURL.search = iframeSearchParams;
37 const linkURL = new URL(chatStylesPath + 'mobile.css', chatOrigin);
38 linkURL.search = new URLSearchParams({ version: chatVersion });
39 const linkMobile = document.createElement('link');
40 linkMobile.type = "text/css";
41 linkMobile.rel='stylesheet';
42 linkMobile.href = linkURL.toString();
44 // Iframe localstorage whitelisting
45 const allowedOrigins = [chatOrigin];
47 function remoteLocalStorageEventHandler(event) {
48 if (allowedOrigins.includes(event.origin)) {
49 const { action, key, value } = event.data;
50 const localStorage = window.localStorage;
53 localStorage.setItem(key, JSON.stringify(value))
54 event.source.postMessage(
55 { action: 'setItemResult', key },
61 let item = localStorage.getItem(key);
64 item = JSON.parse(item);
66 console.error('Cannot read data from localstorage', error);
69 event.source.postMessage(
70 { action: 'getItemResult', key, item },
76 localStorage.removeItem(key);
77 event.source.postMessage(
78 { action: 'removeItemResult', key },
84 typeof action === 'string' && console.debug('Unsupported action', action);
91 let iframe = document.createElement('iframe');
93 iframe['id'] = iframeId;
94 iframe['src'] = iframeSrcURL.toString()
96 let iframe_status = false;
98 document.documentElement.style.setProperty('--xc-ws-div-color', divColor);
99 document.documentElement.style.setProperty('--xc-ws-text-color', textColor);
100 document.documentElement.style.setProperty('--xc-ws-button-color', buttonColor);
101 document.documentElement.style.setProperty('--xc-ws-background-color', backgroungColor);
103 document.head.appendChild(linkMobile);
104 document.body.appendChild(iframe);
106 <% if (alignment == 'bottom_right') { -%>
108 iframe.className = 'motion-chat-iframe-bottom_right';
109 verticalAlignment = 0;
110 <% } else if (alignment == 'right') { -%>
112 iframe.className = 'motion-chat-iframe-right';
113 iframe.style['top'] = verticalAlignment+'%';
114 let iframe_h = topIframe_calc();
115 topIframe_set(iframe_h);
116 let div_tab = document.createElement('div');
117 div_tab['id'] = 'motion-chat-iframe-tab';
118 div_tab.className = 'motion-chat-div-right';
120 <% } else if (alignment == 'left') { -%>
122 iframe.className = 'motion-chat-iframe-left';
123 iframe.style['top'] = verticalAlignment+'%';
124 let iframe_h = topIframe_calc();
125 topIframe_set(iframe_h);
126 let div_tab = document.createElement('div');
127 div_tab.className = 'motion-chat-div-left';
128 div_tab['id'] ='motion-chat-iframe-tab';
132 <% if (alignment == 'right') { -%>
134 topChat_set(iframe_h, verticalAlignment);
135 document.body.appendChild(div_tab);
136 let html = '<div id="chat_tab_arrow"> <strong><</strong> </div> <span id="chat_tab_text" style="writing-mode: tb-rl; transform: rotate(-180deg);" flex><strong><%=labelText%></strong></span>';
137 div_tab.innerHTML = html;
139 div_tab.style.backgroundColor = divColor;
140 document.getElementById("chat_tab_text").style.color = textColor;
141 document.getElementById("chat_tab_arrow").style.color = divColor;
142 document.getElementById("chat_tab_arrow").style.backgroundColor = textColor;
143 document.getElementById("motion-chat-iframe-tab").style.display = "flex";
145 function appendLink(){
146 if(iframe_status == false){
147 document.body.appendChild(iframe);
152 function expandChatRight(){
154 div_tab.style.right = '295px';
155 iframe.style.right = '0px';
156 document.getElementById("chat_tab_arrow").innerHTML = "<strong> > </strong>";
157 let iframeEl = document.getElementById('motion-chat-iframe');
158 iframeEl.contentWindow?.postMessage({"evt":"show"}, '*');
161 function collapseChatRight(){
163 div_tab.style.right = '0px';
164 iframe.style.right = '-312px';
165 document.getElementById("chat_tab_arrow").innerHTML = "<strong> < </strong>";
166 let iframeEl = document.getElementById('motion-chat-iframe');
167 iframeEl.contentWindow?.postMessage({"evt":"hide"}, '*');
170 function toggleChatExpandedRight(){
171 if (tab_status % 2 === 0) {
180 document.getElementById("motion-chat-iframe-tab").addEventListener("click", toggleChatExpandedRight);
181 <% } else if (alignment == 'left') { -%>
183 topChat_set(iframe_h, verticalAlignment);
184 document.body.appendChild(div_tab);
185 let html='<div id="chat_tab_arrow"> <strong>></strong> </div><span id="chat_tab_text" style="writing-mode: tb-rl; transform: rotate(-180deg);" flex><strong><%=labelText%></strong></span>';
186 div_tab.innerHTML = html;
188 div_tab.style.backgroundColor = divColor;
189 document.getElementById("chat_tab_text").style.color = textColor;
190 document.getElementById("chat_tab_arrow").style.color = divColor;
191 document.getElementById("chat_tab_arrow").style.backgroundColor = textColor;
192 document.getElementById("motion-chat-iframe-tab").style.display="flex";
194 function appendLink() {
195 if (iframe_status == false){
196 document.body.appendChild(iframe);
201 function expandChatLeft() {
203 div_tab.style.left = '295px';
204 iframe.style.left = '0px';
205 document.getElementById("chat_tab_arrow").innerHTML = "<strong> < </strong>";
206 let iframeEl = document.getElementById('motion-chat-iframe');
207 iframeEl.contentWindow?.postMessage({"evt":"show"}, '*');
210 function collapseChatLeft() {
212 div_tab.style.left = '0px';
213 iframe.style.left = '-312px';
214 document.getElementById("chat_tab_arrow").innerHTML = "<strong> > </strong>";
215 let iframeEl = document.getElementById('motion-chat-iframe');
216 iframeEl.contentWindow?.postMessage({"evt":"hide"}, '*');
219 function toggleChatExpandedLeft() {
220 if (tab_status % 2 === 0) {
229 document.getElementById("motion-chat-iframe-tab").addEventListener("click", toggleChatExpandedLeft);
232 // START Events management
233 window.addEventListener(
236 remoteLocalStorageEventHandler(evt)
237 switch (evt.data.cmd) {
239 <% if (alignment == 'bottom_right') { -%>
241 iframe.style.top = 'auto';
242 iframe.style.bottom = '0px';
243 <% } else if (alignment == 'right') { -%>
245 iframe.style.right = '0px';
246 div_tab.style.right = '295px';
247 <% } else if (alignment == 'left') { -%>
249 iframe.style.left = '0px';
250 div_tab.style.left = '295px';
254 <% if (alignment == 'bottom_right') { -%>
256 iframe.style.top = 'calc(100% - 50px)';
257 <% } else if (alignment == 'right') { -%>
259 iframe.style.right = '-312px';
260 div_tab.style['right'] = '0px';
261 <% } else if (alignment == 'left') { -%>
263 iframe.style.left = '-312px';
264 div_tab.style.left = '0px';
268 <% if (alignment == 'right' || alignment == 'left') { -%>
270 div_tab.style.backgroundColor = divColor;
271 document.getElementById("chat_tab_text").style.color = textColor;
272 document.getElementById("chat_tab_arrow").style.color = divColor;
273 document.getElementById("chat_tab_arrow").style.backgroundColor = textColor;
274 document.getElementById("motion-chat-iframe-tab").style.display = "flex";
278 <% if (alignment == 'right' || alignment == 'left') { -%>
280 document.getElementById("motion-chat-iframe-tab").style.display = "none";
288 // END Events management
290 // START Proactive action management
291 <% proactiveActions.forEach(function(action, index) { -%>
292 <% if (action.type == 'timeout') { -%>
293 setTimeout(function() {
294 <% if (alignment == 'right') { -%>
297 <% } else if (alignment == 'left') { -%>
301 iframe.style.bottom = '0px';
302 iframe.contentWindow?.postMessage({
306 }, <%- action.timeout %> * 1000);
308 <% if (action.type == 'mouseOver') { -%>
309 let elements<%- index %> = document.querySelectorAll("<%- action.selector %>");
310 for (let i = 0; i < elements<%- index %>.length; i++) {
311 elements<%- index %>[i].onmouseover = function() {
312 <% if (alignment == 'right') { -%>
315 <% } else if (alignment == 'left') { -%>
319 iframe.style.bottom = '0px';
320 iframe.contentWindow?.postMessage({
327 // END Proactive action management
329 if (window.DeviceOrientationEvent) {
330 window.addEventListener(
333 if (alignment == 'right') {
334 document.getElementById("chat_tab_arrow").innerHTML = "<strong> < </strong>";
335 let iframeEl = document.getElementById('motion-chat-iframe');
336 iframeEl.contentWindow?.postMessage({"evt":"hide"}, '*');
338 iframe_h = topIframe_calc();
339 topIframe_set(iframe_h);
340 if (typeof div_tab != "undefined") {
341 topChat_set(iframe_h, verticalAlignment);
344 else if (alignment == 'left') {
345 document.getElementById("chat_tab_arrow").innerHTML = "<strong> > </strong>";
346 let iframeEl = document.getElementById('motion-chat-iframe');
347 iframeEl.contentWindow?.postMessage({"evt":"hide"}, '*');
349 iframe_h = topIframe_calc();
350 topIframe_set(iframe_h);
351 if (typeof div_tab != "undefined") {
352 topChat_set(iframe_h, verticalAlignment);
360 window.addEventListener(
363 let iframe_h = topIframe_calc();
364 topIframe_set(iframe_h);
365 if(typeof div_tab != "undefined") {
366 topChat_set(iframe_h, verticalAlignment);
371 function topIframe_calc(){
373 let heightD = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
374 let iframeT = ((heightD/100)*verticalAlignment) + 450;
375 if (heightD < iframeT) {
376 height_iframe = 450 - (iframeT - heightD);
381 return height_iframe;
384 function topIframe_set(height_iframe) {
385 if (height_iframe > 340) {
386 iframe.style['height'] = height_iframe +'px';
387 if (alignment == "right" || alignment == "left") {
388 iframe.style['top'] = verticalAlignment + "%";
391 iframe.style['bottom'] = "0%";
395 iframe.style['height'] = '340px';
396 if (alignment == "right" || alignment == "left") {
397 iframe.style['top'] = "calc(100% - 340px)";
400 iframe.style['bottom'] = "0%";
405 function topChat_set(height_iframe, verticalAlignment) {
406 if (height_iframe > 340) {
407 div_tab.style['top'] = "calc("+ verticalAlignment +"% + " + (height_iframe - 100) + "px)";
410 div_tab.style['top'] = "auto";
411 div_tab.style['bottom'] = "0px";
416 <% if (hideWhenOffline && intervalId != null) { -%>
418 document.getElementById("motion-chat-iframe-tab").style.display = "none";