util.js 7.0 KB

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