Built motion from commit 20b39a97.|2.6.29
[motion2.git] / server / files / chat / iframe.ejs
1 (function() {
2   'use strict';
3   try {
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.`);
7     }
8   } catch (error) {
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.`);
10     return;
11   }
12
13   // Init all URLs
14   const remoteURL = new URL('{{{remote}}}');
15   const chatOrigin = remoteURL.origin;
16   const chatPath = '/snippet/';
17   const chatStylesPath = chatPath + 'styles/';
18   const chatVersion = '{{{chatVersion}}}';
19
20   // Style setttings
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%>";
27
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;
35
36   // Style URL settings
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();
43
44   // Iframe localstorage whitelisting
45   const allowedOrigins = [chatOrigin];
46
47   function remoteLocalStorageEventHandler(event) {
48     if (allowedOrigins.includes(event.origin)) {
49       const { action, key, value } = event.data;
50       const localStorage = window.localStorage;
51       switch(action) {
52         case 'setItem': {
53             localStorage.setItem(key, JSON.stringify(value))
54             event.source.postMessage(
55               { action: 'setItemResult', key },
56               event.origin
57             );
58             break;
59           }
60         case 'getItem': {
61           let item = localStorage.getItem(key);
62           if (item) {
63             try {
64               item = JSON.parse(item);
65             } catch (error) {
66               console.error('Cannot read data from localstorage', error);
67             }
68           }
69           event.source.postMessage(
70             { action: 'getItemResult', key, item },
71             event.origin
72           );
73           break;
74         }
75         case 'removeItem': {
76           localStorage.removeItem(key);
77           event.source.postMessage(
78             { action: 'removeItemResult', key },
79             event.origin
80           );
81           break;
82         }
83         default:
84           typeof action === 'string' && console.debug('Unsupported action', action);
85         break;
86       }
87     }
88   }
89
90   // DOM Manipulation
91   let iframe = document.createElement('iframe');
92   // Attributes
93   iframe['id'] = iframeId;
94   iframe['src'] = iframeSrcURL.toString()
95
96   let  iframe_status = false;
97
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);
102
103   document.head.appendChild(linkMobile);
104   document.body.appendChild(iframe);
105
106   <% if (alignment == 'bottom_right') { -%>
107     // Bottom, right
108     iframe.className = 'motion-chat-iframe-bottom_right';
109     verticalAlignment = 0;
110   <% } else if (alignment == 'right') { -%>
111     // 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';
119     let  tab_status=0;
120   <% } else if (alignment == 'left') { -%>
121     // 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';
129     let tab_status=0;
130   <% } -%>   
131
132   <% if (alignment == 'right') { -%>
133     // 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;
138     
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";
144     
145     function appendLink(){
146       if(iframe_status == false){
147         document.body.appendChild(iframe);
148         iframe_status=true;
149       }
150     }
151
152     function expandChatRight(){
153       appendLink();
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"}, '*');
159     }
160
161     function collapseChatRight(){
162       appendLink();
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"}, '*');
168     }
169
170     function toggleChatExpandedRight(){    
171       if (tab_status % 2 === 0) {
172         expandChatRight();
173       }
174       else {
175         collapseChatRight();
176       }
177       tab_status++;
178     }
179
180     document.getElementById("motion-chat-iframe-tab").addEventListener("click", toggleChatExpandedRight);
181   <% } else if (alignment == 'left') { -%> 
182     // 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;
187
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";
193
194     function appendLink() {
195       if (iframe_status == false){
196         document.body.appendChild(iframe);
197         iframe_status=true;
198       }
199     }
200
201     function expandChatLeft() {
202       appendLink();
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"}, '*');
208     }
209
210     function collapseChatLeft() {
211       appendLink();
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"}, '*');
217     }
218
219     function toggleChatExpandedLeft() {
220       if (tab_status % 2 === 0) {
221         expandChatLeft();
222       }
223       else {
224         collapseChatLeft();
225       }
226       tab_status++;
227     }
228
229     document.getElementById("motion-chat-iframe-tab").addEventListener("click", toggleChatExpandedLeft); 
230   <% } -%>
231
232   // START Events management
233   window.addEventListener(
234     'message',
235     function(evt) {
236       remoteLocalStorageEventHandler(evt)
237       switch (evt.data.cmd) {
238         case 'show':
239           <% if (alignment == 'bottom_right') { -%>
240             // Bottom, right
241             iframe.style.top = 'auto';
242             iframe.style.bottom = '0px';
243           <% } else if (alignment == 'right') { -%>
244             // Right
245             iframe.style.right = '0px';
246             div_tab.style.right = '295px';
247           <% } else if (alignment == 'left') { -%>
248             // Left
249             iframe.style.left = '0px';
250             div_tab.style.left = '295px';
251           <% } -%>
252           break;
253         case 'hide':
254           <% if (alignment == 'bottom_right') { -%>
255             // Bottom, right
256             iframe.style.top = 'calc(100% - 50px)';
257           <% } else if (alignment == 'right') { -%>
258             // Right
259             iframe.style.right = '-312px';
260             div_tab.style['right'] = '0px';
261           <% } else if (alignment == 'left') { -%>
262             // Left
263             iframe.style.left = '-312px';
264             div_tab.style.left = '0px';
265           <% } -%>
266           break;
267         case "init": 
268           <% if (alignment == 'right' || alignment == 'left') { -%>
269             // Bottom, right
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";
275           <% } -%>
276           break;
277         case "offline": 
278           <% if (alignment == 'right' || alignment == 'left') { -%>
279             // Bottom, right
280             document.getElementById("motion-chat-iframe-tab").style.display = "none";
281           <% } -%>
282           break;
283         default:
284       }
285     },
286     false
287   );
288   // END Events management
289
290   // START Proactive action management
291   <% proactiveActions.forEach(function(action, index) { -%>
292     <% if (action.type == 'timeout') { -%>        
293     setTimeout(function() {
294       <% if (alignment == 'right') { -%>
295         expandChatRight();
296         tab_status++;
297       <% } else if (alignment == 'left') { -%> 
298         expandChatLeft();
299         tab_status++;
300       <% } else { -%> 
301         iframe.style.bottom = '0px';
302         iframe.contentWindow?.postMessage({
303             evt: 'show'
304         }, '*');
305       <% } -%> 
306     }, <%- action.timeout %> * 1000);
307   <% } -%>
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') { -%>
313         expandChatRight();
314         tab_status++;
315       <% } else if (alignment == 'left') { -%> 
316         expandChatLeft();
317         tab_status++;
318       <% } else { -%> 
319         iframe.style.bottom = '0px';
320         iframe.contentWindow?.postMessage({
321             evt: 'show'
322         }, '*');
323       <% } -%> 
324     }
325   }
326   <% } -%>    <% }); -%>
327   // END Proactive action management
328
329   if (window.DeviceOrientationEvent) {
330     window.addEventListener(
331       'orientationchange',
332       function() {
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"}, '*');
337           tab_status = 0;
338           iframe_h = topIframe_calc();
339           topIframe_set(iframe_h);
340           if (typeof div_tab != "undefined") {
341             topChat_set(iframe_h, verticalAlignment);
342           }
343         }
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"}, '*');
348           tab_status = 0;
349           iframe_h = topIframe_calc();
350           topIframe_set(iframe_h);
351           if (typeof div_tab != "undefined") {
352             topChat_set(iframe_h, verticalAlignment);
353           }
354         }
355       },
356       false
357     );
358   }
359
360   window.addEventListener(
361     "resize",
362     function(event) {
363       let iframe_h = topIframe_calc();
364       topIframe_set(iframe_h);
365       if(typeof div_tab != "undefined") {
366         topChat_set(iframe_h, verticalAlignment);
367       }
368     }
369   );
370
371   function topIframe_calc(){
372     let height_iframe
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);
377     }
378     else {
379       height_iframe = 450;
380     }
381     return height_iframe;
382   }
383
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 + "%";
389       }
390       else {
391         iframe.style['bottom'] = "0%";
392       }
393     }
394     else {
395       iframe.style['height'] = '340px';
396       if (alignment == "right" || alignment == "left") {
397         iframe.style['top'] = "calc(100% - 340px)";
398       }
399       else {
400         iframe.style['bottom'] = "0%";
401       }
402     }
403   }
404
405   function topChat_set(height_iframe, verticalAlignment) {
406     if (height_iframe > 340) {
407         div_tab.style['top'] = "calc("+ verticalAlignment +"% + " + (height_iframe - 100) + "px)";
408     }
409     else {
410       div_tab.style['top'] = "auto";
411       div_tab.style['bottom'] = "0px";
412     }
413   }
414
415   // hide chat
416   <% if (hideWhenOffline && intervalId != null) { -%>
417     // hide template
418     document.getElementById("motion-chat-iframe-tab").style.display = "none";
419   <% } -%>
420 }());