]>
git.proxmox.com Git - mirror_novnc.git/blob - include/util.js
2 * noVNC: HTML5 VNC client
3 * Copyright (C) 2010 Joel Martin
4 * Licensed under LGPL-3 (see LICENSE.LGPL-3)
6 * See README.md for usage and integration instructions.
10 /*jslint bitwise: false, white: false */
11 /*global window, document, navigator, ActiveXObject*/
13 // Globals defined here
18 * Logging/debug routines
21 Util
.init_logging = function (level
) {
22 if (typeof window
.console
=== "undefined") {
23 if (typeof window
.opera
!== "undefined") {
25 'log' : window
.opera
.postError
,
26 'warn' : window
.opera
.postError
,
27 'error': window
.opera
.postError
};
30 'log' : function(m
) {},
31 'warn' : function(m
) {},
32 'error': function(m
) {}};
36 Util
.Debug
= Util
.Info
= Util
.Warn
= Util
.Error = function (msg
) {};
38 case 'debug': Util
.Debug = function (msg
) { console
.log(msg
); };
39 case 'info': Util
.Info = function (msg
) { console
.log(msg
); };
40 case 'warn': Util
.Warn = function (msg
) { console
.warn(msg
); };
41 case 'error': Util
.Error = function (msg
) { console
.error(msg
); };
44 throw("invalid logging type '" + level
+ "'");
47 // Initialize logging level
48 Util
.init_logging( (document
.location
.href
.match(
49 /logging=([A-Za-z0-9\._\-]*)/) ||
53 * Simple DOM selector by ID
57 if (document
.getElementById
) {
58 return document
.getElementById(id
);
59 } else if (document
.all
) {
60 return document
.all
[id
];
61 } else if (document
.layers
) {
62 return document
.layers
[id
];
72 Array
.prototype.shift8 = function () {
75 Array
.prototype.push8 = function (num
) {
76 this.push(num
& 0xFF);
79 Array
.prototype.shift16 = function () {
80 return (this.shift() << 8) +
83 Array
.prototype.push16 = function (num
) {
84 this.push((num
>> 8) & 0xFF,
87 Array
.prototype.push16le = function (num
) {
88 this.push((num
) & 0xFF,
93 Array
.prototype.shift32 = function () {
94 return (this.shift() << 24) +
95 (this.shift() << 16) +
99 Array
.prototype.get32 = function (off
) {
100 return (this[off
] << 24) +
101 (this[off
+ 1] << 16) +
102 (this[off
+ 2] << 8) +
105 Array
.prototype.push32 = function (num
) {
106 this.push((num
>> 24) & 0xFF,
111 Array
.prototype.push32le = function (num
) {
112 this.push((num
) & 0xFF,
115 (num
>> 24) & 0xFF );
119 Array
.prototype.shiftStr = function (len
) {
120 var arr
= this.splice(0, len
);
121 return arr
.map(function (num
) {
122 return String
.fromCharCode(num
); } ).join('');
124 Array
.prototype.pushStr = function (str
) {
125 var i
, n
= str
.length
;
126 for (i
=0; i
< n
; i
+=1) {
127 this.push(str
.charCodeAt(i
));
131 Array
.prototype.shiftBytes = function (len
) {
132 return this.splice(0, len
);
136 * ------------------------------------------------------
138 * ------------------------------------------------------
141 Util
.dirObj = function (obj
, depth
, parent
) {
142 var i
, msg
= "", val
= "";
143 if (! depth
) { depth
=2; }
144 if (! parent
) { parent
= ""; }
146 // Print the properties of the passed-in object
148 if ((depth
> 1) && (typeof obj
[i
] === "object")) {
149 // Recurse attributes that are objects
150 msg
+= Util
.dirObj(obj
[i
], depth
-1, parent
+ "." + i
);
152 //val = new String(obj[i]).replace("\n", " ");
153 val
= obj
[i
].toString().replace("\n", " ");
154 if (val
.length
> 30) {
155 val
= val
.substr(0,30) + "...";
157 msg
+= parent
+ "." + i
+ ": " + val
+ "\n";
164 * Cross-browser routines
167 // Get DOM element position on page
168 Util
.getPosition = function (obj
) {
170 if (obj
.offsetParent
) {
174 obj
= obj
.offsetParent
;
177 return {'x': x
, 'y': y
};
180 // Get mouse event position in DOM element
181 Util
.getEventPosition = function (e
, obj
) {
182 var evt
, docX
, docY
, pos
;
183 //if (!e) evt = window.event;
184 evt
= (e
? e
: window
.event
);
185 if (evt
.pageX
|| evt
.pageY
) {
188 } else if (evt
.clientX
|| evt
.clientY
) {
189 docX
= evt
.clientX
+ document
.body
.scrollLeft
+
190 document
.documentElement
.scrollLeft
;
191 docY
= evt
.clientY
+ document
.body
.scrollTop
+
192 document
.documentElement
.scrollTop
;
194 pos
= Util
.getPosition(obj
);
195 return {'x': docX
- pos
.x
, 'y': docY
- pos
.y
};
199 // Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events
200 Util
.addEvent = function (obj
, evType
, fn
){
201 if (obj
.attachEvent
){
202 var r
= obj
.attachEvent("on"+evType
, fn
);
204 } else if (obj
.addEventListener
){
205 obj
.addEventListener(evType
, fn
, false);
208 throw("Handler could not be attached");
212 Util
.removeEvent = function(obj
, evType
, fn
){
213 if (obj
.detachEvent
){
214 var r
= obj
.detachEvent("on"+evType
, fn
);
216 } else if (obj
.removeEventListener
){
217 obj
.removeEventListener(evType
, fn
, false);
220 throw("Handler could not be removed");
224 Util
.stopEvent = function(e
) {
225 if (e
.stopPropagation
) { e
.stopPropagation(); }
226 else { e
.cancelBubble
= true; }
228 if (e
.preventDefault
) { e
.preventDefault(); }
229 else { e
.returnValue
= false; }
233 // Set browser engine versions. Based on mootools.
234 Util
.Features
= {xpath
: !!(document
.evaluate
), air
: !!(window
.runtime
), query
: !!(document
.querySelector
)};
237 'presto': (function() {
238 return (!window
.opera
) ? false : ((arguments
.callee
.caller
) ? 960 : ((document
.getElementsByClassName
) ? 950 : 925)); }()),
239 'trident': (function() {
240 return (!window
.ActiveXObject
) ? false : ((window
.XMLHttpRequest
) ? ((document
.querySelectorAll
) ? 6 : 5) : 4); }()),
241 'webkit': (function() {
242 try { return (navigator
.taintEnabled
) ? false : ((Util
.Features
.xpath
) ? ((Util
.Features
.query
) ? 525 : 420) : 419); } catch (e
) { return false; } }()),
243 //'webkit': (function() {
244 // return ((typeof navigator.taintEnabled !== "unknown") && navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); }()),
245 'gecko': (function() {
246 return (!document
.getBoxObjectFor
&& !window
.mozInnerScreenX
) ? false : ((document
.getElementsByClassName
) ? 19 : 18); }())
249 Util
.Flash
= (function(){
252 v
= navigator
.plugins
['Shockwave Flash'].description
;
255 v
= new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
260 version
= v
.match(/\d+/g);
261 return {version
: parseInt(version
[0] || 0 + '.' + version
[1], 10) || 0, build
: parseInt(version
[2], 10) || 0};
265 * Cookie handling. Dervied from: http://www.quirksmode.org/js/cookies.html
267 // No days means only for this browser session
268 Util
.createCookie = function(name
,value
,days
) {
270 var date
= new Date();
271 date
.setTime(date
.getTime()+(days
*24*60*60*1000));
272 var expires
= "; expires="+date
.toGMTString();
274 else var expires
= "";
275 document
.cookie
= name
+"="+value
+expires
+"; path=/";
278 Util
.readCookie = function(name
, defaultValue
) {
279 var nameEQ
= name
+ "=";
280 var ca
= document
.cookie
.split(';');
281 for(var i
=0;i
< ca
.length
;i
++) {
283 while (c
.charAt(0)==' ') c
= c
.substring(1,c
.length
);
284 if (c
.indexOf(nameEQ
) == 0) return c
.substring(nameEQ
.length
,c
.length
);
286 return (typeof defaultValue
!== 'undefined') ? defaultValue
: null;
289 Util
.eraseCookie = function(name
) {
290 createCookie(name
,"",-1);
294 * Alternate stylesheet selection
296 Util
.getStylesheets = function() { var i
, links
, sheets
= [];
297 links
= document
.getElementsByTagName("link")
298 for (i
= 0; i
< links
.length
; i
++) {
299 if (links
[i
].title
&&
300 links
[i
].rel
.toUpperCase().indexOf("STYLESHEET") > -1) {
301 sheets
.push(links
[i
]);
307 // No sheet means try and use value from cookie, null sheet used to
308 // clear all alternates.
309 Util
.selectStylesheet = function(sheet
) {
310 var i
, link
, sheets
= Util
.getStylesheets();
311 if (typeof sheet
=== 'undefined') {
314 for (i
=0; i
< sheets
.length
; i
++) {
316 if (link
.title
=== sheet
) {
317 Util
.Debug("Using stylesheet " + sheet
);
318 link
.disabled
= false;
320 Util
.Debug("Skipping stylesheet " + link
.title
);
321 link
.disabled
= true;
327 // call once to disable alternates and get around webkit bug
328 Util
.selectStylesheet(null);