Mercurial > libervia-templates
comparison default/static/websocket.js @ 84:b2ef34e602cf
base, js (websocket), css (main style): dynamic pages implementation, first draft:
this patch introduces the browser part of dynamic pages.
Dynamic pages work by establishing a websocket between server and the current page, if requested by server (which means that needed arguments are present in template).
Once the connection is established, the server can, for now, reload the page, append HTML elements, or receive arbitrary data (without reloading the page, in opposition to data post).
If connection can't be established, a popup will be displayed and connection will be retried many times after variable timeouts.
The browser will finally give up and display an alert to client if the number of retries is too high (20 for now).
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 03 Jan 2018 01:12:16 +0100 |
parents | |
children | 27d6453a6209 |
comparison
equal
deleted
inserted
replaced
83:caab77328b1c | 84:b2ef34e602cf |
---|---|
1 /* | |
2 SàT templates: suit of templates for Salut à Toi | |
3 Copyright (C) 2017 Jérôme Poisson (goffi@goffi.org) | |
4 | |
5 This program is free software: you can redistribute it and/or modify | |
6 it under the terms of the GNU Affero General Public License as published by | |
7 the Free Software Foundation, either version 3 of the License, or | |
8 (at your option) any later version. | |
9 | |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU Affero General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Affero General Public License | |
16 along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 */ | |
18 | |
19 /* websocket handler */ | |
20 | |
21 | |
22 //TODO: retry websocket instead of reload | |
23 function WSHandler(url, token, debug=false) { | |
24 var socket = new WebSocket(url, 'libervia_page_' + token ); | |
25 var retried = 0; | |
26 | |
27 var errorHandler = function(error) { | |
28 if (retried > 20) { | |
29 console.error("Too many tries, can't start websocket"); | |
30 alert("Dynamic connection with server can't be established, please try to reload this page in a while or contact your service administrator"); | |
31 return; | |
32 } | |
33 var delay = Math.floor((Math.random() * 10) + 1) + 30 * Math.min(retried, 6); | |
34 notifyRetry(delay, function() { | |
35 retried++; | |
36 socket = new WebSocket(url, 'libervia_page_' + token ); | |
37 socket.addEventListener('error', errorHandler); | |
38 }); | |
39 }; | |
40 | |
41 socket.addEventListener('error', errorHandler); | |
42 | |
43 if (debug) { | |
44 socket.addEventListener('message', function(event) { | |
45 console.log('WS in <== ', JSON.parse(event.data)); | |
46 }); | |
47 } | |
48 | |
49 socket.addEventListener('message', function(event) { | |
50 try {data = JSON.parse(event.data);} | |
51 catch (e) { | |
52 console.warn('invalid websocket message received: %s', e); | |
53 return; | |
54 } | |
55 switch (data.type) { | |
56 case 'reload': | |
57 location.reload(true); | |
58 break; | |
59 case 'dom': | |
60 selected_element = document.body.querySelector(data.selectors); | |
61 switch (data.update_type) { | |
62 case 'append': | |
63 var template = document.createElement('template'); | |
64 template.innerHTML = data.html; | |
65 new_element = template.content.firstChild; | |
66 selected_element.appendChild(new_element); | |
67 break; | |
68 default: | |
69 console.warn('Unknown DOM update type: %s', data.update_type); | |
70 } | |
71 break; | |
72 default: | |
73 console.warn('Unknown data type: %s', data.type); | |
74 } | |
75 }); | |
76 | |
77 socket.addEventListener('open', function (event) { | |
78 console.log('Websocket opened'); | |
79 retried = 0; | |
80 }.bind(this)); | |
81 | |
82 this.send = function(data) { | |
83 if (debug) { | |
84 console.log('WS out ==> ', data); | |
85 } | |
86 socket.send(JSON.stringify(data)); | |
87 }; | |
88 | |
89 function notifyRetry(timeout, retryCb) { | |
90 /* Show a notification dialog informing the user that server can't be reach | |
91 * and call retryCb after timeout seconds. | |
92 * A "retry now" link allows to retry immediately" | |
93 * | |
94 * @param timeout(int): delay before retrying, in seconds | |
95 * @param retryCb(function): function to call when retrying | |
96 */ | |
97 var startTime = Date.now() / 1000; | |
98 var retryIntervalID; | |
99 var notif = document.createElement("div"); | |
100 notif.setAttribute('class', 'notification retry'); | |
101 //FIXME: we use English without translation for now, must be changed when we can use gettext in Libervia pages | |
102 notif.innerHTML = "<p>Can't reach the server, retrying in <span id='retry_counter'></span> seconds</p><p><a id='retry_now'>retry now</a></p>"; | |
103 document.body.appendChild(notif); | |
104 var retryCounter = document.getElementById('retry_counter'); | |
105 retryCounter.textContent = timeout; | |
106 | |
107 var retry = function () { | |
108 clearInterval(retryIntervalID); | |
109 notif.parentNode.removeChild(notif); | |
110 retryCb(); | |
111 }; | |
112 | |
113 var updateTimer = function () { | |
114 var elapsed = Math.floor(Date.now() / 1000 - startTime); | |
115 var remaining = timeout - elapsed; | |
116 if (remaining < 0) { | |
117 retry(); | |
118 } | |
119 else { | |
120 retryCounter.textContent = remaining; | |
121 } | |
122 }; | |
123 | |
124 var retryNow = document.getElementById('retry_now'); | |
125 retryNow.addEventListener('click', function(){ | |
126 retry(); | |
127 }); | |
128 | |
129 retryIntervalID = setInterval(updateTimer, 1000); | |
130 } | |
131 } |