/src/utils/env.js

https://github.com/ivmartel/dwv · JavaScript · 278 lines · 150 code · 27 blank · 101 comment · 23 complexity · a9607601d1942968d7c27cd6c0c23cdc MD5 · raw file

  1. // namespaces
  2. var dwv = dwv || {};
  3. /** @namespace */
  4. dwv.env = dwv.env || {};
  5. /**
  6. * Local function to ask Modernizr if a property is supported.
  7. *
  8. * @param {string} property The property to test.
  9. * @returns {boolean} True if the env supports the input feature.
  10. */
  11. dwv.env.askModernizr = function (property) {
  12. if (typeof dwv.Modernizr === 'undefined') {
  13. dwv.ModernizrInit(window, document);
  14. }
  15. var props = property.split('.');
  16. var prop = dwv.Modernizr;
  17. for (var i = 0; i < props.length; ++i) {
  18. prop = prop[props[i]];
  19. }
  20. return prop;
  21. };
  22. /**
  23. * Browser check for the FileAPI.
  24. * Assume support for Safari5.
  25. *
  26. * @returns {boolean} True if the env supports the feature.
  27. */
  28. dwv.env.hasFileApi = function () {
  29. // regular test does not work on Safari 5
  30. var isSafari5 = (navigator.appVersion.indexOf('Safari') !== -1) &&
  31. (navigator.appVersion.indexOf('Chrome') === -1) &&
  32. ((navigator.appVersion.indexOf('5.0.') !== -1) ||
  33. (navigator.appVersion.indexOf('5.1.') !== -1));
  34. if (isSafari5) {
  35. dwv.logger.warn('Assuming FileAPI support for Safari5...');
  36. return true;
  37. }
  38. // regular test
  39. return dwv.env.askModernizr('filereader');
  40. };
  41. /**
  42. * Browser check for the XMLHttpRequest.
  43. *
  44. * @returns {boolean} True if the env supports the feature.
  45. */
  46. dwv.env.hasXmlHttpRequest = function () {
  47. return dwv.env.askModernizr('xhrresponsetype') &&
  48. dwv.env.askModernizr('xhrresponsetypearraybuffer') &&
  49. dwv.env.askModernizr('xhrresponsetypetext') &&
  50. 'XMLHttpRequest' in window && 'withCredentials' in new XMLHttpRequest();
  51. };
  52. /**
  53. * Browser check for typed array.
  54. *
  55. * @returns {boolean} True if the env supports the feature.
  56. */
  57. dwv.env.hasTypedArray = function () {
  58. return dwv.env.askModernizr('dataview') &&
  59. dwv.env.askModernizr('typedarrays');
  60. };
  61. /**
  62. * Browser check for input with type='color'.
  63. * Missing in IE and Safari.
  64. *
  65. * @returns {boolean} True if the env supports the feature.
  66. */
  67. dwv.env.hasInputColor = function () {
  68. return dwv.env.askModernizr('inputtypes.color');
  69. };
  70. /**
  71. * Browser check for input with type='files' and webkitdirectory flag.
  72. * Missing in IE and Safari.
  73. *
  74. * @returns {boolean} True if the env supports the feature.
  75. */
  76. dwv.env.hasInputDirectory = function () {
  77. return dwv.env.askModernizr('fileinputdirectory');
  78. };
  79. //only check at startup (since we propose a replacement)
  80. dwv.env._hasTypedArraySlice =
  81. (typeof Uint8Array.prototype.slice !== 'undefined');
  82. /**
  83. * Browser check for typed array slice method.
  84. * Missing in Internet Explorer 11.
  85. *
  86. * @returns {boolean} True if the env supports the feature.
  87. */
  88. dwv.env.hasTypedArraySlice = function () {
  89. return dwv.env._hasTypedArraySlice;
  90. };
  91. // only check at startup (since we propose a replacement)
  92. dwv.env._hasFloat64Array = ('Float64Array' in window);
  93. /**
  94. * Browser check for Float64Array array.
  95. * Missing in PhantomJS 1.9.20 (on Travis).
  96. *
  97. * @returns {boolean} True if the env supports the feature.
  98. */
  99. dwv.env.hasFloat64Array = function () {
  100. return dwv.env._hasFloat64Array;
  101. };
  102. //only check at startup (since we propose a replacement)
  103. dwv.env._hasClampedArray = ('Uint8ClampedArray' in window);
  104. /**
  105. * Browser check for clamped array.
  106. * Missing in:
  107. * - Safari 5.1.7 for Windows
  108. * - PhantomJS 1.9.20 (on Travis).
  109. *
  110. * @returns {boolean} True if the env supports the feature.
  111. */
  112. dwv.env.hasClampedArray = function () {
  113. return dwv.env._hasClampedArray;
  114. };
  115. /**
  116. * Browser checks to see if it can run dwv. Throws an error if not.
  117. * Silently replaces basic functions.
  118. */
  119. dwv.env.check = function () {
  120. // Required --------------
  121. var message = '';
  122. // Check for the File API support
  123. if (!dwv.env.hasFileApi()) {
  124. message = 'The File APIs are not supported in this browser. ';
  125. throw new Error(message);
  126. }
  127. // Check for XMLHttpRequest
  128. if (!dwv.env.hasXmlHttpRequest()) {
  129. message = 'The XMLHttpRequest is not supported in this browser. ';
  130. throw new Error(message);
  131. }
  132. // Check typed array
  133. if (!dwv.env.hasTypedArray()) {
  134. message = 'The Typed arrays are not supported in this browser. ';
  135. throw new Error(message);
  136. }
  137. // Replaced if not present ------------
  138. // Check typed array slice
  139. if (!dwv.env.hasTypedArraySlice()) {
  140. // silent fail with warning
  141. dwv.logger.warn(
  142. 'The TypedArray.slice method is not supported in this browser.' +
  143. ' This may impair performance. ');
  144. // basic Uint16Array implementation
  145. Uint16Array.prototype.slice = function (begin, end) {
  146. var size = end - begin;
  147. var cloned = new Uint16Array(size);
  148. for (var i = 0; i < size; i++) {
  149. cloned[i] = this[begin + i];
  150. }
  151. return cloned;
  152. };
  153. // basic Int16Array implementation
  154. Int16Array.prototype.slice = function (begin, end) {
  155. var size = end - begin;
  156. var cloned = new Int16Array(size);
  157. for (var i = 0; i < size; i++) {
  158. cloned[i] = this[begin + i];
  159. }
  160. return cloned;
  161. };
  162. // basic Uint8Array implementation
  163. Uint8Array.prototype.slice = function (begin, end) {
  164. var size = end - begin;
  165. var cloned = new Uint8Array(size);
  166. for (var i = 0; i < size; i++) {
  167. cloned[i] = this[begin + i];
  168. }
  169. return cloned;
  170. };
  171. // basic Int8Array implementation
  172. Int8Array.prototype.slice = function (begin, end) {
  173. var size = end - begin;
  174. var cloned = new Int8Array(size);
  175. for (var i = 0; i < size; i++) {
  176. cloned[i] = this[begin + i];
  177. }
  178. return cloned;
  179. };
  180. }
  181. // check clamped array
  182. if (!dwv.env.hasClampedArray()) {
  183. // silent fail with warning
  184. dwv.logger.warn(
  185. 'The Uint8ClampedArray is not supported in this browser.' +
  186. ' This may impair performance. ');
  187. // Use Uint8Array instead... Not good
  188. // TODO Find better replacement!
  189. window.Uint8ClampedArray = window.Uint8Array;
  190. }
  191. // check Float64 array
  192. if (!dwv.env.hasFloat64Array()) {
  193. // silent fail with warning
  194. dwv.logger.warn(
  195. 'The Float64Array is not supported in this browser.' +
  196. ' This may impair performance. ');
  197. // Use Float32Array instead... Not good
  198. // TODO Find better replacement!
  199. window.Float64Array = window.Float32Array;
  200. }
  201. // array Find
  202. // https://tc39.github.io/ecma262/#sec-array.prototype.find
  203. if (!Array.prototype.find) {
  204. Object.defineProperty(Array.prototype, 'find', {
  205. value: function (predicate) {
  206. // 1. Let O be ? ToObject(this value).
  207. if (this === null) {
  208. throw new TypeError('"this" is null or not defined');
  209. }
  210. var o = Object(this);
  211. // 2. Let len be ? ToLength(? Get(O, "length")).
  212. var len = o.length >>> 0;
  213. // 3. If IsCallable(predicate) is false, throw a TypeError exception.
  214. if (typeof predicate !== 'function') {
  215. throw new TypeError('predicate must be a function');
  216. }
  217. // 4. If thisArg was supplied, let T be thisArg; else let T
  218. // be undefined.
  219. var thisArg = arguments[1];
  220. // 5. Let k be 0.
  221. var k = 0;
  222. // 6. Repeat, while k < len
  223. while (k < len) {
  224. // a. Let Pk be ! ToString(k).
  225. // b. Let kValue be ? Get(O, Pk).
  226. // c. Let testResult be ToBoolean(? Call(predicate,
  227. // T, « kValue, k, O »)).
  228. // d. If testResult is true, return kValue.
  229. var kValue = o[k];
  230. if (predicate.call(thisArg, kValue, k, o)) {
  231. return kValue;
  232. }
  233. // e. Increase k by 1.
  234. k++;
  235. }
  236. // 7. Return undefined.
  237. return undefined;
  238. },
  239. configurable: true,
  240. writable: true
  241. });
  242. }
  243. // check string startsWith
  244. if (!String.prototype.startsWith) {
  245. Object.defineProperty(String.prototype, 'startsWith', {
  246. value: function (search, rawPos) {
  247. return dwv.utils.startsWith(this, search, rawPos);
  248. }
  249. });
  250. }
  251. };