util.js 7.5 KB

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