novnc-rails 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +0 -0
  3. data/LICENSE.txt +0 -0
  4. data/README.md +0 -0
  5. data/lib/novnc-rails.rb +8 -0
  6. data/lib/novnc-rails/version.rb +5 -0
  7. data/vendor/assets/javascripts/noVNC/Orbitron700.ttf +0 -0
  8. data/vendor/assets/javascripts/noVNC/Orbitron700.woff +0 -0
  9. data/vendor/assets/javascripts/noVNC/base.css +512 -0
  10. data/vendor/assets/javascripts/noVNC/base64.js +113 -0
  11. data/vendor/assets/javascripts/noVNC/black.css +71 -0
  12. data/vendor/assets/javascripts/noVNC/blue.css +64 -0
  13. data/vendor/assets/javascripts/noVNC/des.js +276 -0
  14. data/vendor/assets/javascripts/noVNC/display.js +751 -0
  15. data/vendor/assets/javascripts/noVNC/input.js +388 -0
  16. data/vendor/assets/javascripts/noVNC/jsunzip.js +676 -0
  17. data/vendor/assets/javascripts/noVNC/keyboard.js +543 -0
  18. data/vendor/assets/javascripts/noVNC/keysym.js +378 -0
  19. data/vendor/assets/javascripts/noVNC/keysymdef.js +15 -0
  20. data/vendor/assets/javascripts/noVNC/logo.js +1 -0
  21. data/vendor/assets/javascripts/noVNC/playback.js +102 -0
  22. data/vendor/assets/javascripts/noVNC/rfb.js +1889 -0
  23. data/vendor/assets/javascripts/noVNC/ui.js +979 -0
  24. data/vendor/assets/javascripts/noVNC/util.js +656 -0
  25. data/vendor/assets/javascripts/noVNC/web-socket-js/README.txt +109 -0
  26. data/vendor/assets/javascripts/noVNC/web-socket-js/WebSocketMain.swf +0 -0
  27. data/vendor/assets/javascripts/noVNC/web-socket-js/swfobject.js +4 -0
  28. data/vendor/assets/javascripts/noVNC/web-socket-js/web_socket.js +391 -0
  29. data/vendor/assets/javascripts/noVNC/websock.js +388 -0
  30. data/vendor/assets/javascripts/noVNC/webutil.js +239 -0
  31. metadata +86 -0
