]> git.proxmox.com Git - mirror_novnc.git/blob - app/webutil.js
Remove alternative style sheets
[mirror_novnc.git] / app / webutil.js
1 /*
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2012 Joel Martin
4 * Copyright (C) 2013 NTT corp.
5 * Licensed under MPL 2.0 (see LICENSE.txt)
6 *
7 * See README.md for usage and integration instructions.
8 */
9
10 /*jslint bitwise: false, white: false, browser: true, devel: true */
11 /*global Util, window, document */
12
13 /* [module]
14 * import Util from "../core/util";
15 */
16
17 // Globals defined here
18 var WebUtil = {};
19
20 /*
21 * ------------------------------------------------------
22 * Namespaced in WebUtil
23 * ------------------------------------------------------
24 */
25
26 // init log level reading the logging HTTP param
27 WebUtil.init_logging = function (level) {
28 "use strict";
29 if (typeof level !== "undefined") {
30 Util._log_level = level;
31 } else {
32 var param = document.location.href.match(/logging=([A-Za-z0-9\._\-]*)/);
33 Util._log_level = (param || ['', Util._log_level])[1];
34 }
35 Util.init_logging();
36 };
37
38
39 WebUtil.dirObj = function (obj, depth, parent) {
40 "use strict";
41 if (! depth) { depth = 2; }
42 if (! parent) { parent = ""; }
43
44 // Print the properties of the passed-in object
45 var msg = "";
46 for (var i in obj) {
47 if ((depth > 1) && (typeof obj[i] === "object")) {
48 // Recurse attributes that are objects
49 msg += WebUtil.dirObj(obj[i], depth - 1, parent + "." + i);
50 } else {
51 //val = new String(obj[i]).replace("\n", " ");
52 var val = "";
53 if (typeof(obj[i]) === "undefined") {
54 val = "undefined";
55 } else {
56 val = obj[i].toString().replace("\n", " ");
57 }
58 if (val.length > 30) {
59 val = val.substr(0, 30) + "...";
60 }
61 msg += parent + "." + i + ": " + val + "\n";
62 }
63 }
64 return msg;
65 };
66
67 // Read a query string variable
68 WebUtil.getQueryVar = function (name, defVal) {
69 "use strict";
70 var re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
71 match = document.location.href.match(re);
72 if (typeof defVal === 'undefined') { defVal = null; }
73 if (match) {
74 return decodeURIComponent(match[1]);
75 } else {
76 return defVal;
77 }
78 };
79
80 // Read a hash fragment variable
81 WebUtil.getHashVar = function (name, defVal) {
82 "use strict";
83 var re = new RegExp('.*[&#]' + name + '=([^&]*)'),
84 match = document.location.hash.match(re);
85 if (typeof defVal === 'undefined') { defVal = null; }
86 if (match) {
87 return decodeURIComponent(match[1]);
88 } else {
89 return defVal;
90 }
91 };
92
93 // Read a variable from the fragment or the query string
94 // Fragment takes precedence
95 WebUtil.getConfigVar = function (name, defVal) {
96 "use strict";
97 var val = WebUtil.getHashVar(name);
98 if (val === null) {
99 val = WebUtil.getQueryVar(name, defVal);
100 }
101 return val;
102 };
103
104 /*
105 * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
106 */
107
108 // No days means only for this browser session
109 WebUtil.createCookie = function (name, value, days) {
110 "use strict";
111 var date, expires;
112 if (days) {
113 date = new Date();
114 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
115 expires = "; expires=" + date.toGMTString();
116 } else {
117 expires = "";
118 }
119
120 var secure;
121 if (document.location.protocol === "https:") {
122 secure = "; secure";
123 } else {
124 secure = "";
125 }
126 document.cookie = name + "=" + value + expires + "; path=/" + secure;
127 };
128
129 WebUtil.readCookie = function (name, defaultValue) {
130 "use strict";
131 var nameEQ = name + "=",
132 ca = document.cookie.split(';');
133
134 for (var i = 0; i < ca.length; i += 1) {
135 var c = ca[i];
136 while (c.charAt(0) === ' ') { c = c.substring(1, c.length); }
137 if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length, c.length); }
138 }
139 return (typeof defaultValue !== 'undefined') ? defaultValue : null;
140 };
141
142 WebUtil.eraseCookie = function (name) {
143 "use strict";
144 WebUtil.createCookie(name, "", -1);
145 };
146
147 /*
148 * Setting handling.
149 */
150
151 WebUtil.initSettings = function (callback /*, ...callbackArgs */) {
152 "use strict";
153 var callbackArgs = Array.prototype.slice.call(arguments, 1);
154 if (window.chrome && window.chrome.storage) {
155 window.chrome.storage.sync.get(function (cfg) {
156 WebUtil.settings = cfg;
157 console.log(WebUtil.settings);
158 if (callback) {
159 callback.apply(this, callbackArgs);
160 }
161 });
162 } else {
163 // No-op
164 if (callback) {
165 callback.apply(this, callbackArgs);
166 }
167 }
168 };
169
170 // No days means only for this browser session
171 WebUtil.writeSetting = function (name, value) {
172 "use strict";
173 if (window.chrome && window.chrome.storage) {
174 //console.log("writeSetting:", name, value);
175 if (WebUtil.settings[name] !== value) {
176 WebUtil.settings[name] = value;
177 window.chrome.storage.sync.set(WebUtil.settings);
178 }
179 } else {
180 localStorage.setItem(name, value);
181 }
182 };
183
184 WebUtil.readSetting = function (name, defaultValue) {
185 "use strict";
186 var value;
187 if (window.chrome && window.chrome.storage) {
188 value = WebUtil.settings[name];
189 } else {
190 value = localStorage.getItem(name);
191 }
192 if (typeof value === "undefined") {
193 value = null;
194 }
195 if (value === null && typeof defaultValue !== undefined) {
196 return defaultValue;
197 } else {
198 return value;
199 }
200 };
201
202 WebUtil.eraseSetting = function (name) {
203 "use strict";
204 if (window.chrome && window.chrome.storage) {
205 window.chrome.storage.sync.remove(name);
206 delete WebUtil.settings[name];
207 } else {
208 localStorage.removeItem(name);
209 }
210 };
211
212 WebUtil.injectParamIfMissing = function (path, param, value) {
213 // force pretend that we're dealing with a relative path
214 // (assume that we wanted an extra if we pass one in)
215 path = "/" + path;
216
217 var elem = document.createElement('a');
218 elem.href = path;
219
220 var param_eq = encodeURIComponent(param) + "=";
221 var query;
222 if (elem.search) {
223 query = elem.search.slice(1).split('&');
224 } else {
225 query = [];
226 }
227
228 if (!query.some(function (v) { return v.startsWith(param_eq); })) {
229 query.push(param_eq + encodeURIComponent(value));
230 elem.search = "?" + query.join("&");
231 }
232
233 // some browsers (e.g. IE11) may occasionally omit the leading slash
234 // in the elem.pathname string. Handle that case gracefully.
235 if (elem.pathname.charAt(0) == "/") {
236 return elem.pathname.slice(1) + elem.search + elem.hash;
237 } else {
238 return elem.pathname + elem.search + elem.hash;
239 }
240 };
241
242 // Emulate Element.setCapture() when not supported
243
244 WebUtil._captureRecursion = false;
245 WebUtil._captureProxy = function (e) {
246 // Recursion protection as we'll see our own event
247 if (WebUtil._captureRecursion) return;
248
249 // Clone the event as we cannot dispatch an already dispatched event
250 var newEv = new e.constructor(e.type, e);
251
252 WebUtil._captureRecursion = true;
253 WebUtil._captureElem.dispatchEvent(newEv);
254 WebUtil._captureRecursion = false;
255
256 // Implicitly release the capture on button release
257 if ((e.type === "mouseup") || (e.type === "touchend")) {
258 WebUtil.releaseCapture();
259 }
260 };
261
262 WebUtil.setCapture = function (elem) {
263 if (elem.setCapture) {
264
265 elem.setCapture();
266
267 // IE releases capture on 'click' events which might not trigger
268 elem.addEventListener('mouseup', WebUtil.releaseCapture);
269 elem.addEventListener('touchend', WebUtil.releaseCapture);
270
271 } else {
272 // Safari on iOS 9 has a broken constructor for TouchEvent.
273 // We are fine in this case however, since Safari seems to
274 // have some sort of implicit setCapture magic anyway.
275 if (window.TouchEvent !== undefined) {
276 try {
277 new TouchEvent("touchstart");
278 } catch (TypeError) {
279 return;
280 }
281 }
282
283 var captureElem = document.getElementById("noVNC_mouse_capture_elem");
284
285 if (captureElem === null) {
286 captureElem = document.createElement("div");
287 captureElem.id = "noVNC_mouse_capture_elem";
288 captureElem.style.position = "fixed";
289 captureElem.style.top = "0px";
290 captureElem.style.left = "0px";
291 captureElem.style.width = "100%";
292 captureElem.style.height = "100%";
293 captureElem.style.zIndex = 10000;
294 captureElem.style.display = "none";
295 document.body.appendChild(captureElem);
296
297 captureElem.addEventListener('mousemove', WebUtil._captureProxy);
298 captureElem.addEventListener('mouseup', WebUtil._captureProxy);
299
300 captureElem.addEventListener('touchmove', WebUtil._captureProxy);
301 captureElem.addEventListener('touchend', WebUtil._captureProxy);
302 }
303
304 WebUtil._captureElem = elem;
305 captureElem.style.display = null;
306
307 // We listen to events on window in order to keep tracking if it
308 // happens to leave the viewport
309 window.addEventListener('mousemove', WebUtil._captureProxy);
310 window.addEventListener('mouseup', WebUtil._captureProxy);
311
312 window.addEventListener('touchmove', WebUtil._captureProxy);
313 window.addEventListener('touchend', WebUtil._captureProxy);
314 }
315 };
316
317 WebUtil.releaseCapture = function () {
318 if (document.releaseCapture) {
319
320 document.releaseCapture();
321
322 } else {
323 var captureElem = document.getElementById("noVNC_mouse_capture_elem");
324 WebUtil._captureElem = null;
325 captureElem.style.display = "none";
326
327 window.removeEventListener('mousemove', WebUtil._captureProxy);
328 window.removeEventListener('mouseup', WebUtil._captureProxy);
329
330 window.removeEventListener('touchmove', WebUtil._captureProxy);
331 window.removeEventListener('touchend', WebUtil._captureProxy);
332 }
333 };
334
335
336 // Dynamically load scripts without using document.write()
337 // Reference: http://unixpapa.com/js/dyna.html
338 //
339 // Handles the case where load_scripts is invoked from a script that
340 // itself is loaded via load_scripts. Once all scripts are loaded the
341 // window.onscriptsloaded handler is called (if set).
342 WebUtil.get_include_uri = function (root_dir) {
343 return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI + root_dir + '/' : root_dir + '/';
344 };
345 WebUtil._loading_scripts = [];
346 WebUtil._pending_scripts = [];
347 WebUtil.load_scripts = function (files_by_dir) {
348 "use strict";
349 var head = document.getElementsByTagName('head')[0], script,
350 ls = WebUtil._loading_scripts, ps = WebUtil._pending_scripts;
351
352 var loadFunc = function (e) {
353 while (ls.length > 0 && (ls[0].readyState === 'loaded' ||
354 ls[0].readyState === 'complete')) {
355 // For IE, append the script to trigger execution
356 var s = ls.shift();
357 //console.log("loaded script: " + s.src);
358 head.appendChild(s);
359 }
360 if (!this.readyState ||
361 (Util.Engine.presto && this.readyState === 'loaded') ||
362 this.readyState === 'complete') {
363 if (ps.indexOf(this) >= 0) {
364 this.onload = this.onreadystatechange = null;
365 //console.log("completed script: " + this.src);
366 ps.splice(ps.indexOf(this), 1);
367
368 // Call window.onscriptsload after last script loads
369 if (ps.length === 0 && window.onscriptsload) {
370 window.onscriptsload();
371 }
372 }
373 }
374 };
375
376 var root_dirs = Object.keys(files_by_dir);
377
378 for (var d = 0; d < root_dirs.length; d++) {
379 var root_dir = root_dirs[d];
380 var files = files_by_dir[root_dir];
381
382 for (var f = 0; f < files.length; f++) {
383 script = document.createElement('script');
384 script.type = 'text/javascript';
385 script.src = WebUtil.get_include_uri(root_dir) + files[f];
386 //console.log("loading script: " + script.src);
387 script.onload = script.onreadystatechange = loadFunc;
388 // In-order script execution tricks
389 if (Util.Engine.trident) {
390 // For IE wait until readyState is 'loaded' before
391 // appending it which will trigger execution
392 // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
393 ls.push(script);
394 } else {
395 // For webkit and firefox set async=false and append now
396 // https://developer.mozilla.org/en-US/docs/HTML/Element/script
397 script.async = false;
398 head.appendChild(script);
399 }
400 ps.push(script);
401 }
402 }
403 };
404
405 /* [module] export default WebUtil; */