]> git.proxmox.com Git - mirror_novnc.git/blame - include/util.js
Split util into two file:
[mirror_novnc.git] / include / util.js
CommitLineData
61dd52c9 1/*
15046f00
JM
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2010 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 */
a7a89626 11/*global window, console, document, navigator, ActiveXObject*/
61dd52c9 12
15046f00
JM
13// Globals defined here
14var Util = {}, $;
15
81e5adaf 16
da6dd893
JM
17/*
18 * Simple DOM selector by ID
19 */
15046f00
JM
20if (!window.$) {
21 $ = function (id) {
22 if (document.getElementById) {
23 return document.getElementById(id);
24 } else if (document.all) {
25 return document.all[id];
26 } else if (document.layers) {
27 return document.layers[id];
28 }
29 return undefined;
30 };
31}
56ec48be
JM
32
33/*
34 * Make arrays quack
35 */
36
56ec48be
JM
37Array.prototype.push8 = function (num) {
38 this.push(num & 0xFF);
39};
40
56ec48be
JM
41Array.prototype.push16 = function (num) {
42 this.push((num >> 8) & 0xFF,
43 (num ) & 0xFF );
44};
56ec48be
JM
45Array.prototype.push32 = function (num) {
46 this.push((num >> 24) & 0xFF,
47 (num >> 16) & 0xFF,
48 (num >> 8) & 0xFF,
49 (num ) & 0xFF );
50};
56ec48be 51
15046f00
JM
52/*
53 * ------------------------------------------------------
54 * Namespaced in Util
55 * ------------------------------------------------------
56 */
57
8db09746
JM
58/*
59 * Logging/debug routines
60 */
61
c1eba48f 62Util._log_level = 'warn';
8db09746 63Util.init_logging = function (level) {
c1eba48f 64 if (typeof level === 'undefined') {
c1eba48f
JM
65 level = Util._log_level;
66 } else {
67 Util._log_level = level;
68 }
8db09746
JM
69 if (typeof window.console === "undefined") {
70 if (typeof window.opera !== "undefined") {
71 window.console = {
72 'log' : window.opera.postError,
73 'warn' : window.opera.postError,
74 'error': window.opera.postError };
75 } else {
76 window.console = {
77 'log' : function(m) {},
78 'warn' : function(m) {},
79 'error': function(m) {}};
80 }
81 }
82
83 Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {};
84 switch (level) {
85 case 'debug': Util.Debug = function (msg) { console.log(msg); };
86 case 'info': Util.Info = function (msg) { console.log(msg); };
87 case 'warn': Util.Warn = function (msg) { console.warn(msg); };
88 case 'error': Util.Error = function (msg) { console.error(msg); };
89 case 'none':
90 break;
91 default:
92 throw("invalid logging type '" + level + "'");
93 }
94};
c1eba48f 95Util.get_logging = function () {
8d5d2c82
AM
96 return Util._log_level;
97}
8db09746 98// Initialize logging level
c1eba48f 99Util.init_logging();
8db09746 100
a8edf9d8 101
125d8bbb 102// Set defaults for Crockford style function namespaces
ff36b127
JM
103Util.conf_default = function(cfg, api, v, type, defval, desc) {
104 // Description
105 api['get_' + v + '_desc'] = desc;
125d8bbb
JM
106 // Default getter
107 if (typeof api['get_' + v] === 'undefined') {
108 api['get_' + v] = function () {
109 return cfg[v];
110 };
111 }
112 // Default setter
113 if (typeof api['set_' + v] === 'undefined') {
114 api['set_' + v] = function (val) {
ff36b127 115 if (type in {'boolean':1, 'bool':1}) {
8db09746
JM
116 if ((!val) || (val in {'0':1, 'no':1, 'false':1})) {
117 val = false;
118 } else {
119 val = true;
120 }
ff36b127
JM
121 } else if (type in {'integer':1, 'int':1}) {
122 val = parseInt(val, 10);
8db09746 123 }
125d8bbb
JM
124 cfg[v] = val;
125 };
126 }
ff36b127
JM
127
128 if (typeof cfg[v] === 'undefined') {
129 // Set to default
130 api['set_' + v](defval);
131 } else {
132 // Coerce existing setting to the right type
133 api['set_' + v](cfg[v]);
134 }
125d8bbb
JM
135};
136
137
a8edf9d8 138
15046f00
JM
139/*
140 * Cross-browser routines
141 */
142
143// Get DOM element position on page
144Util.getPosition = function (obj) {
145 var x = 0, y = 0;
146 if (obj.offsetParent) {
147 do {
148 x += obj.offsetLeft;
149 y += obj.offsetTop;
150 obj = obj.offsetParent;
151 } while (obj);
152 }
153 return {'x': x, 'y': y};
154};
155
156// Get mouse event position in DOM element
125d8bbb 157Util.getEventPosition = function (e, obj, scale) {
15046f00
JM
158 var evt, docX, docY, pos;
159 //if (!e) evt = window.event;
160 evt = (e ? e : window.event);
161 if (evt.pageX || evt.pageY) {
162 docX = evt.pageX;
163 docY = evt.pageY;
164 } else if (evt.clientX || evt.clientY) {
165 docX = evt.clientX + document.body.scrollLeft +
166 document.documentElement.scrollLeft;
167 docY = evt.clientY + document.body.scrollTop +
168 document.documentElement.scrollTop;
169 }
170 pos = Util.getPosition(obj);
125d8bbb
JM
171 if (typeof scale === "undefined") {
172 scale = 1;
173 }
174 return {'x': (docX - pos.x) / scale, 'y': (docY - pos.y) / scale};
15046f00
JM
175};
176
177
178// Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events
179Util.addEvent = function (obj, evType, fn){
d93d3e09 180 if (obj.attachEvent){
15046f00
JM
181 var r = obj.attachEvent("on"+evType, fn);
182 return r;
d93d3e09
JM
183 } else if (obj.addEventListener){
184 obj.addEventListener(evType, fn, false);
185 return true;
15046f00
JM
186 } else {
187 throw("Handler could not be attached");
188 }
189};
190
191Util.removeEvent = function(obj, evType, fn){
d93d3e09 192 if (obj.detachEvent){
15046f00
JM
193 var r = obj.detachEvent("on"+evType, fn);
194 return r;
d93d3e09
JM
195 } else if (obj.removeEventListener){
196 obj.removeEventListener(evType, fn, false);
197 return true;
15046f00
JM
198 } else {
199 throw("Handler could not be removed");
200 }
201};
202
203Util.stopEvent = function(e) {
204 if (e.stopPropagation) { e.stopPropagation(); }
205 else { e.cancelBubble = true; }
206
207 if (e.preventDefault) { e.preventDefault(); }
208 else { e.returnValue = false; }
209};
210
211
212// Set browser engine versions. Based on mootools.
213Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)};
214
215Util.Engine = {
216 'presto': (function() {
217 return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()),
218 'trident': (function() {
219 return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); }()),
220 'webkit': (function() {
11bb7a4a
JM
221 try { return (navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); } catch (e) { return false; } }()),
222 //'webkit': (function() {
223 // return ((typeof navigator.taintEnabled !== "unknown") && navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); }()),
15046f00 224 'gecko': (function() {
8787e49b 225 return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18); }())
15046f00
JM
226};
227
228Util.Flash = (function(){
229 var v, version;
230 try {
231 v = navigator.plugins['Shockwave Flash'].description;
232 } catch(err1) {
233 try {
234 v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
235 } catch(err2) {
236 v = '0 r0';
237 }
238 }
239 version = v.match(/\d+/g);
240 return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
8d5d2c82 241}());