util.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * noVNC: HTML5 VNC client
  3. * Copyright (C) 2010 Joel Martin
  4. * Licensed under LGPL-3 (see LICENSE.LGPL-3)
  5. *
  6. * See README.md for usage and integration instructions.
  7. */
  8. "use strict";
  9. /*jslint bitwise: false, white: false */
  10. /*global window, document, navigator, ActiveXObject*/
  11. // Globals defined here
  12. var Util = {}, $;
  13. // Debug routines
  14. if (typeof window.console === "undefined") {
  15. window.console = {
  16. 'log': function(m) {},
  17. 'warn': function(m) {},
  18. 'error': function(m) {}};
  19. }
  20. if (/__debug__$/i.test(document.location.href)) {
  21. if (typeof window.opera !== "undefined") {
  22. window.console.log = window.opera.postError;
  23. window.console.warn = window.opera.postError;
  24. window.console.error = window.opera.postError;
  25. }
  26. } else {
  27. /*
  28. // non-debug mode, an empty function
  29. window.console.log = function (message) {};
  30. window.console.warn = function (message) {};
  31. window.console.error = function (message) {};
  32. */
  33. }
  34. // Simple DOM selector by ID
  35. if (!window.$) {
  36. $ = function (id) {
  37. if (document.getElementById) {
  38. return document.getElementById(id);
  39. } else if (document.all) {
  40. return document.all[id];
  41. } else if (document.layers) {
  42. return document.layers[id];
  43. }
  44. return undefined;
  45. };
  46. }
  47. /*
  48. * Make arrays quack
  49. */
  50. Array.prototype.shift8 = function () {
  51. return this.shift();
  52. };
  53. Array.prototype.push8 = function (num) {
  54. this.push(num & 0xFF);
  55. };
  56. Array.prototype.shift16 = function () {
  57. return (this.shift() << 8) +
  58. (this.shift() );
  59. };
  60. Array.prototype.push16 = function (num) {
  61. this.push((num >> 8) & 0xFF,
  62. (num ) & 0xFF );
  63. };
  64. Array.prototype.shift32 = function () {
  65. return (this.shift() << 24) +
  66. (this.shift() << 16) +
  67. (this.shift() << 8) +
  68. (this.shift() );
  69. };
  70. Array.prototype.get32 = function (off) {
  71. return (this[off ] << 24) +
  72. (this[off + 1] << 16) +
  73. (this[off + 2] << 8) +
  74. (this[off + 3] );
  75. };
  76. Array.prototype.push32 = function (num) {
  77. this.push((num >> 24) & 0xFF,
  78. (num >> 16) & 0xFF,
  79. (num >> 8) & 0xFF,
  80. (num ) & 0xFF );
  81. };
  82. Array.prototype.shiftStr = function (len) {
  83. var arr = this.splice(0, len);
  84. return arr.map(function (num) {
  85. return String.fromCharCode(num); } ).join('');
  86. };
  87. Array.prototype.pushStr = function (str) {
  88. var i, n = str.length;
  89. for (i=0; i < n; i+=1) {
  90. this.push(str.charCodeAt(i));
  91. }
  92. };
  93. Array.prototype.shiftBytes = function (len) {
  94. return this.splice(0, len);
  95. };
  96. /*
  97. * ------------------------------------------------------
  98. * Namespaced in Util
  99. * ------------------------------------------------------
  100. */
  101. Util.dirObj = function (obj, depth, parent) {
  102. var i, msg = "", val = "";
  103. if (! depth) { depth=2; }
  104. if (! parent) { parent= ""; }
  105. // Print the properties of the passed-in object
  106. for (i in obj) {
  107. if ((depth > 1) && (typeof obj[i] === "object")) {
  108. // Recurse attributes that are objects
  109. msg += Util.dirObj(obj[i], depth-1, parent + "." + i);
  110. } else {
  111. //val = new String(obj[i]).replace("\n", " ");
  112. val = obj[i].toString().replace("\n", " ");
  113. if (val.length > 30) {
  114. val = val.substr(0,30) + "...";
  115. }
  116. msg += parent + "." + i + ": " + val + "\n";
  117. }
  118. }
  119. return msg;
  120. };
  121. /*
  122. * Cross-browser routines
  123. */
  124. // Get DOM element position on page
  125. Util.getPosition = function (obj) {
  126. var x = 0, y = 0;
  127. if (obj.offsetParent) {
  128. do {
  129. x += obj.offsetLeft;
  130. y += obj.offsetTop;
  131. obj = obj.offsetParent;
  132. } while (obj);
  133. }
  134. return {'x': x, 'y': y};
  135. };
  136. // Get mouse event position in DOM element
  137. Util.getEventPosition = function (e, obj) {
  138. var evt, docX, docY, pos;
  139. //if (!e) evt = window.event;
  140. evt = (e ? e : window.event);
  141. if (evt.pageX || evt.pageY) {
  142. docX = evt.pageX;
  143. docY = evt.pageY;
  144. } else if (evt.clientX || evt.clientY) {
  145. docX = evt.clientX + document.body.scrollLeft +
  146. document.documentElement.scrollLeft;
  147. docY = evt.clientY + document.body.scrollTop +
  148. document.documentElement.scrollTop;
  149. }
  150. pos = Util.getPosition(obj);
  151. return {'x': docX - pos.x, 'y': docY - pos.y};
  152. };
  153. // Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events
  154. Util.addEvent = function (obj, evType, fn){
  155. if (obj.addEventListener){
  156. obj.addEventListener(evType, fn, false);
  157. return true;
  158. } else if (obj.attachEvent){
  159. var r = obj.attachEvent("on"+evType, fn);
  160. return r;
  161. } else {
  162. throw("Handler could not be attached");
  163. }
  164. };
  165. Util.removeEvent = function(obj, evType, fn){
  166. if (obj.removeEventListener){
  167. obj.removeEventListener(evType, fn, false);
  168. return true;
  169. } else if (obj.detachEvent){
  170. var r = obj.detachEvent("on"+evType, fn);
  171. return r;
  172. } else {
  173. throw("Handler could not be removed");
  174. }
  175. };
  176. Util.stopEvent = function(e) {
  177. if (e.stopPropagation) { e.stopPropagation(); }
  178. else { e.cancelBubble = true; }
  179. if (e.preventDefault) { e.preventDefault(); }
  180. else { e.returnValue = false; }
  181. };
  182. // Set browser engine versions. Based on mootools.
  183. Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)};
  184. Util.Engine = {
  185. 'presto': (function() {
  186. return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()),
  187. 'trident': (function() {
  188. return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); }()),
  189. 'webkit': (function() {
  190. try { return (navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); } catch (e) { return false; } }()),
  191. //'webkit': (function() {
  192. // return ((typeof navigator.taintEnabled !== "unknown") && navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); }()),
  193. 'gecko': (function() {
  194. return (!document.getBoxObjectFor && !window.mozInnerScreenX) ? false : ((document.getElementsByClassName) ? 19 : 18); }())
  195. };
  196. Util.Flash = (function(){
  197. var v, version;
  198. try {
  199. v = navigator.plugins['Shockwave Flash'].description;
  200. } catch(err1) {
  201. try {
  202. v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
  203. } catch(err2) {
  204. v = '0 r0';
  205. }
  206. }
  207. version = v.match(/\d+/g);
  208. return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
  209. }());