Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / server / files / chat / iframe.ejs
1 (function() {
2     'use strict';
3     const chatWebsiteAddressOrigin = '{{{chatWebsiteAddressOrigin}}}'
4     if(chatWebsiteAddressOrigin !== window.location.origin){
5         alert(`The current location does not match ${chatWebsiteAddressOrigin}. Please check your website domain in the current XCALLY Chat Website settings.`)
6     }
7     else
8     {
9         // Init all URLs
10         const remoteURL = new URL('{{{remote}}}')
11         const chatOrigin = remoteURL.origin
12         const chatPath = '/snippet/'
13         const chatStylesPath = chatPath + 'styles/'
14         const chatVersion = '{{{chatVersion}}}'
15
16         // Style setttings
17         const divColor = '<%=div_color%>'
18         const textColor = '<%=text_color%>'
19         const buttonColor = '<%=button_color%>'
20         const backgroungColor = '<%=background_color%>'
21         let alignment = "<%=alignment%>";
22         let verticalAlignment = "<%=verticalAlignment%>";
23
24         // iframe URL settings
25         const iframeId = 'motion-chat-iframe'
26         const iframeSrcURL = new URL(chatPath, chatOrigin)
27         const iframeSearchParams = new URLSearchParams('{{{query}}}')
28         iframeSearchParams.append('version', chatVersion)
29         iframeSearchParams.append('location', btoa(window.location.host))
30         iframeSrcURL.search = iframeSearchParams
31
32         // Style URL settings
33         const linkURL =  new URL(chatStylesPath + 'mobile.css', chatOrigin)
34         linkURL.search = new URLSearchParams({ version: chatVersion })
35         const linkMobile = document.createElement('link');
36         linkMobile.type = "text/css";
37         linkMobile.rel='stylesheet';
38         linkMobile.href = linkURL.toString()
39
40         // Iframe localstorage whitelisting
41         const allowedOrigins = [chatOrigin]
42
43         function remoteLocalStorageEventHandler(event){
44             if (allowedOrigins.includes(event.origin)) {
45                 const { action, key, value } = event.data
46                 const localStorage = window.localStorage
47                 switch(action){
48                     case 'setItem':
49                         {
50                             localStorage.setItem(key, JSON.stringify(value))
51                             event.source.postMessage(
52                                 {
53                                 action: 'setItemResult',
54                                 key
55                                 }, event.origin)
56                         }
57                         break
58                     case 'getItem':
59                         {
60                             let item = localStorage.getItem(key)
61                             if(item){
62                                 try {
63                                     item = JSON.parse(item)
64                                 } catch (error) {
65                                     console.error('Cannot read data from localstorage', error)
66                                 }
67                             }
68                             event.source.postMessage(
69                                 {
70                                 action: 'getItemResult',
71                                 key,
72                                 item
73                                 }, event.origin)
74                         }
75                         break
76                     case 'removeItem':
77                         {   
78                             localStorage.removeItem(key)
79                             event.source.postMessage(
80                                 {
81                                 action: 'removeItemResult',
82                                 key
83                                 }, event.origin)
84                         }
85                         break
86                     default:
87                         typeof action === 'string' && console.debug('Unsupported action', action)
88                     break;
89                 }
90             }
91         }
92
93         // DOM Manipulation
94         let iframe = document.createElement('iframe');
95         // Attributes
96         iframe['id'] = iframeId;
97         iframe['src'] = iframeSrcURL.toString()
98
99         let  iframe_status = false;
100
101         document.documentElement.style.setProperty('--xc-ws-div-color', divColor);
102         document.documentElement.style.setProperty('--xc-ws-text-color', textColor);
103         document.documentElement.style.setProperty('--xc-ws-button-color', buttonColor);
104         document.documentElement.style.setProperty('--xc-ws-background-color', backgroungColor);
105     
106         document.head.appendChild(linkMobile);
107
108         <% if (alignment == 'bottom_right') { -%> // Bottom, right
109             iframe.className = 'motion-chat-iframe-bottom_right';
110             verticalAlignment = 0;
111             document.body.appendChild(iframe);
112
113         <% } else if (alignment == 'right') { -%> // Right
114             iframe.className = 'motion-chat-iframe-right';
115             iframe.style['top'] = verticalAlignment+'%';
116             let  iframe_h = topIframe_calc();
117             topIframe_set(iframe_h);
118             let  div_tab = document.createElement('div');
119             div_tab['id'] = 'motion-chat-iframe-tab';
120             div_tab.className = 'motion-chat-div-right';
121             let  tab_status=0;
122
123         <% } else if (alignment == 'left') { -%> // Left   
124             iframe.className = 'motion-chat-iframe-left';
125             iframe.style['top'] = verticalAlignment+'%';
126             let  iframe_h = topIframe_calc();
127             topIframe_set(iframe_h);
128             let  div_tab = document.createElement('div');
129             div_tab.className = 'motion-chat-div-left';
130             div_tab['id'] ='motion-chat-iframe-tab';
131             let  tab_status=0;
132
133         <% } -%>   
134
135         <% if (alignment == 'right') { -%> // Right
136             topChat_set(iframe_h, verticalAlignment);
137             document.body.appendChild(div_tab);
138             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>';
139             div_tab.innerHTML = html;
140             
141             div_tab.style.backgroundColor = divColor;
142             document.getElementById("chat_tab_text").style.color = textColor; 
143             document.getElementById("chat_tab_arrow").style.color = divColor 
144             document.getElementById("chat_tab_arrow").style.backgroundColor = textColor; 
145             document.getElementById("motion-chat-iframe-tab").style.display = "flex";
146             
147             function appendLink(){
148                 if(iframe_status == false){
149                     document.body.appendChild(iframe);
150                     iframe_status=true;
151                 }      
152             }
153
154             function expandChatRight(){
155                 appendLink()
156                 div_tab.style.right = '295px';
157                 iframe.style.right = '0px';
158                 document.getElementById("chat_tab_arrow").innerHTML = "<strong> > </strong>";
159                 let iframeEl = document.getElementById('motion-chat-iframe');
160                 iframeEl.contentWindow?.postMessage({"evt":"show"}, '*');
161             }
162
163             function collapseChatRight(){
164                 appendLink()
165                 div_tab.style.right = '0px';
166                 iframe.style.right = '-312px';
167                 document.getElementById("chat_tab_arrow").innerHTML = "<strong> < </strong>";
168                 let iframeEl = document.getElementById('motion-chat-iframe');
169                 iframeEl.contentWindow?.postMessage({"evt":"hide"}, '*');
170             }
171
172             function toggleChatExpandedRight(){    
173                 if(tab_status % 2 === 0) {
174                     expandChatRight()
175                 }
176                 else {
177                     collapseChatRight()
178                 }
179                 tab_status++;
180             }
181
182             document.getElementById("motion-chat-iframe-tab").addEventListener("click", toggleChatExpandedRight);
183         <% } else if (alignment == 'left') { -%> 
184             topChat_set(iframe_h, verticalAlignment);
185             document.body.appendChild(div_tab);
186             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>';
187             div_tab.innerHTML=html;
188
189             div_tab.style.backgroundColor = divColor;
190             document.getElementById("chat_tab_text").style.color = textColor; 
191             document.getElementById("chat_tab_arrow").style.color = divColor; 
192             document.getElementById("chat_tab_arrow").style.backgroundColor = textColor; 
193             document.getElementById("motion-chat-iframe-tab").style.display="flex";
194
195             function appendLink(){
196                 if(iframe_status == false){
197                     document.body.appendChild(iframe);
198                     iframe_status=true;
199                 }   
200             }
201
202             function expandChatLeft(){
203                 appendLink()
204                 div_tab.style.left = '295px';
205                 iframe.style.left = '0px';
206                 document.getElementById("chat_tab_arrow").innerHTML = "<strong> < </strong>";
207                 let iframeEl = document.getElementById('motion-chat-iframe');
208                 iframeEl.contentWindow?.postMessage({"evt":"show"}, '*');
209             }
210
211             function collapseChatLeft(){
212                 appendLink()
213                 div_tab.style.left = '0px';
214                 iframe.style.left = '-312px';
215                 document.getElementById("chat_tab_arrow").innerHTML = "<strong> > </strong>";
216                 let iframeEl = document.getElementById('motion-chat-iframe');
217                 iframeEl.contentWindow?.postMessage({"evt":"hide"}, '*');
218             }
219
220             function toggleChatExpandedLeft(){
221                 if(tab_status % 2 === 0) {
222                     expandChatLeft()
223                 }   
224                 else {
225                     collapseChatLeft()
226                 }   
227                 tab_status++;
228             }
229
230             document.getElementById("motion-chat-iframe-tab").addEventListener("click", toggleChatExpandedLeft); 
231
232             <% } -%>    
233
234         // START Events management
235         window.addEventListener('message', function(evt) {
236             remoteLocalStorageEventHandler(evt)
237             switch (evt.data.cmd) {
238                 case 'show':
239                     <% if (alignment == 'bottom_right') { -%> // Bottom, right
240                         iframe.style.top = 'auto';
241                         iframe.style.bottom = '0px';
242                     <% } else if (alignment == 'right') { -%> // Right
243                         iframe.style.right = '0px';
244                         div_tab.style.right = '295px';
245                     <% } else if (alignment == 'left') { -%> // Left
246                         iframe.style.left = '0px';
247                         div_tab.style.left = '295px';
248                     // Left    
249                     <% } -%>                break;
250                 case 'hide':
251                     <% if (alignment == 'bottom_right') { -%> // Bottom, right
252                     iframe.style.top = 'calc(100% - 50px)';
253                     <% } else if (alignment == 'right') { -%> // Right
254                         iframe.style.right = '-312px';
255                         div_tab.style['right'] = '0px';
256                     <% } else if (alignment == 'left') { -%> // Left
257                         iframe.style.left = '-312px';
258                         div_tab.style.left = '0px';
259                     <% } -%>                break;
260                 case "init": 
261                     <% if (alignment == 'right' || alignment == 'left') { -%> // Bottom, right
262                         div_tab.style.backgroundColor = divColor;
263                         document.getElementById("chat_tab_text").style.color = textColor; 
264                         document.getElementById("chat_tab_arrow").style.color = divColor; 
265                         document.getElementById("chat_tab_arrow").style.backgroundColor = textColor; 
266                         document.getElementById("motion-chat-iframe-tab").style.display = "flex";
267                     <% } -%>                break;
268                 case "offline": 
269                     <% if (alignment == 'right' || alignment == 'left') { -%> // Bottom, right
270                         document.getElementById("motion-chat-iframe-tab").style.display = "none";
271                     <% } -%>                break;
272                 default:
273             }
274
275         }, false);
276         // END Events management
277
278         // START Proactive action management
279         <% proactiveActions.forEach(function(action, index) { -%>
280             <% if (action.type == 'timeout') { -%>        
281             setTimeout(function() {
282                 <% if (alignment == 'right') { -%>
283                 expandChatRight();
284                 tab_status++;
285                 <% } else if (alignment == 'left') { -%> 
286                 expandChatLeft();
287                 tab_status++;
288                 <% } else { -%> 
289                 iframe.style.bottom = '0px';
290                 iframe.contentWindow?.postMessage({
291                     evt: 'show'
292                 }, '*');
293                 <% } -%> 
294             }, <%- action.timeout %> * 1000);
295         <% } -%>
296         <% if (action.type == 'mouseOver') { -%>
297         let  elements<%- index %> = document.querySelectorAll("<%- action.selector %>");
298         for (let  i = 0; i < elements<%- index %>.length; i++) {
299             elements<%- index %>[i].onmouseover = function() {
300                 <% if (alignment == 'right') { -%>
301                 expandChatRight();
302                 tab_status++;
303                 <% } else if (alignment == 'left') { -%> 
304                 expandChatLeft();
305                 tab_status++;
306                 <% } else { -%> 
307                 iframe.style.bottom = '0px';
308                 iframe.contentWindow?.postMessage({
309                     evt: 'show'
310                 }, '*');
311                 <% } -%> 
312             }
313         }
314         <% } -%>    <% }); -%>
315         // END Proactive action management
316         
317
318         if (window.DeviceOrientationEvent) {
319             window.addEventListener('orientationchange', function() {
320             if (alignment == 'right'){
321                 document.getElementById("chat_tab_arrow").innerHTML = "<strong> < </strong>";
322                 let  iframeEl = document.getElementById('motion-chat-iframe');
323                 iframeEl.contentWindow?.postMessage({"evt":"hide"}, '*');
324                 tab_status = 0;
325                 iframe_h = topIframe_calc();
326                 topIframe_set(iframe_h);
327                 if(typeof div_tab != "undefined") topChat_set(iframe_h, verticalAlignment);
328             }
329             else if (alignment == 'left'){
330                 document.getElementById("chat_tab_arrow").innerHTML = "<strong> > </strong>";
331                 let  iframeEl = document.getElementById('motion-chat-iframe');
332                 iframeEl.contentWindow?.postMessage({"evt":"hide"}, '*');
333                 tab_status = 0;
334                 iframe_h = topIframe_calc();
335                 topIframe_set(iframe_h);
336                 if(typeof div_tab != "undefined") topChat_set(iframe_h, verticalAlignment);
337             } }, false);
338         }
339
340         window.addEventListener("resize", function(event) {
341         let  iframe_h = topIframe_calc();
342         topIframe_set(iframe_h);
343         if(typeof div_tab != "undefined") topChat_set(iframe_h, verticalAlignment);
344         });
345
346         function topIframe_calc(){
347         let height_iframe
348         let  heightD = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
349         let  iframeT = ((heightD/100)*verticalAlignment) + 450;
350         if (heightD < iframeT) {
351             height_iframe = 450 - (iframeT - heightD);
352         }
353         else { height_iframe = 450; }
354         return height_iframe;
355         }
356
357         function topIframe_set(height_iframe){
358             if( height_iframe > 340){
359             iframe.style['height'] = height_iframe +'px';
360             if (alignment == "right" || alignment == "left" )
361             { iframe.style['top'] = verticalAlignment + "%"; }
362             else{ iframe.style['bottom'] = "0%"; }
363
364             }
365             else {
366             iframe.style['height'] = '340px';
367             if (alignment == "right" || alignment == "left" )
368             { iframe.style['top'] = "calc(100% - 340px)"; }
369             else{ iframe.style['bottom'] = "0%"; }
370
371             }
372         }
373     
374         function topChat_set(height_iframe, verticalAlignment){
375     
376         if( height_iframe > 340){
377             div_tab.style['top'] = "calc("+ verticalAlignment +"% + " + (height_iframe - 100) + "px)";
378         }
379         else {
380             div_tab.style['top'] = "auto";
381             div_tab.style['bottom'] = "0px";
382         }
383         }
384
385         // hide chat
386         <% if (hideWhenOffline && intervalId != null) { -%> // hide template
387             document.getElementById("motion-chat-iframe-tab").style.display = "none";
388         <% } -%>
389     }
390 }());