]>
git.proxmox.com Git - mirror_novnc.git/blob - app/webutil.js
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)
7 * See README.md for usage and integration instructions.
10 /*jslint bitwise: false, white: false, browser: true, devel: true */
11 /*global Util, window, document */
14 * import Util from "../core/util";
17 // Globals defined here
21 * ------------------------------------------------------
22 * Namespaced in WebUtil
23 * ------------------------------------------------------
26 // init log level reading the logging HTTP param
27 WebUtil
.init_logging = function (level
) {
29 if (typeof level
!== "undefined") {
30 Util
._log_level
= level
;
32 var param
= document
.location
.href
.match(/logging=([A-Za-z0-9\._\-]*)/);
33 Util
._log_level
= (param
|| ['', Util
._log_level
])[1];
39 WebUtil
.dirObj = function (obj
, depth
, parent
) {
41 if (! depth
) { depth
= 2; }
42 if (! parent
) { parent
= ""; }
44 // Print the properties of the passed-in object
47 if ((depth
> 1) && (typeof obj
[i
] === "object")) {
48 // Recurse attributes that are objects
49 msg
+= WebUtil
.dirObj(obj
[i
], depth
- 1, parent
+ "." + i
);
51 //val = new String(obj[i]).replace("\n", " ");
53 if (typeof(obj
[i
]) === "undefined") {
56 val
= obj
[i
].toString().replace("\n", " ");
58 if (val
.length
> 30) {
59 val
= val
.substr(0, 30) + "...";
61 msg
+= parent
+ "." + i
+ ": " + val
+ "\n";
67 // Read a query string variable
68 WebUtil
.getQueryVar = function (name
, defVal
) {
70 var re
= new RegExp('.*[?&]' + name
+ '=([^&#]*)'),
71 match
= document
.location
.href
.match(re
);
72 if (typeof defVal
=== 'undefined') { defVal
= null; }
74 return decodeURIComponent(match
[1]);
80 // Read a hash fragment variable
81 WebUtil
.getHashVar = function (name
, defVal
) {
83 var re
= new RegExp('.*[&#]' + name
+ '=([^&]*)'),
84 match
= document
.location
.hash
.match(re
);
85 if (typeof defVal
=== 'undefined') { defVal
= null; }
87 return decodeURIComponent(match
[1]);
93 // Read a variable from the fragment or the query string
94 // Fragment takes precedence
95 WebUtil
.getConfigVar = function (name
, defVal
) {
97 var val
= WebUtil
.getHashVar(name
);
99 val
= WebUtil
.getQueryVar(name
, defVal
);
105 * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
108 // No days means only for this browser session
109 WebUtil
.createCookie = function (name
, value
, days
) {
114 date
.setTime(date
.getTime() + (days
* 24 * 60 * 60 * 1000));
115 expires
= "; expires=" + date
.toGMTString();
121 if (document
.location
.protocol
=== "https:") {
126 document
.cookie
= name
+ "=" + value
+ expires
+ "; path=/" + secure
;
129 WebUtil
.readCookie = function (name
, defaultValue
) {
131 var nameEQ
= name
+ "=",
132 ca
= document
.cookie
.split(';');
134 for (var i
= 0; i
< ca
.length
; i
+= 1) {
136 while (c
.charAt(0) === ' ') { c
= c
.substring(1, c
.length
); }
137 if (c
.indexOf(nameEQ
) === 0) { return c
.substring(nameEQ
.length
, c
.length
); }
139 return (typeof defaultValue
!== 'undefined') ? defaultValue
: null;
142 WebUtil
.eraseCookie = function (name
) {
144 WebUtil
.createCookie(name
, "", -1);
151 WebUtil
.initSettings = function (callback
/*, ...callbackArgs */) {
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
);
159 callback
.apply(this, callbackArgs
);
165 callback
.apply(this, callbackArgs
);
170 // No days means only for this browser session
171 WebUtil
.writeSetting = function (name
, value
) {
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
);
180 localStorage
.setItem(name
, value
);
184 WebUtil
.readSetting = function (name
, defaultValue
) {
187 if (window
.chrome
&& window
.chrome
.storage
) {
188 value
= WebUtil
.settings
[name
];
190 value
= localStorage
.getItem(name
);
192 if (typeof value
=== "undefined") {
195 if (value
=== null && typeof defaultValue
!== undefined) {
202 WebUtil
.eraseSetting = function (name
) {
204 if (window
.chrome
&& window
.chrome
.storage
) {
205 window
.chrome
.storage
.sync
.remove(name
);
206 delete WebUtil
.settings
[name
];
208 localStorage
.removeItem(name
);
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)
217 var elem
= document
.createElement('a');
220 var param_eq
= encodeURIComponent(param
) + "=";
223 query
= elem
.search
.slice(1).split('&');
228 if (!query
.some(function (v
) { return v
.startsWith(param_eq
); })) {
229 query
.push(param_eq
+ encodeURIComponent(value
));
230 elem
.search
= "?" + query
.join("&");
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
;
238 return elem
.pathname
+ elem
.search
+ elem
.hash
;
242 // Emulate Element.setCapture() when not supported
244 WebUtil
._captureRecursion
= false;
245 WebUtil
._captureProxy = function (e
) {
246 // Recursion protection as we'll see our own event
247 if (WebUtil
._captureRecursion
) return;
249 // Clone the event as we cannot dispatch an already dispatched event
250 var newEv
= new e
.constructor(e
.type
, e
);
252 WebUtil
._captureRecursion
= true;
253 WebUtil
._captureElem
.dispatchEvent(newEv
);
254 WebUtil
._captureRecursion
= false;
256 // Implicitly release the capture on button release
257 if ((e
.type
=== "mouseup") || (e
.type
=== "touchend")) {
258 WebUtil
.releaseCapture();
262 WebUtil
.setCapture = function (elem
) {
263 if (elem
.setCapture
) {
267 // IE releases capture on 'click' events which might not trigger
268 elem
.addEventListener('mouseup', WebUtil
.releaseCapture
);
269 elem
.addEventListener('touchend', WebUtil
.releaseCapture
);
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) {
277 new TouchEvent("touchstart");
278 } catch (TypeError
) {
283 var captureElem
= document
.getElementById("noVNC_mouse_capture_elem");
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
);
297 captureElem
.addEventListener('mousemove', WebUtil
._captureProxy
);
298 captureElem
.addEventListener('mouseup', WebUtil
._captureProxy
);
300 captureElem
.addEventListener('touchmove', WebUtil
._captureProxy
);
301 captureElem
.addEventListener('touchend', WebUtil
._captureProxy
);
304 WebUtil
._captureElem
= elem
;
305 captureElem
.style
.display
= null;
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
);
312 window
.addEventListener('touchmove', WebUtil
._captureProxy
);
313 window
.addEventListener('touchend', WebUtil
._captureProxy
);
317 WebUtil
.releaseCapture = function () {
318 if (document
.releaseCapture
) {
320 document
.releaseCapture();
323 var captureElem
= document
.getElementById("noVNC_mouse_capture_elem");
324 WebUtil
._captureElem
= null;
325 captureElem
.style
.display
= "none";
327 window
.removeEventListener('mousemove', WebUtil
._captureProxy
);
328 window
.removeEventListener('mouseup', WebUtil
._captureProxy
);
330 window
.removeEventListener('touchmove', WebUtil
._captureProxy
);
331 window
.removeEventListener('touchend', WebUtil
._captureProxy
);
336 // Dynamically load scripts without using document.write()
337 // Reference: http://unixpapa.com/js/dyna.html
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
+ '/';
345 WebUtil
._loading_scripts
= [];
346 WebUtil
._pending_scripts
= [];
347 WebUtil
.load_scripts = function (files_by_dir
) {
349 var head
= document
.getElementsByTagName('head')[0], script
,
350 ls
= WebUtil
._loading_scripts
, ps
= WebUtil
._pending_scripts
;
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
357 //console.log("loaded script: " + s.src);
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);
368 // Call window.onscriptsload after last script loads
369 if (ps
.length
=== 0 && window
.onscriptsload
) {
370 window
.onscriptsload();
376 var root_dirs
= Object
.keys(files_by_dir
);
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
];
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
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
);
405 /* [module] export default WebUtil; */