]>
Commit | Line | Data |
---|---|---|
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 |
18 | var 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 |
27 | WebUtil.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 | ||
39 | WebUtil.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 |
68 | WebUtil.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 |
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 | }; | |
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 |
109 | WebUtil.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 |
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); } | |
8d5d2c82 AM |
138 | } |
139 | return (typeof defaultValue !== 'undefined') ? defaultValue : null; | |
140 | }; | |
141 | ||
ee7d4c61 SR |
142 | WebUtil.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 |
151 | WebUtil.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 |
171 | WebUtil.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 |
184 | WebUtil.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 |
202 | WebUtil.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 |
215 | WebUtil.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 |
231 | WebUtil.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 | |
251 | WebUtil.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). | |
287 | WebUtil.get_include_uri = function (root_dir) { | |
288 | return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI + root_dir + '/' : root_dir + '/'; | |
289 | }; | |
290 | WebUtil._loading_scripts = []; | |
291 | WebUtil._pending_scripts = []; | |
292 | WebUtil.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; */ |