@@ -0,0 +1,656 @@
1
+ /*
2
+ * noVNC: HTML5 VNC client
3
+ * Copyright (C) 2012 Joel Martin
4
+ * Licensed under MPL 2.0 (see LICENSE.txt)
5
+ *
6
+ * See README.md for usage and integration instructions.
7
+ */
8
+
9
+ /* jshint white: false, nonstandard: true */
10
+ /*global window, console, document, navigator, ActiveXObject, INCLUDE_URI */
11
+
12
+ // Globals defined here
13
+ var Util = {};
14
+
15
+
16
+ /*
17
+ * Make arrays quack
18
+ */
19
+
20
+ var addFunc = function (cl, name, func) {
21
+ if (!cl.prototype[name]) {
22
+ Object.defineProperty(cl.prototype, name, { enumerable: false, value: func });
23
+ }
24
+ };
25
+
26
+ addFunc(Array, 'push8', function (num) {
27
+ "use strict";
28
+ this.push(num & 0xFF);
29
+ });
30
+
31
+ addFunc(Array, 'push16', function (num) {
32
+ "use strict";
33
+ this.push((num >> 8) & 0xFF,
34
+ num & 0xFF);
35
+ });
36
+
37
+ addFunc(Array, 'push32', function (num) {
38
+ "use strict";
39
+ this.push((num >> 24) & 0xFF,
40
+ (num >> 16) & 0xFF,
41
+ (num >> 8) & 0xFF,
42
+ num & 0xFF);
43
+ });
44
+
45
+ // IE does not support map (even in IE9)
46
+ //This prototype is provided by the Mozilla foundation and
47
+ //is distributed under the MIT license.
48
+ //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
49
+ addFunc(Array, 'map', function (fun /*, thisp*/) {
50
+ "use strict";
51
+ var len = this.length;
52
+ if (typeof fun != "function") {
53
+ throw new TypeError();
54
+ }
55
+
56
+ var res = new Array(len);
57
+ var thisp = arguments[1];
58
+ for (var i = 0; i < len; i++) {
59
+ if (i in this) {
60
+ res[i] = fun.call(thisp, this[i], i, this);
61
+ }
62
+ }
63
+
64
+ return res;
65
+ });
66
+
67
+ // IE <9 does not support indexOf
68
+ //This prototype is provided by the Mozilla foundation and
69
+ //is distributed under the MIT license.
70
+ //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
71
+ addFunc(Array, 'indexOf', function (elt /*, from*/) {
72
+ "use strict";
73
+ var len = this.length >>> 0;
74
+
75
+ var from = Number(arguments[1]) || 0;
76
+ from = (from < 0) ? Math.ceil(from) : Math.floor(from);
77
+ if (from < 0) {
78
+ from += len;
79
+ }
80
+
81
+ for (; from < len; from++) {
82
+ if (from in this &&
83
+ this[from] === elt) {
84
+ return from;
85
+ }
86
+ }
87
+ return -1;
88
+ });
89
+
90
+ // From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys
91
+ if (!Object.keys) {
92
+ Object.keys = (function () {
93
+ 'use strict';
94
+ var hasOwnProperty = Object.prototype.hasOwnProperty,
95
+ hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
96
+ dontEnums = [
97
+ 'toString',
98
+ 'toLocaleString',
99
+ 'valueOf',
100
+ 'hasOwnProperty',
101
+ 'isPrototypeOf',
102
+ 'propertyIsEnumerable',
103
+ 'constructor'
104
+ ],
105
+ dontEnumsLength = dontEnums.length;
106
+
107
+ return function (obj) {
108
+ if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
109
+ throw new TypeError('Object.keys called on non-object');
110
+ }
111
+
112
+ var result = [], prop, i;
113
+
114
+ for (prop in obj) {
115
+ if (hasOwnProperty.call(obj, prop)) {
116
+ result.push(prop);
117
+ }
118
+ }
119
+
120
+ if (hasDontEnumBug) {
121
+ for (i = 0; i < dontEnumsLength; i++) {
122
+ if (hasOwnProperty.call(obj, dontEnums[i])) {
123
+ result.push(dontEnums[i]);
124
+ }
125
+ }
126
+ }
127
+ return result;
128
+ };
129
+ })();
130
+ }
131
+
132
+ // PhantomJS 1.x doesn't support bind,
133
+ // so leave this in until PhantomJS 2.0 is released
134
+ //This prototype is provided by the Mozilla foundation and
135
+ //is distributed under the MIT license.
136
+ //http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
137
+ addFunc(Function, 'bind', function (oThis) {
138
+ if (typeof this !== "function") {
139
+ // closest thing possible to the ECMAScript 5
140
+ // internal IsCallable function
141
+ throw new TypeError("Function.prototype.bind - " +
142
+ "what is trying to be bound is not callable");
143
+ }
144
+
145
+ var aArgs = Array.prototype.slice.call(arguments, 1),
146
+ fToBind = this,
147
+ fNOP = function () {},
148
+ fBound = function () {
149
+ return fToBind.apply(this instanceof fNOP && oThis ? this
150
+ : oThis,
151
+ aArgs.concat(Array.prototype.slice.call(arguments)));
152
+ };
153
+
154
+ fNOP.prototype = this.prototype;
155
+ fBound.prototype = new fNOP();
156
+
157
+ return fBound;
158
+ });
159
+
160
+ //
161
+ // requestAnimationFrame shim with setTimeout fallback
162
+ //
163
+
164
+ window.requestAnimFrame = (function () {
165
+ "use strict";
166
+ return window.requestAnimationFrame ||
167
+ window.webkitRequestAnimationFrame ||
168
+ window.mozRequestAnimationFrame ||
169
+ window.oRequestAnimationFrame ||
170
+ window.msRequestAnimationFrame ||
171
+ function (callback) {
172
+ window.setTimeout(callback, 1000 / 60);
173
+ };
174
+ })();
175
+
176
+ /*
177
+ * ------------------------------------------------------
178
+ * Namespaced in Util
179
+ * ------------------------------------------------------
180
+ */
181
+
182
+ /*
183
+ * Logging/debug routines
184
+ */
185
+
186
+ Util._log_level = 'warn';
187
+ Util.init_logging = function (level) {
188
+ "use strict";
189
+ if (typeof level === 'undefined') {
190
+ level = Util._log_level;
191
+ } else {
192
+ Util._log_level = level;
193
+ }
194
+ if (typeof window.console === "undefined") {
195
+ if (typeof window.opera !== "undefined") {
196
+ window.console = {
197
+ 'log' : window.opera.postError,
198
+ 'warn' : window.opera.postError,
199
+ 'error': window.opera.postError
200
+ };
201
+ } else {
202
+ window.console = {
203
+ 'log' : function (m) {},
204
+ 'warn' : function (m) {},
205
+ 'error': function (m) {}
206
+ };
207
+ }
208
+ }
209
+
210
+ Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {};
211
+ /* jshint -W086 */
212
+ switch (level) {
213
+ case 'debug':
214
+ Util.Debug = function (msg) { console.log(msg); };
215
+ case 'info':
216
+ Util.Info = function (msg) { console.log(msg); };
217
+ case 'warn':
218
+ Util.Warn = function (msg) { console.warn(msg); };
219
+ case 'error':
220
+ Util.Error = function (msg) { console.error(msg); };
221
+ case 'none':
222
+ break;
223
+ default:
224
+ throw new Error("invalid logging type '" + level + "'");
225
+ }
226
+ /* jshint +W086 */
227
+ };
228
+ Util.get_logging = function () {
229
+ return Util._log_level;
230
+ };
231
+ // Initialize logging level
232
+ Util.init_logging();
233
+
234
+ Util.make_property = function (proto, name, mode, type) {
235
+ "use strict";
236
+
237
+ var getter;
238
+ if (type === 'arr') {
239
+ getter = function (idx) {
240
+ if (typeof idx !== 'undefined') {
241
+ return this['_' + name][idx];
242
+ } else {
243
+ return this['_' + name];
244
+ }
245
+ };
246
+ } else {
247
+ getter = function () {
248
+ return this['_' + name];
249
+ };
250
+ }
251
+
252
+ var make_setter = function (process_val) {
253
+ if (process_val) {
254
+ return function (val, idx) {
255
+ if (typeof idx !== 'undefined') {
256
+ this['_' + name][idx] = process_val(val);
257
+ } else {
258
+ this['_' + name] = process_val(val);
259
+ }
260
+ };
261
+ } else {
262
+ return function (val, idx) {
263
+ if (typeof idx !== 'undefined') {
264
+ this['_' + name][idx] = val;
265
+ } else {
266
+ this['_' + name] = val;
267
+ }
268
+ };
269
+ }
270
+ };
271
+
272
+ var setter;
273
+ if (type === 'bool') {
274
+ setter = make_setter(function (val) {
275
+ if (!val || (val in {'0': 1, 'no': 1, 'false': 1})) {
276
+ return false;
277
+ } else {
278
+ return true;
279
+ }
280
+ });
281
+ } else if (type === 'int') {
282
+ setter = make_setter(function (val) { return parseInt(val, 10); });
283
+ } else if (type === 'float') {
284
+ setter = make_setter(parseFloat);
285
+ } else if (type === 'str') {
286
+ setter = make_setter(String);
287
+ } else if (type === 'func') {
288
+ setter = make_setter(function (val) {
289
+ if (!val) {
290
+ return function () {};
291
+ } else {
292
+ return val;
293
+ }
294
+ });
295
+ } else if (type === 'arr' || type === 'dom' || type == 'raw') {
296
+ setter = make_setter();
297
+ } else {
298
+ throw new Error('Unknown property type ' + type); // some sanity checking
299
+ }
300
+
301
+ // set the getter
302
+ if (typeof proto['get_' + name] === 'undefined') {
303
+ proto['get_' + name] = getter;
304
+ }
305
+
306
+ // set the setter if needed
307
+ if (typeof proto['set_' + name] === 'undefined') {
308
+ if (mode === 'rw') {
309
+ proto['set_' + name] = setter;
310
+ } else if (mode === 'wo') {
311
+ proto['set_' + name] = function (val, idx) {
312
+ if (typeof this['_' + name] !== 'undefined') {
313
+ throw new Error(name + " can only be set once");
314
+ }
315
+ setter.call(this, val, idx);
316
+ };
317
+ }
318
+ }
319
+
320
+ // make a special setter that we can use in set defaults
321
+ proto['_raw_set_' + name] = function (val, idx) {
322
+ setter.call(this, val, idx);
323
+ //delete this['_init_set_' + name]; // remove it after use
324
+ };
325
+ };
326
+
327
+ Util.make_properties = function (constructor, arr) {
328
+ "use strict";
329
+ for (var i = 0; i < arr.length; i++) {
330
+ Util.make_property(constructor.prototype, arr[i][0], arr[i][1], arr[i][2]);
331
+ }
332
+ };
333
+
334
+ Util.set_defaults = function (obj, conf, defaults) {
335
+ var defaults_keys = Object.keys(defaults);
336
+ var conf_keys = Object.keys(conf);
337
+ var keys_obj = {};
338
+ var i;
339
+ for (i = 0; i < defaults_keys.length; i++) { keys_obj[defaults_keys[i]] = 1; }
340
+ for (i = 0; i < conf_keys.length; i++) { keys_obj[conf_keys[i]] = 1; }
341
+ var keys = Object.keys(keys_obj);
342
+
343
+ for (i = 0; i < keys.length; i++) {
344
+ var setter = obj['_raw_set_' + keys[i]];
345
+ if (!setter) {
346
+ Util.Warn('Invalid property ' + keys[i]);
347
+ continue;
348
+ }
349
+
350
+ if (keys[i] in conf) {
351
+ setter.call(obj, conf[keys[i]]);
352
+ } else {
353
+ setter.call(obj, defaults[keys[i]]);
354
+ }
355
+ }
356
+ };
357
+
358
+ /*
359
+ * Decode from UTF-8
360
+ */
361
+ Util.decodeUTF8 = function (utf8string) {
362
+ "use strict";
363
+ return decodeURIComponent(escape(utf8string));
364
+ };
365
+
366
+
367
+
368
+ /*
369
+ * Cross-browser routines
370
+ */
371
+
372
+
373
+ // Dynamically load scripts without using document.write()
374
+ // Reference: http://unixpapa.com/js/dyna.html
375
+ //
376
+ // Handles the case where load_scripts is invoked from a script that
377
+ // itself is loaded via load_scripts. Once all scripts are loaded the
378
+ // window.onscriptsloaded handler is called (if set).
379
+ Util.get_include_uri = function () {
380
+ return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI : "include/";
381
+ };
382
+ Util._loading_scripts = [];
383
+ Util._pending_scripts = [];
384
+ Util.load_scripts = function (files) {
385
+ "use strict";
386
+ var head = document.getElementsByTagName('head')[0], script,
387
+ ls = Util._loading_scripts, ps = Util._pending_scripts;
388
+
389
+ var loadFunc = function (e) {
390
+ while (ls.length > 0 && (ls[0].readyState === 'loaded' ||
391
+ ls[0].readyState === 'complete')) {
392
+ // For IE, append the script to trigger execution
393
+ var s = ls.shift();
394
+ //console.log("loaded script: " + s.src);
395
+ head.appendChild(s);
396
+ }
397
+ if (!this.readyState ||
398
+ (Util.Engine.presto && this.readyState === 'loaded') ||
399
+ this.readyState === 'complete') {
400
+ if (ps.indexOf(this) >= 0) {
401
+ this.onload = this.onreadystatechange = null;
402
+ //console.log("completed script: " + this.src);
403
+ ps.splice(ps.indexOf(this), 1);
404
+
405
+ // Call window.onscriptsload after last script loads
406
+ if (ps.length === 0 && window.onscriptsload) {
407
+ window.onscriptsload();
408
+ }
409
+ }
410
+ }
411
+ };
412
+
413
+ for (var f = 0; f < files.length; f++) {
414
+ script = document.createElement('script');
415
+ script.type = 'text/javascript';
416
+ script.src = Util.get_include_uri() + files[f];
417
+ //console.log("loading script: " + script.src);
418
+ script.onload = script.onreadystatechange = loadFunc;
419
+ // In-order script execution tricks
420
+ if (Util.Engine.trident) {
421
+ // For IE wait until readyState is 'loaded' before
422
+ // appending it which will trigger execution
423
+ // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
424
+ ls.push(script);
425
+ } else {
426
+ // For webkit and firefox set async=false and append now
427
+ // https://developer.mozilla.org/en-US/docs/HTML/Element/script
428
+ script.async = false;
429
+ head.appendChild(script);
430
+ }
431
+ ps.push(script);
432
+ }
433
+ };
434
+
435
+
436
+ // Get DOM element position on page
437
+ // This solution is based based on http://www.greywyvern.com/?post=331
438
+ // Thanks to Brian Huisman AKA GreyWyvern!
439
+ Util.getPosition = (function () {
440
+ "use strict";
441
+ function getStyle(obj, styleProp) {
442
+ var y;
443
+ if (obj.currentStyle) {
444
+ y = obj.currentStyle[styleProp];
445
+ } else if (window.getComputedStyle)
446
+ y = window.getComputedStyle(obj, null)[styleProp];
447
+ return y;
448
+ }
449
+
450
+ function scrollDist() {
451
+ var myScrollTop = 0, myScrollLeft = 0;
452
+ var html = document.getElementsByTagName('html')[0];
453
+
454
+ // get the scrollTop part
455
+ if (html.scrollTop && document.documentElement.scrollTop) {
456
+ myScrollTop = html.scrollTop;
457
+ } else if (html.scrollTop || document.documentElement.scrollTop) {
458
+ myScrollTop = html.scrollTop + document.documentElement.scrollTop;
459
+ } else if (document.body.scrollTop) {
460
+ myScrollTop = document.body.scrollTop;
461
+ } else {
462
+ myScrollTop = 0;
463
+ }
464
+
465
+ // get the scrollLeft part
466
+ if (html.scrollLeft && document.documentElement.scrollLeft) {
467
+ myScrollLeft = html.scrollLeft;
468
+ } else if (html.scrollLeft || document.documentElement.scrollLeft) {
469
+ myScrollLeft = html.scrollLeft + document.documentElement.scrollLeft;
470
+ } else if (document.body.scrollLeft) {
471
+ myScrollLeft = document.body.scrollLeft;
472
+ } else {
473
+ myScrollLeft = 0;
474
+ }
475
+
476
+ return [myScrollLeft, myScrollTop];
477
+ }
478
+
479
+ return function (obj) {
480
+ var curleft = 0, curtop = 0, scr = obj, fixed = false;
481
+ while ((scr = scr.parentNode) && scr != document.body) {
482
+ curleft -= scr.scrollLeft || 0;
483
+ curtop -= scr.scrollTop || 0;
484
+ if (getStyle(scr, "position") == "fixed") {
485
+ fixed = true;
486
+ }
487
+ }
488
+ if (fixed && !window.opera) {
489
+ var scrDist = scrollDist();
490
+ curleft += scrDist[0];
491
+ curtop += scrDist[1];
492
+ }
493
+
494
+ do {
495
+ curleft += obj.offsetLeft;
496
+ curtop += obj.offsetTop;
497
+ } while ((obj = obj.offsetParent));
498
+
499
+ return {'x': curleft, 'y': curtop};
500
+ };
501
+ })();
502
+
503
+
504
+ // Get mouse event position in DOM element
505
+ Util.getEventPosition = function (e, obj, scale) {
506
+ "use strict";
507
+ var evt, docX, docY, pos;
508
+ //if (!e) evt = window.event;
509
+ evt = (e ? e : window.event);
510
+ evt = (evt.changedTouches ? evt.changedTouches[0] : evt.touches ? evt.touches[0] : evt);
511
+ if (evt.pageX || evt.pageY) {
512
+ docX = evt.pageX;
513
+ docY = evt.pageY;
514
+ } else if (evt.clientX || evt.clientY) {
515
+ docX = evt.clientX + document.body.scrollLeft +
516
+ document.documentElement.scrollLeft;
517
+ docY = evt.clientY + document.body.scrollTop +
518
+ document.documentElement.scrollTop;
519
+ }
520
+ pos = Util.getPosition(obj);
521
+ if (typeof scale === "undefined") {
522
+ scale = 1;
523
+ }
524
+ var realx = docX - pos.x;
525
+ var realy = docY - pos.y;
526
+ var x = Math.max(Math.min(realx, obj.width - 1), 0);
527
+ var y = Math.max(Math.min(realy, obj.height - 1), 0);
528
+ return {'x': x / scale, 'y': y / scale, 'realx': realx / scale, 'realy': realy / scale};
529
+ };
530
+
531
+
532
+ // Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events
533
+ Util.addEvent = function (obj, evType, fn) {
534
+ "use strict";
535
+ if (obj.attachEvent) {
536
+ var r = obj.attachEvent("on" + evType, fn);
537
+ return r;
538
+ } else if (obj.addEventListener) {
539
+ obj.addEventListener(evType, fn, false);
540
+ return true;
541
+ } else {
542
+ throw new Error("Handler could not be attached");
543
+ }
544
+ };
545
+
546
+ Util.removeEvent = function (obj, evType, fn) {
547
+ "use strict";
548
+ if (obj.detachEvent) {
549
+ var r = obj.detachEvent("on" + evType, fn);
550
+ return r;
551
+ } else if (obj.removeEventListener) {
552
+ obj.removeEventListener(evType, fn, false);
553
+ return true;
554
+ } else {
555
+ throw new Error("Handler could not be removed");
556
+ }
557
+ };
558
+
559
+ Util.stopEvent = function (e) {
560
+ "use strict";
561
+ if (e.stopPropagation) { e.stopPropagation(); }
562
+ else { e.cancelBubble = true; }
563
+
564
+ if (e.preventDefault) { e.preventDefault(); }
565
+ else { e.returnValue = false; }
566
+ };
567
+
568
+
569
+ // Set browser engine versions. Based on mootools.
570
+ Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)};
571
+
572
+ (function () {
573
+ "use strict";
574
+ // 'presto': (function () { return (!window.opera) ? false : true; }()),
575
+ var detectPresto = function () {
576
+ return !!window.opera;
577
+ };
578
+
579
+ // 'trident': (function () { return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4);
580
+ var detectTrident = function () {
581
+ if (!window.ActiveXObject) {
582
+ return false;
583
+ } else {
584
+ if (window.XMLHttpRequest) {
585
+ return (document.querySelectorAll) ? 6 : 5;
586
+ } else {
587
+ return 4;
588
+ }
589
+ }
590
+ };
591
+
592
+ // 'webkit': (function () { try { return (navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); } catch (e) { return false; } }()),
593
+ var detectInitialWebkit = function () {
594
+ try {
595
+ if (navigator.taintEnabled) {
596
+ return false;
597
+ } else {
598
+ if (Util.Features.xpath) {
599
+ return (Util.Features.query) ? 525 : 420;
600
+ } else {
601
+ return 419;
602
+ }
603
+ }
604
+ } catch (e) {
605
+ return false;
606
+ }
607
+ };
608
+
609
+ var detectActualWebkit = function (initial_ver) {
610
+ var re = /WebKit\/([0-9\.]*) /;
611
+ var str_ver = (navigator.userAgent.match(re) || ['', initial_ver])[1];
612
+ return parseFloat(str_ver, 10);
613
+ };
614
+
615
+ // 'gecko': (function () { return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19ssName) ? 19 : 18 : 18); }())
616
+ var detectGecko = function () {
617
+ /* jshint -W041 */
618
+ if (!document.getBoxObjectFor && window.mozInnerScreenX == null) {
619
+ return false;
620
+ } else {
621
+ return (document.getElementsByClassName) ? 19 : 18;
622
+ }
623
+ /* jshint +W041 */
624
+ };
625
+
626
+ Util.Engine = {
627
+ // Version detection break in Opera 11.60 (errors on arguments.callee.caller reference)
628
+ //'presto': (function() {
629
+ // return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()),
630
+ 'presto': detectPresto(),
631
+ 'trident': detectTrident(),
632
+ 'webkit': detectInitialWebkit(),
633
+ 'gecko': detectGecko(),
634
+ };
635
+
636
+ if (Util.Engine.webkit) {
637
+ // Extract actual webkit version if available
638
+ Util.Engine.webkit = detectActualWebkit(Util.Engine.webkit);
639
+ }
640
+ })();
641
+
642
+ Util.Flash = (function () {
643
+ "use strict";
644
+ var v, version;
645
+ try {
646
+ v = navigator.plugins['Shockwave Flash'].description;
647
+ } catch (err1) {
648
+ try {
649
+ v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
650
+ } catch (err2) {
651
+ v = '0 r0';
652
+ }
653
+ }
654
+ version = v.match(/\d+/g);
655
+ return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
656
+ }());