]> git.proxmox.com Git - mirror_novnc.git/blame - app/webutil.js
Clean up Util
[mirror_novnc.git] / app / webutil.js
CommitLineData
8d5d2c82
AM
1/*
2 * noVNC: HTML5 VNC client
d58f8b51 3 * Copyright (C) 2012 Joel Martin
ad941fad 4 * Copyright (C) 2013 NTT corp.
1d728ace 5 * Licensed under MPL 2.0 (see LICENSE.txt)
8d5d2c82
AM
6 *
7 * See README.md for usage and integration instructions.
8 */
9
ee7d4c61 10/*jslint bitwise: false, white: false, browser: true, devel: true */
ff4bfcb7 11/*global Util, window, document */
8d5d2c82 12
ae510306
SR
13/* [module]
14 * import Util from "../core/util";
8d5d2c82 15 */
8d5d2c82 16
ae510306
SR
17// Globals defined here
18var WebUtil = {};
8d5d2c82 19
ee7d4c61 20/*
8d5d2c82
AM
21 * ------------------------------------------------------
22 * Namespaced in WebUtil
23 * ------------------------------------------------------
24 */
25
26// init log level reading the logging HTTP param
ee7d4c61
SR
27WebUtil.init_logging = function (level) {
28 "use strict";
2cde6e43
JM
29 if (typeof level !== "undefined") {
30 Util._log_level = level;
31 } else {
ee7d4c61
SR
32 var param = document.location.href.match(/logging=([A-Za-z0-9\._\-]*)/);
33 Util._log_level = (param || ['', Util._log_level])[1];
2cde6e43 34 }
ff4bfcb7
JM
35 Util.init_logging();
36};
8d5d2c82
AM
37
38
39WebUtil.dirObj = function (obj, depth, parent) {
ee7d4c61
SR
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")) {
8d5d2c82 48 // Recurse attributes that are objects
ee7d4c61 49 msg += WebUtil.dirObj(obj[i], depth - 1, parent + "." + i);
8d5d2c82
AM
50 } else {
51 //val = new String(obj[i]).replace("\n", " ");
ee7d4c61 52 var val = "";
0a920147
JM
53 if (typeof(obj[i]) === "undefined") {
54 val = "undefined";
55 } else {
56 val = obj[i].toString().replace("\n", " ");
57 }
8d5d2c82 58 if (val.length > 30) {
ee7d4c61
SR
59 val = val.substr(0, 30) + "...";
60 }
8d5d2c82
AM
61 msg += parent + "." + i + ": " + val + "\n";
62 }
63 }
64 return msg;
65};
66
67// Read a query string variable
ee7d4c61
SR
68WebUtil.getQueryVar = function (name, defVal) {
69 "use strict";
d8c09535 70 var re = new RegExp('.*[?&]' + name + '=([^&#]*)'),
fa5b334d 71 match = document.location.href.match(re);
8d5d2c82 72 if (typeof defVal === 'undefined') { defVal = null; }
fa5b334d
JM
73 if (match) {
74 return decodeURIComponent(match[1]);
75 } else {
76 return defVal;
77 }
8d5d2c82
AM
78};
79
494b407a
GV
80// Read a hash fragment variable
81WebUtil.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
95WebUtil.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};
8d5d2c82
AM
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
ee7d4c61
SR
109WebUtil.createCookie = function (name, value, days) {
110 "use strict";
111 var date, expires;
8d5d2c82
AM
112 if (days) {
113 date = new Date();
ee7d4c61
SR
114 date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
115 expires = "; expires=" + date.toGMTString();
ad941fad 116 } else {
8d5d2c82
AM
117 expires = "";
118 }
ee7d4c61
SR
119
120 var secure;
ad941fad
TN
121 if (document.location.protocol === "https:") {
122 secure = "; secure";
123 } else {
124 secure = "";
125 }
ee7d4c61 126 document.cookie = name + "=" + value + expires + "; path=/" + secure;
8d5d2c82
AM
127};
128
ee7d4c61
SR
129WebUtil.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); }
8d5d2c82
AM
138 }
139 return (typeof defaultValue !== 'undefined') ? defaultValue : null;
140};
141
ee7d4c61
SR
142WebUtil.eraseCookie = function (name) {
143 "use strict";
144 WebUtil.createCookie(name, "", -1);
8d5d2c82
AM
145};
146
3af1c275
JM
147/*
148 * Setting handling.
149 */
150
ee7d4c61
SR
151WebUtil.initSettings = function (callback /*, ...callbackArgs */) {
152 "use strict";
3af1c275 153 var callbackArgs = Array.prototype.slice.call(arguments, 1);
d5fe1509
JM
154 if (window.chrome && window.chrome.storage) {
155 window.chrome.storage.sync.get(function (cfg) {
3af1c275
JM
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
ee7d4c61
SR
171WebUtil.writeSetting = function (name, value) {
172 "use strict";
d5fe1509 173 if (window.chrome && window.chrome.storage) {
3af1c275
JM
174 //console.log("writeSetting:", name, value);
175 if (WebUtil.settings[name] !== value) {
176 WebUtil.settings[name] = value;
d5fe1509 177 window.chrome.storage.sync.set(WebUtil.settings);
3af1c275
JM
178 }
179 } else {
180 localStorage.setItem(name, value);
181 }
182};
183
ee7d4c61
SR
184WebUtil.readSetting = function (name, defaultValue) {
185 "use strict";
3af1c275 186 var value;
d5fe1509 187 if (window.chrome && window.chrome.storage) {
3af1c275
JM
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
ee7d4c61
SR
202WebUtil.eraseSetting = function (name) {
203 "use strict";
d5fe1509
JM
204 if (window.chrome && window.chrome.storage) {
205 window.chrome.storage.sync.remove(name);
3af1c275
JM
206 delete WebUtil.settings[name];
207 } else {
208 localStorage.removeItem(name);
209 }
210};
211
8d5d2c82
AM
212/*
213 * Alternate stylesheet selection
214 */
ee7d4c61
SR
215WebUtil.getStylesheets = function () {
216 "use strict";
217 var links = document.getElementsByTagName("link");
218 var sheets = [];
219
220 for (var i = 0; i < links.length; i += 1) {
8d5d2c82
AM
221 if (links[i].title &&
222 links[i].rel.toUpperCase().indexOf("STYLESHEET") > -1) {
223 sheets.push(links[i]);
224 }
225 }
226 return sheets;
227};
228
229// No sheet means try and use value from cookie, null sheet used to
230// clear all alternates.
ee7d4c61
SR
231WebUtil.selectStylesheet = function (sheet) {
232 "use strict";
8d5d2c82
AM
233 if (typeof sheet === 'undefined') {
234 sheet = 'default';
235 }
ee7d4c61
SR
236
237 var sheets = WebUtil.getStylesheets();
238 for (var i = 0; i < sheets.length; i += 1) {
239 var link = sheets[i];
240 if (link.title === sheet) {
8d5d2c82
AM
241 Util.Debug("Using stylesheet " + sheet);
242 link.disabled = false;
243 } else {
244 //Util.Debug("Skipping stylesheet " + link.title);
245 link.disabled = true;
246 }
247 }
248 return sheet;
249};
c55f05f6
MXPN
250
251WebUtil.injectParamIfMissing = function (path, param, value) {
252 // force pretend that we're dealing with a relative path
253 // (assume that we wanted an extra if we pass one in)
254 path = "/" + path;
255
256 var elem = document.createElement('a');
257 elem.href = path;
258
259 var param_eq = encodeURIComponent(param) + "=";
260 var query;
261 if (elem.search) {
262 query = elem.search.slice(1).split('&');
263 } else {
264 query = [];
265 }
266
267 if (!query.some(function (v) { return v.startsWith(param_eq); })) {
268 query.push(param_eq + encodeURIComponent(value));
269 elem.search = "?" + query.join("&");
270 }
271
c8294760
JB
272 // some browsers (e.g. IE11) may occasionally omit the leading slash
273 // in the elem.pathname string. Handle that case gracefully.
274 if (elem.pathname.charAt(0) == "/") {
275 return elem.pathname.slice(1) + elem.search + elem.hash;
276 } else {
277 return elem.pathname + elem.search + elem.hash;
3c955844 278 }
c55f05f6 279};
ae510306 280
72bdd06e
SR
281// Dynamically load scripts without using document.write()
282// Reference: http://unixpapa.com/js/dyna.html
283//
284// Handles the case where load_scripts is invoked from a script that
285// itself is loaded via load_scripts. Once all scripts are loaded the
286// window.onscriptsloaded handler is called (if set).
287WebUtil.get_include_uri = function (root_dir) {
288 return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI + root_dir + '/' : root_dir + '/';
289};
290WebUtil._loading_scripts = [];
291WebUtil._pending_scripts = [];
292WebUtil.load_scripts = function (files_by_dir) {
293 "use strict";
294 var head = document.getElementsByTagName('head')[0], script,
295 ls = WebUtil._loading_scripts, ps = WebUtil._pending_scripts;
296
297 var loadFunc = function (e) {
298 while (ls.length > 0 && (ls[0].readyState === 'loaded' ||
299 ls[0].readyState === 'complete')) {
300 // For IE, append the script to trigger execution
301 var s = ls.shift();
302 //console.log("loaded script: " + s.src);
303 head.appendChild(s);
304 }
305 if (!this.readyState ||
306 (Util.Engine.presto && this.readyState === 'loaded') ||
307 this.readyState === 'complete') {
308 if (ps.indexOf(this) >= 0) {
309 this.onload = this.onreadystatechange = null;
310 //console.log("completed script: " + this.src);
311 ps.splice(ps.indexOf(this), 1);
312
313 // Call window.onscriptsload after last script loads
314 if (ps.length === 0 && window.onscriptsload) {
315 window.onscriptsload();
316 }
317 }
318 }
319 };
320
321 var root_dirs = Object.keys(files_by_dir);
322
323 for (var d = 0; d < root_dirs.length; d++) {
324 var root_dir = root_dirs[d];
325 var files = files_by_dir[root_dir];
326
327 for (var f = 0; f < files.length; f++) {
328 script = document.createElement('script');
329 script.type = 'text/javascript';
330 script.src = WebUtil.get_include_uri(root_dir) + files[f];
331 //console.log("loading script: " + script.src);
332 script.onload = script.onreadystatechange = loadFunc;
333 // In-order script execution tricks
334 if (Util.Engine.trident) {
335 // For IE wait until readyState is 'loaded' before
336 // appending it which will trigger execution
337 // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
338 ls.push(script);
339 } else {
340 // For webkit and firefox set async=false and append now
341 // https://developer.mozilla.org/en-US/docs/HTML/Element/script
342 script.async = false;
343 head.appendChild(script);
344 }
345 ps.push(script);
346 }
347 }
348};
349
ae510306 350/* [module] export default WebUtil; */