ts/util/BrowserUtil.ts - StructureJS

StructureJS

0.15.2

A class based utility library for building modular and scalable web platform applications. Features opt-in classes and utilities which provide a solid foundation and toolset to build your next project.

File: ts/util/BrowserUtil.ts

  1. import EventDispatcher from '../event/EventDispatcher';
  2. import BaseEvent from '../event/BaseEvent';
  3. import Util from '../util/Util';
  4.  
  5. /**
  6. * A helper class to detect OS and browsers.
  7. *
  8. * @class BrowserUtil
  9. * @module StructureJS
  10. * @submodule util
  11. * @author Robert S. (www.codeBelt.com)
  12. * @static
  13. */
  14. class BrowserUtil
  15. {
  16. /**
  17. * A reference to the EventDispatcher object.
  18. *
  19. * @property _eventDispatcher
  20. * @type {EventDispatcher}
  21. * @private
  22. * @static
  23. */
  24. private static _eventDispatcher:EventDispatcher = new EventDispatcher();
  25.  
  26. /**
  27. * A reference to the browser window object.
  28. *
  29. * @property _window
  30. * @type {Window}
  31. * @private
  32. * @static
  33. */
  34. private static _window:Window = window;
  35.  
  36. /**
  37. * A reference to the getComputedStyle method.
  38. *
  39. * @property _styleDeclaration
  40. * @type {any}
  41. * @private
  42. * @static
  43. */
  44. private static _styleDeclaration:any = window.getComputedStyle(document.querySelector('body'), ':after');
  45.  
  46. /**
  47. * TODO: YUIDoc_comment
  48. *
  49. * @property _onBreakpointChangeHandler
  50. * @type {any}
  51. * @private
  52. * @static
  53. */
  54. private static _onBreakpointChangeHandler:any = null;
  55.  
  56. /**
  57. * The delay in milliseconds for the Util.{{#crossLink "Util/debounce:method"}}{{/crossLink}} method that dispatches
  58. * the BaseEvent.RESIZE event to get the your browser breakpoints. See {{#crossLink "BrowserUtil/getBreakpoint:method"}}{{/crossLink}}.
  59. *
  60. * @property debounceDelay
  61. * @type {number}
  62. * @default 250
  63. * @public
  64. * @static
  65. */
  66. public static debounceDelay:number = 250;
  67.  
  68. /**
  69. * The isEnabled property is used to keep track of the enabled state of listening for Breakpoint changes.
  70. *
  71. * @property isEnabled
  72. * @type {boolean}
  73. * @public
  74. * @static
  75. */
  76. public static isEnabled:boolean = false;
  77.  
  78. constructor()
  79. {
  80. throw new Error('[BrowserUtil] Do not instantiate the BrowserUtil class because it is a static class.');
  81. }
  82.  
  83. /**
  84. * Dispatches a breakpoint event.
  85. *
  86. * @method enable
  87. * @public
  88. * @static
  89. */
  90. public static enable():void
  91. {
  92. if (BrowserUtil.isEnabled === true)
  93. {
  94. return;
  95. }
  96.  
  97. BrowserUtil._onBreakpointChangeHandler = Util.debounce(BrowserUtil._onBreakpointChange, BrowserUtil.debounceDelay, false, BrowserUtil);
  98. BrowserUtil._window.addEventListener('resize', BrowserUtil._onBreakpointChangeHandler);
  99.  
  100. BrowserUtil.isEnabled = true;
  101. }
  102.  
  103. /**
  104. * @overridden EventDispatcher.disable
  105. */
  106. public static disable():void
  107. {
  108. if (BrowserUtil.isEnabled === false)
  109. {
  110. return;
  111. }
  112.  
  113. BrowserUtil._window.removeEventListener('resize', BrowserUtil._onBreakpointChangeHandler);
  114.  
  115. BrowserUtil.isEnabled = false;
  116. }
  117.  
  118. /**
  119. * Returns the name of the browser.
  120. *
  121. * @method browserName
  122. * @return {string}
  123. * @public
  124. * @static
  125. * @example
  126. * BrowserUtil.browserName();
  127. * // 'Chrome'
  128. */
  129. public static browserName():string
  130. {
  131. return BrowserUtil.getBrowser()[0];
  132. }
  133.  
  134. /**
  135. * Returns the version of the browser.
  136. *
  137. * @method browserVersion
  138. * @param [majorVersion=true] {boolean}
  139. * @return {number|string}
  140. * @public
  141. * @static
  142. * @example
  143. * BrowserUtil.browserVersion();
  144. * // 39
  145. *
  146. * BrowserUtil.browserVersion(false);
  147. * // '39.0.2171.99'
  148. */
  149. public static browserVersion(majorVersion:boolean = true):any
  150. {
  151. const version:string = BrowserUtil.getBrowser()[1];
  152.  
  153. if (majorVersion === true)
  154. {
  155. return parseInt(version, 10);
  156. }
  157. else
  158. {
  159. return version;
  160. }
  161. }
  162.  
  163. /**
  164. * Gets the browser name a user agent.
  165. *
  166. * @method getBrowser
  167. * @public
  168. * @return {Array.<string>}
  169. * @static
  170. * @example
  171. * BrowserUtil.getBrowser();
  172. * // ["Chrome", "39.0.2171.99"]
  173. */
  174. public static getBrowser():Array<string>
  175. {
  176. const N = navigator.appName;
  177. const ua = navigator.userAgent;
  178. const tem = ua.match(/version\/([\.\d]+)/i);
  179. let M = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
  180.  
  181. if (M && tem != null)
  182. {
  183. M[2] = tem[1];
  184. }
  185.  
  186. M = M ? [M[1], M[2]] : [N, navigator.appVersion, '-?'];
  187.  
  188. return M;
  189. }
  190.  
  191. /**
  192. * Determines if the device OS is Android.
  193. *
  194. * @method isAndroid
  195. * @returns {boolean}
  196. * @public
  197. * @static
  198. * @example
  199. * BrowserUtil.isAndroid();
  200. * // false
  201. */
  202. public static isAndroid():boolean
  203. {
  204. return !!navigator.userAgent.match(/Android/i);
  205. }
  206.  
  207. /**
  208. * Determines if the device OS is Android.
  209. *
  210. * @method isBlackBerry
  211. * @returns {boolean}
  212. * @public
  213. * @static
  214. * @example
  215. * BrowserUtil.isBlackBerry();
  216. * // false
  217. */
  218. public static isBlackBerry():boolean
  219. {
  220. return Boolean(!!navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/BB10; Touch/));
  221. }
  222.  
  223. /**
  224. * Determines if the device OS is IOS.
  225. *
  226. * @method isIOS
  227. * @returns {boolean}
  228. * @public
  229. * @static
  230. * @example
  231. * BrowserUtil.isIOS();
  232. * // false
  233. */
  234. public static isIOS():boolean
  235. {
  236. return !!navigator.userAgent.match(/iPhone|iPad|iPod/i);
  237. }
  238.  
  239. /**
  240. * Determines if the device OS is Opera Mini.
  241. *
  242. * @method isOperaMini
  243. * @returns {boolean}
  244. * @public
  245. * @static
  246. * @example
  247. * BrowserUtil.isOperaMini();
  248. * // false
  249. */
  250. public static isOperaMini():boolean
  251. {
  252. return !!navigator.userAgent.match(/Opera Mini/i);
  253. }
  254.  
  255. /**
  256. * Determines if the device OS is IE Mobile.
  257. *
  258. * @method isIEMobile
  259. * @returns {boolean}
  260. * @public
  261. * @static
  262. * @example
  263. * BrowserUtil.isIEMobile();
  264. * // false
  265. */
  266. public static isIEMobile():boolean
  267. {
  268. return !!navigator.userAgent.match(/IEMobile/i);
  269. }
  270.  
  271. /**
  272. * Determines if the it is run on a mobile or desktop device.
  273. *
  274. * @method isMobile
  275. * @returns {boolean}
  276. * @public
  277. * @static
  278. * @example
  279. * BrowserUtil.isMobile();
  280. * // false
  281. */
  282. public static isMobile():boolean
  283. {
  284. return (BrowserUtil.isAndroid() || BrowserUtil.isBlackBerry() || BrowserUtil.isIOS() || BrowserUtil.isOperaMini() || BrowserUtil.isIEMobile());
  285. }
  286.  
  287. /**
  288. * Determines if the browser can you Browser History push states.
  289. *
  290. * @method hasBrowserHistory
  291. * @returns {boolean}
  292. * @public
  293. * @static
  294. * @example
  295. * BrowserUtil.hasBrowserHistory();
  296. * // true
  297. */
  298. public static hasBrowserHistory():boolean
  299. {
  300. return !!(window.history && history.pushState);
  301. }
  302.  
  303. /**
  304. * Determines if the browser can you Local Storage.
  305. *
  306. * @method hasLocalStorage
  307. * @returns {boolean}
  308. * @public
  309. * @static
  310. * @example
  311. * BrowserUtil.hasLocalStorage();
  312. * // true
  313. */
  314. public static hasLocalStorage():boolean
  315. {
  316. try
  317. {
  318. return ('localStorage' in window) && window.localStorage !== null;
  319. }
  320. catch (error)
  321. {
  322. return false;
  323. }
  324. }
  325.  
  326. /**
  327. * Determines if the browser can you Session Storage.
  328. *
  329. * @method hasSessionStorage
  330. * @returns {boolean}
  331. * @public
  332. * @static
  333. * @example
  334. * BrowserUtil.hasSessionStorage();
  335. * // true
  336. */
  337. public static hasSessionStorage():boolean
  338. {
  339. try
  340. {
  341. return ('sessionStorage' in window) && window.sessionStorage !== null;
  342. }
  343. catch (error)
  344. {
  345. return false;
  346. }
  347. }
  348.  
  349. /**
  350. * Get the current breakpoint from the style sheets. You must add a body:after property with a specific content
  351. * in each of your style sheets for this functionality to work.
  352. *
  353. * @method getBreakpoint
  354. * @returns {string} The string value of the current style sheet.
  355. * @public
  356. * @static
  357. * @example
  358. * // For each of your different style sheets add something like below:
  359. * // screen_lg.css
  360. * body:after {
  361. * content: 'screen_lg'; width: 1px; height: 1px; padding: 0; margin: -1px; border: 0; position: absolute; clip: rect(0 0 0 0); overflow: hidden;
  362. * }
  363. * // screen_sm.css
  364. * body:after {
  365. * content: 'screen_sm'; width: 1px; height: 1px; padding: 0; margin: -1px; border: 0; position: absolute; clip: rect(0 0 0 0); overflow: hidden;
  366. * }
  367. *
  368. * BrowserUtil.getBreakpoint();
  369. * // 'screen_lg'
  370. *
  371. * // Add a listener to get notified when the browser is resized:
  372. * BrowserUtil.addEventListener(BaseEvent.RESIZE, this._onBreakpointChange, this);
  373. * ...
  374. * _onBreakpointChange(baseEvent) {
  375. * console.log(baseEvent.data);
  376. * // 'screen_sm'
  377. * }
  378. */
  379. public static getBreakpoint()
  380. {
  381. return BrowserUtil._styleDeclaration.getPropertyValue('content').replace(/["']/g, '');
  382. }
  383.  
  384. /**
  385. * TODO: YUIDoc_comment
  386. *
  387. * @method addEventListener
  388. * @public
  389. * @static
  390. */
  391. public static addEventListener(type:string, callback:Function, scope:any, priority:number = 0):void
  392. {
  393. BrowserUtil._eventDispatcher.addEventListener(type, callback, scope, priority);
  394. BrowserUtil.enable();
  395. }
  396.  
  397. /**
  398. * TODO: YUIDoc_comment
  399. *
  400. * @method removeEventListener
  401. * @public
  402. * @static
  403. */
  404. public static removeEventListener(type:string, callback:Function, scope:any):void
  405. {
  406. BrowserUtil._eventDispatcher.removeEventListener(type, callback, scope);
  407. }
  408.  
  409. /**
  410. * TODO: YUIDoc_comment
  411. *
  412. * @method dispatchEvent
  413. * @public
  414. * @static
  415. */
  416. public static dispatchEvent(type:any, data:any = null):void
  417. {
  418. let event:any = type;
  419.  
  420. if (typeof event === 'string')
  421. {
  422. event = new BaseEvent(type, false, false, data);
  423. }
  424.  
  425. event.target = BrowserUtil;
  426. event.currentTarget = BrowserUtil;
  427.  
  428. BrowserUtil._eventDispatcher.dispatchEvent(event);
  429. }
  430.  
  431. /**
  432. * Dispatches a breakpoint event.
  433. *
  434. * @method _onBreakpointChange
  435. * @private
  436. * @static
  437. */
  438. private static _onBreakpointChange(event)
  439. {
  440. BrowserUtil.dispatchEvent(new BaseEvent(BaseEvent.RESIZE, true, false, BrowserUtil.getBreakpoint()));
  441. }
  442.  
  443. }
  444.  
  445. export default BrowserUtil;
  446.