]> git.proxmox.com Git - mirror_novnc.git/blame - include/util.js
Add websockify.py symlink for Windows.
[mirror_novnc.git] / include / util.js
CommitLineData
61dd52c9 1/*
15046f00 2 * noVNC: HTML5 VNC client
d0c29bb6 3 * Copyright (C) 2011 Joel Martin
5f409eee 4 * Licensed under LGPL-3 (see LICENSE.txt)
15046f00
JM
5 *
6 * See README.md for usage and integration instructions.
61dd52c9
JM
7 */
8
15046f00
JM
9"use strict";
10/*jslint bitwise: false, white: false */
a59f1cd2 11/*global window, console, document, navigator, ActiveXObject */
61dd52c9 12
15046f00 13// Globals defined here
a59f1cd2 14var Util = {};
15046f00 15
81e5adaf 16
56ec48be
JM
17/*
18 * Make arrays quack
19 */
20
56ec48be
JM
21Array.prototype.push8 = function (num) {
22 this.push(num & 0xFF);
23};
24
56ec48be
JM
25Array.prototype.push16 = function (num) {
26 this.push((num >> 8) & 0xFF,
27 (num ) & 0xFF );
28};
56ec48be
JM
29Array.prototype.push32 = function (num) {
30 this.push((num >> 24) & 0xFF,
31 (num >> 16) & 0xFF,
32 (num >> 8) & 0xFF,
33 (num ) & 0xFF );
34};
56ec48be 35
15046f00
JM
36/*
37 * ------------------------------------------------------
38 * Namespaced in Util
39 * ------------------------------------------------------
40 */
41
8db09746
JM
42/*
43 * Logging/debug routines
44 */
45
c1eba48f 46Util._log_level = 'warn';
8db09746 47Util.init_logging = function (level) {
c1eba48f 48 if (typeof level === 'undefined') {
c1eba48f
JM
49 level = Util._log_level;
50 } else {
51 Util._log_level = level;
52 }
8db09746
JM
53 if (typeof window.console === "undefined") {
54 if (typeof window.opera !== "undefined") {
55 window.console = {
56 'log' : window.opera.postError,
57 'warn' : window.opera.postError,
58 'error': window.opera.postError };
59 } else {
60 window.console = {
61 'log' : function(m) {},
62 'warn' : function(m) {},
63 'error': function(m) {}};
64 }
65 }
66
67 Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {};
68 switch (level) {
69 case 'debug': Util.Debug = function (msg) { console.log(msg); };
70 case 'info': Util.Info = function (msg) { console.log(msg); };
71 case 'warn': Util.Warn = function (msg) { console.warn(msg); };
72 case 'error': Util.Error = function (msg) { console.error(msg); };
73 case 'none':
74 break;
75 default:
76 throw("invalid logging type '" + level + "'");
77 }
78};
c1eba48f 79Util.get_logging = function () {
8d5d2c82 80 return Util._log_level;
d3796c14 81};
8db09746 82// Initialize logging level
c1eba48f 83Util.init_logging();
8db09746 84
a8edf9d8 85
5210330a
JM
86// Set configuration default for Crockford style function namespaces
87Util.conf_default = function(cfg, api, defaults, v, mode, type, defval, desc) {
88 var getter, setter;
89
90 // Default getter function
91 getter = function (idx) {
92 if ((type in {'arr':1, 'array':1}) &&
93 (typeof idx !== 'undefined')) {
94 return cfg[v][idx];
95 } else {
96 return cfg[v];
97 }
98 };
99
100 // Default setter function
101 setter = function (val, idx) {
102 if (type in {'boolean':1, 'bool':1}) {
103 if ((!val) || (val in {'0':1, 'no':1, 'false':1})) {
104 val = false;
d890e864 105 } else {
5210330a 106 val = true;
d890e864 107 }
5210330a
JM
108 } else if (type in {'integer':1, 'int':1}) {
109 val = parseInt(val, 10);
110 } else if (type === 'func') {
111 if (!val) {
112 val = function () {};
113 }
114 }
115 if (typeof idx !== 'undefined') {
116 cfg[v][idx] = val;
117 } else {
118 cfg[v] = val;
119 }
120 };
121
122 // Set the description
123 api[v + '_description'] = desc;
124
125 // Set the getter function
126 if (typeof api['get_' + v] === 'undefined') {
127 api['get_' + v] = getter;
125d8bbb 128 }
d890e864 129
5210330a 130 // Set the setter function with extra sanity checks
125d8bbb 131 if (typeof api['set_' + v] === 'undefined') {
d890e864 132 api['set_' + v] = function (val, idx) {
5210330a
JM
133 if (mode in {'RO':1, 'ro':1}) {
134 throw(v + " is read-only");
135 } else if ((mode in {'WO':1, 'wo':1}) &&
136 (typeof cfg[v] !== 'undefined')) {
137 throw(v + " can only be set once");
d890e864 138 }
5210330a 139 setter(val, idx);
d890e864 140 };
125d8bbb 141 }
ff36b127 142
5210330a
JM
143 // Set the default value
144 if (typeof defaults[v] !== 'undefined') {
145 defval = defaults[v];
146 } else if ((type in {'arr':1, 'array':1}) &&
147 (! (defval instanceof Array))) {
148 defval = [];
ff36b127 149 }
5210330a
JM
150 // Coerce existing setting to the right type
151 //Util.Debug("v: " + v + ", defval: " + defval + ", defaults[v]: " + defaults[v]);
152 setter(defval);
125d8bbb
JM
153};
154
5210330a
JM
155// Set group of configuration defaults
156Util.conf_defaults = function(cfg, api, defaults, arr) {
157 var i;
158 for (i = 0; i < arr.length; i++) {
159 Util.conf_default(cfg, api, defaults, arr[i][0], arr[i][1],
160 arr[i][2], arr[i][3], arr[i][4]);
161 }
162}
125d8bbb 163
a8edf9d8 164
15046f00
JM
165/*
166 * Cross-browser routines
167 */
168
169// Get DOM element position on page
170Util.getPosition = function (obj) {
171 var x = 0, y = 0;
172 if (obj.offsetParent) {
173 do {
174 x += obj.offsetLeft;
175 y += obj.offsetTop;
176 obj = obj.offsetParent;
177 } while (obj);
178 }
179 return {'x': x, 'y': y};
180};
181
182// Get mouse event position in DOM element
125d8bbb 183Util.getEventPosition = function (e, obj, scale) {
15046f00
JM
184 var evt, docX, docY, pos;
185 //if (!e) evt = window.event;
186 evt = (e ? e : window.event);
ad3f7624 187 evt = (evt.changedTouches ? evt.changedTouches[0] : evt.touches ? evt.touches[0] : evt);
15046f00
JM
188 if (evt.pageX || evt.pageY) {
189 docX = evt.pageX;
190 docY = evt.pageY;
191 } else if (evt.clientX || evt.clientY) {
192 docX = evt.clientX + document.body.scrollLeft +
193 document.documentElement.scrollLeft;
194 docY = evt.clientY + document.body.scrollTop +
195 document.documentElement.scrollTop;
196 }
197 pos = Util.getPosition(obj);
125d8bbb
JM
198 if (typeof scale === "undefined") {
199 scale = 1;
200 }
201 return {'x': (docX - pos.x) / scale, 'y': (docY - pos.y) / scale};
15046f00
JM
202};
203
204
205// Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events
206Util.addEvent = function (obj, evType, fn){
d93d3e09 207 if (obj.attachEvent){
15046f00
JM
208 var r = obj.attachEvent("on"+evType, fn);
209 return r;
d93d3e09
JM
210 } else if (obj.addEventListener){
211 obj.addEventListener(evType, fn, false);
212 return true;
15046f00
JM
213 } else {
214 throw("Handler could not be attached");
215 }
216};
217
218Util.removeEvent = function(obj, evType, fn){
d93d3e09 219 if (obj.detachEvent){
15046f00
JM
220 var r = obj.detachEvent("on"+evType, fn);
221 return r;
d93d3e09
JM
222 } else if (obj.removeEventListener){
223 obj.removeEventListener(evType, fn, false);
224 return true;
15046f00
JM
225 } else {
226 throw("Handler could not be removed");
227 }
228};
229
230Util.stopEvent = function(e) {
231 if (e.stopPropagation) { e.stopPropagation(); }
232 else { e.cancelBubble = true; }
233
234 if (e.preventDefault) { e.preventDefault(); }
235 else { e.returnValue = false; }
236};
237
238
239// Set browser engine versions. Based on mootools.
240Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)};
241
242Util.Engine = {
aa670567
JM
243 // Version detection break in Opera 11.60 (errors on arguments.callee.caller reference)
244 //'presto': (function() {
c3a172b9 245 // return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()),
aa670567
JM
246 'presto': (function() { return (!window.opera) ? false : true; }()),
247
15046f00
JM
248 'trident': (function() {
249 return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); }()),
250 'webkit': (function() {
11bb7a4a
JM
251 try { return (navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); } catch (e) { return false; } }()),
252 //'webkit': (function() {
253 // return ((typeof navigator.taintEnabled !== "unknown") && navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); }()),
15046f00 254 'gecko': (function() {
8787e49b 255 return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18); }())
15046f00 256};
cdb55d26
JM
257if (Util.Engine.webkit) {
258 // Extract actual webkit version if available
259 Util.Engine.webkit = (function(v) {
260 var re = new RegExp('WebKit/([0-9\.]*) ');
261 v = (navigator.userAgent.match(re) || ['', v])[1];
262 return parseFloat(v, 10);
263 })(Util.Engine.webkit);
264}
15046f00
JM
265
266Util.Flash = (function(){
267 var v, version;
268 try {
269 v = navigator.plugins['Shockwave Flash'].description;
270 } catch(err1) {
271 try {
272 v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
273 } catch(err2) {
274 v = '0 r0';
275 }
276 }
277 version = v.match(/\d+/g);
278 return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
a59f1cd2 279}());