a zip code crypto-currency system good for red ONLY

platform.js 41KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. (function (factory) {
  2. if (typeof module === "object" && typeof module.exports === "object") {
  3. var v = factory(require, exports);
  4. if (v !== undefined) module.exports = v;
  5. }
  6. else if (typeof define === "function" && define.amd) {
  7. define(["require", "exports", "@angular/core", "../util/dom", "./query-params", "../util/util"], factory);
  8. }
  9. })(function (require, exports) {
  10. "use strict";
  11. Object.defineProperty(exports, "__esModule", { value: true });
  12. var core_1 = require("@angular/core");
  13. var dom_1 = require("../util/dom");
  14. var query_params_1 = require("./query-params");
  15. var util_1 = require("../util/util");
  16. /**
  17. * @name Platform
  18. * @description
  19. * The Platform service can be used to get information about your current device.
  20. * You can get all of the platforms associated with the device using the [platforms](#platforms)
  21. * method, including whether the app is being viewed from a tablet, if it's
  22. * on a mobile device or browser, and the exact platform (iOS, Android, etc).
  23. * You can also get the orientation of the device, if it uses right-to-left
  24. * language direction, and much much more. With this information you can completely
  25. * customize your app to fit any device.
  26. *
  27. * @usage
  28. * ```ts
  29. * import { Platform } from 'ionic-angular';
  30. *
  31. * @Component({...})
  32. * export MyPage {
  33. * constructor(public platform: Platform) {
  34. *
  35. * }
  36. * }
  37. * ```
  38. * @demo /docs/demos/src/platform/
  39. */
  40. var Platform = (function () {
  41. function Platform() {
  42. var _this = this;
  43. this._versions = {};
  44. this._qp = new query_params_1.QueryParams();
  45. this._bbActions = [];
  46. this._pW = 0;
  47. this._pH = 0;
  48. this._lW = 0;
  49. this._lH = 0;
  50. this._isPortrait = null;
  51. this._uiEvtOpts = false;
  52. /** @internal */
  53. this._platforms = [];
  54. // Events meant to be triggered by the engine
  55. // **********************************************
  56. /**
  57. * @hidden
  58. */
  59. this.backButton = new core_1.EventEmitter();
  60. /**
  61. * The pause event emits when the native platform puts the application
  62. * into the background, typically when the user switches to a different
  63. * application. This event would emit when a Cordova app is put into
  64. * the background, however, it would not fire on a standard web browser.
  65. */
  66. this.pause = new core_1.EventEmitter();
  67. /**
  68. * The resume event emits when the native platform pulls the application
  69. * out from the background. This event would emit when a Cordova app comes
  70. * out from the background, however, it would not fire on a standard web browser.
  71. */
  72. this.resume = new core_1.EventEmitter();
  73. /**
  74. * The resize event emits when the browser window has changed dimensions. This
  75. * could be from a browser window being physically resized, or from a device
  76. * changing orientation.
  77. */
  78. this.resize = new core_1.EventEmitter();
  79. this._readyPromise = new Promise(function (res) { _this._readyResolve = res; });
  80. this.backButton.subscribe(function () {
  81. // the hardware back button event has been fired
  82. (void 0) /* console.debug */;
  83. // decide which backbutton action should run
  84. _this.runBackButtonAction();
  85. });
  86. }
  87. /**
  88. * @hidden
  89. */
  90. Platform.prototype.setWindow = function (win) {
  91. this._win = win;
  92. };
  93. /**
  94. * @hidden
  95. */
  96. Platform.prototype.win = function () {
  97. return this._win;
  98. };
  99. /**
  100. * @hidden
  101. */
  102. Platform.prototype.setDocument = function (doc) {
  103. this._doc = doc;
  104. };
  105. /**
  106. * @hidden
  107. */
  108. Platform.prototype.doc = function () {
  109. return this._doc;
  110. };
  111. /**
  112. * @hidden
  113. */
  114. Platform.prototype.setZone = function (zone) {
  115. this.zone = zone;
  116. };
  117. /**
  118. * @hidden
  119. */
  120. Platform.prototype.setCssProps = function (docElement) {
  121. this.Css = dom_1.getCss(docElement);
  122. };
  123. // Methods
  124. // **********************************************
  125. /**
  126. * @returns {boolean} returns true/false based on platform.
  127. * @description
  128. * Depending on the platform the user is on, `is(platformName)` will
  129. * return `true` or `false`. Note that the same app can return `true`
  130. * for more than one platform name. For example, an app running from
  131. * an iPad would return `true` for the platform names: `mobile`,
  132. * `ios`, `ipad`, and `tablet`. Additionally, if the app was running
  133. * from Cordova then `cordova` would be true, and if it was running
  134. * from a web browser on the iPad then `mobileweb` would be `true`.
  135. *
  136. * ```
  137. * import { Platform } from 'ionic-angular';
  138. *
  139. * @Component({...})
  140. * export MyPage {
  141. * constructor(public platform: Platform) {
  142. * if (this.platform.is('ios')) {
  143. * // This will only print when on iOS
  144. * console.log('I am an iOS device!');
  145. * }
  146. * }
  147. * }
  148. * ```
  149. *
  150. * | Platform Name | Description |
  151. * |-----------------|------------------------------------|
  152. * | android | on a device running Android. |
  153. * | cordova | on a device running Cordova. |
  154. * | core | on a desktop device. |
  155. * | ios | on a device running iOS. |
  156. * | ipad | on an iPad device. |
  157. * | iphone | on an iPhone device. |
  158. * | mobile | on a mobile device. |
  159. * | mobileweb | in a browser on a mobile device. |
  160. * | phablet | on a phablet device. |
  161. * | tablet | on a tablet device. |
  162. * | windows | on a device running Windows. |
  163. *
  164. * @param {string} platformName
  165. */
  166. Platform.prototype.is = function (platformName) {
  167. return (this._platforms.indexOf(platformName) > -1);
  168. };
  169. /**
  170. * @returns {array} the array of platforms
  171. * @description
  172. * Depending on what device you are on, `platforms` can return multiple values.
  173. * Each possible value is a hierarchy of platforms. For example, on an iPhone,
  174. * it would return `mobile`, `ios`, and `iphone`.
  175. *
  176. * ```
  177. * import { Platform } from 'ionic-angular';
  178. *
  179. * @Component({...})
  180. * export MyPage {
  181. * constructor(public platform: Platform) {
  182. * // This will print an array of the current platforms
  183. * console.log(this.platform.platforms());
  184. * }
  185. * }
  186. * ```
  187. */
  188. Platform.prototype.platforms = function () {
  189. // get the array of active platforms, which also knows the hierarchy,
  190. // with the last one the most important
  191. return this._platforms;
  192. };
  193. /**
  194. * Returns an object containing version information about all of the platforms.
  195. *
  196. * ```
  197. * import { Platform } from 'ionic-angular';
  198. *
  199. * @Component({...})
  200. * export MyPage {
  201. * constructor(public platform: Platform) {
  202. * // This will print an object containing
  203. * // all of the platforms and their versions
  204. * console.log(platform.versions());
  205. * }
  206. * }
  207. * ```
  208. *
  209. * @returns {object} An object containing all of the platforms and their versions.
  210. */
  211. Platform.prototype.versions = function () {
  212. // get all the platforms that have a valid parsed version
  213. return this._versions;
  214. };
  215. /**
  216. * @hidden
  217. */
  218. Platform.prototype.version = function () {
  219. for (var platformName in this._versions) {
  220. if (this._versions[platformName]) {
  221. return this._versions[platformName];
  222. }
  223. }
  224. return {};
  225. };
  226. /**
  227. * Returns a promise when the platform is ready and native functionality
  228. * can be called. If the app is running from within a web browser, then
  229. * the promise will resolve when the DOM is ready. When the app is running
  230. * from an application engine such as Cordova, then the promise will
  231. * resolve when Cordova triggers the `deviceready` event.
  232. *
  233. * The resolved value is the `readySource`, which states which platform
  234. * ready was used. For example, when Cordova is ready, the resolved ready
  235. * source is `cordova`. The default ready source value will be `dom`. The
  236. * `readySource` is useful if different logic should run depending on the
  237. * platform the app is running from. For example, only Cordova can execute
  238. * the status bar plugin, so the web should not run status bar plugin logic.
  239. *
  240. * ```
  241. * import { Component } from '@angular/core';
  242. * import { Platform } from 'ionic-angular';
  243. *
  244. * @Component({...})
  245. * export MyApp {
  246. * constructor(public platform: Platform) {
  247. * this.platform.ready().then((readySource) => {
  248. * console.log('Platform ready from', readySource);
  249. * // Platform now ready, execute any required native code
  250. * });
  251. * }
  252. * }
  253. * ```
  254. * @returns {promise}
  255. */
  256. Platform.prototype.ready = function () {
  257. return this._readyPromise;
  258. };
  259. /**
  260. * @hidden
  261. * This should be triggered by the engine when the platform is
  262. * ready. If there was no custom prepareReady method from the engine,
  263. * such as Cordova or Electron, then it uses the default DOM ready.
  264. */
  265. Platform.prototype.triggerReady = function (readySource) {
  266. var _this = this;
  267. this.zone.run(function () {
  268. _this._readyResolve(readySource);
  269. });
  270. };
  271. /**
  272. * @hidden
  273. * This is the default prepareReady if it's not replaced by an engine,
  274. * such as Cordova or Electron. If there was no custom prepareReady
  275. * method from an engine then it uses the method below, which triggers
  276. * the platform ready on the DOM ready event, and the default resolved
  277. * value is `dom`.
  278. */
  279. Platform.prototype.prepareReady = function () {
  280. var self = this;
  281. if (self._doc.readyState === 'complete' || self._doc.readyState === 'interactive') {
  282. self.triggerReady('dom');
  283. }
  284. else {
  285. self._doc.addEventListener('DOMContentLoaded', completed, false);
  286. self._win.addEventListener('load', completed, false);
  287. }
  288. function completed() {
  289. self._doc.removeEventListener('DOMContentLoaded', completed, false);
  290. self._win.removeEventListener('load', completed, false);
  291. self.triggerReady('dom');
  292. }
  293. };
  294. /**
  295. * Set the app's language direction, which will update the `dir` attribute
  296. * on the app's root `<html>` element. We recommend the app's `index.html`
  297. * file already has the correct `dir` attribute value set, such as
  298. * `<html dir="ltr">` or `<html dir="rtl">`. This method is useful if the
  299. * direction needs to be dynamically changed per user/session.
  300. * [W3C: Structural markup and right-to-left text in HTML](http://www.w3.org/International/questions/qa-html-dir)
  301. * @param {DocumentDirection} dir Examples: `rtl`, `ltr`
  302. * @param {boolean} updateDocument
  303. */
  304. Platform.prototype.setDir = function (dir, updateDocument) {
  305. this._dir = dir;
  306. this.isRTL = (dir === 'rtl');
  307. if (updateDocument !== false) {
  308. this._doc['documentElement'].setAttribute('dir', dir);
  309. }
  310. };
  311. /**
  312. * Returns app's language direction.
  313. * We recommend the app's `index.html` file already has the correct `dir`
  314. * attribute value set, such as `<html dir="ltr">` or `<html dir="rtl">`.
  315. * [W3C: Structural markup and right-to-left text in HTML](http://www.w3.org/International/questions/qa-html-dir)
  316. * @returns {DocumentDirection}
  317. */
  318. Platform.prototype.dir = function () {
  319. return this._dir;
  320. };
  321. /**
  322. * Set the app's language and optionally the country code, which will update
  323. * the `lang` attribute on the app's root `<html>` element.
  324. * We recommend the app's `index.html` file already has the correct `lang`
  325. * attribute value set, such as `<html lang="en">`. This method is useful if
  326. * the language needs to be dynamically changed per user/session.
  327. * [W3C: Declaring language in HTML](http://www.w3.org/International/questions/qa-html-language-declarations)
  328. * @param {string} language Examples: `en-US`, `en-GB`, `ar`, `de`, `zh`, `es-MX`
  329. * @param {boolean} updateDocument Specifies whether the `lang` attribute of `<html>` should be updated
  330. */
  331. Platform.prototype.setLang = function (language, updateDocument) {
  332. this._lang = language;
  333. if (updateDocument !== false) {
  334. this._doc['documentElement'].setAttribute('lang', language);
  335. }
  336. };
  337. /**
  338. * Returns app's language and optional country code.
  339. * We recommend the app's `index.html` file already has the correct `lang`
  340. * attribute value set, such as `<html lang="en">`.
  341. * [W3C: Declaring language in HTML](http://www.w3.org/International/questions/qa-html-language-declarations)
  342. * @returns {string}
  343. */
  344. Platform.prototype.lang = function () {
  345. return this._lang;
  346. };
  347. // Methods meant to be overridden by the engine
  348. // **********************************************
  349. // Provided NOOP methods so they do not error when
  350. // called by engines (the browser)that do not provide them
  351. /**
  352. * @hidden
  353. */
  354. Platform.prototype.exitApp = function () { };
  355. /**
  356. * The back button event is triggered when the user presses the native
  357. * platform's back button, also referred to as the "hardware" back button.
  358. * This event is only used within Cordova apps running on Android and
  359. * Windows platforms. This event is not fired on iOS since iOS doesn't come
  360. * with a hardware back button in the same sense an Android or Windows device
  361. * does.
  362. *
  363. * Registering a hardware back button action and setting a priority allows
  364. * apps to control which action should be called when the hardware back
  365. * button is pressed. This method decides which of the registered back button
  366. * actions has the highest priority and should be called.
  367. *
  368. * @param {Function} fn Called when the back button is pressed,
  369. * if this registered action has the highest priority.
  370. * @param {number} priority Set the priority for this action. Only the highest priority will execute. Defaults to `0`.
  371. * @returns {Function} A function that, when called, will unregister
  372. * the back button action.
  373. */
  374. Platform.prototype.registerBackButtonAction = function (fn, priority) {
  375. var _this = this;
  376. if (priority === void 0) { priority = 0; }
  377. var action = { fn: fn, priority: priority };
  378. this._bbActions.push(action);
  379. // return a function to unregister this back button action
  380. return function () {
  381. util_1.removeArrayItem(_this._bbActions, action);
  382. };
  383. };
  384. /**
  385. * @hidden
  386. */
  387. Platform.prototype.runBackButtonAction = function () {
  388. // decide which one back button action should run
  389. var winner = null;
  390. this._bbActions.forEach(function (action) {
  391. if (!winner || action.priority >= winner.priority) {
  392. winner = action;
  393. }
  394. });
  395. // run the winning action if there is one
  396. winner && winner.fn && winner.fn();
  397. };
  398. // Getter/Setter Methods
  399. // **********************************************
  400. /**
  401. * @hidden
  402. */
  403. Platform.prototype.setUserAgent = function (userAgent) {
  404. this._ua = userAgent;
  405. };
  406. /**
  407. * @hidden
  408. */
  409. Platform.prototype.setQueryParams = function (url) {
  410. this._qp.parseUrl(url);
  411. };
  412. /**
  413. * Get the query string parameter
  414. */
  415. Platform.prototype.getQueryParam = function (key) {
  416. return this._qp.get(key);
  417. };
  418. /**
  419. * Get the current url.
  420. */
  421. Platform.prototype.url = function () {
  422. return this._win['location']['href'];
  423. };
  424. /**
  425. * @hidden
  426. */
  427. Platform.prototype.userAgent = function () {
  428. return this._ua || '';
  429. };
  430. /**
  431. * @hidden
  432. */
  433. Platform.prototype.setNavigatorPlatform = function (navigatorPlt) {
  434. this._nPlt = navigatorPlt;
  435. };
  436. /**
  437. * @hidden
  438. */
  439. Platform.prototype.navigatorPlatform = function () {
  440. return this._nPlt || '';
  441. };
  442. /**
  443. * Gets the width of the platform's viewport using `window.innerWidth`.
  444. * Using this method is preferred since the dimension is a cached value,
  445. * which reduces the chance of multiple and expensive DOM reads.
  446. */
  447. Platform.prototype.width = function () {
  448. this._calcDim();
  449. return this._isPortrait ? this._pW : this._lW;
  450. };
  451. /**
  452. * Gets the height of the platform's viewport using `window.innerHeight`.
  453. * Using this method is preferred since the dimension is a cached value,
  454. * which reduces the chance of multiple and expensive DOM reads.
  455. */
  456. Platform.prototype.height = function () {
  457. this._calcDim();
  458. return this._isPortrait ? this._pH : this._lH;
  459. };
  460. /**
  461. * @hidden
  462. */
  463. Platform.prototype.getElementComputedStyle = function (ele, pseudoEle) {
  464. return this._win['getComputedStyle'](ele, pseudoEle);
  465. };
  466. /**
  467. * @hidden
  468. */
  469. Platform.prototype.getElementFromPoint = function (x, y) {
  470. return this._doc['elementFromPoint'](x, y);
  471. };
  472. /**
  473. * @hidden
  474. */
  475. Platform.prototype.getElementBoundingClientRect = function (ele) {
  476. return ele['getBoundingClientRect']();
  477. };
  478. /**
  479. * Returns `true` if the app is in portait mode.
  480. */
  481. Platform.prototype.isPortrait = function () {
  482. this._calcDim();
  483. return this._isPortrait;
  484. };
  485. /**
  486. * Returns `true` if the app is in landscape mode.
  487. */
  488. Platform.prototype.isLandscape = function () {
  489. return !this.isPortrait();
  490. };
  491. Platform.prototype._calcDim = function () {
  492. // we're caching window dimensions so that
  493. // we're not forcing many layouts
  494. // if _isPortrait is null then that means
  495. // the dimensions needs to be looked up again
  496. // this also has to cover an edge case that only
  497. // happens on iOS 10 (not other versions of iOS)
  498. // where window.innerWidth is always bigger than
  499. // window.innerHeight when it is first measured,
  500. // even when the device is in portrait but
  501. // the second time it is measured it is correct.
  502. // Hopefully this check will not be needed in the future
  503. if (this._isPortrait === null || this._isPortrait === false && this._win['innerWidth'] < this._win['innerHeight']) {
  504. var win = this._win;
  505. var innerWidth = win['innerWidth'];
  506. var innerHeight = win['innerHeight'];
  507. // we're keeping track of portrait and landscape dimensions
  508. // separately because the virtual keyboard can really mess
  509. // up accurate values when the keyboard is up
  510. if (win.screen.width > 0 && win.screen.height > 0) {
  511. if (innerWidth < innerHeight) {
  512. // the device is in portrait
  513. // we have to do fancier checking here
  514. // because of the virtual keyboard resizing
  515. // the window
  516. if (this._pW <= innerWidth) {
  517. (void 0) /* console.debug */;
  518. this._isPortrait = true;
  519. this._pW = innerWidth;
  520. }
  521. if (this._pH <= innerHeight) {
  522. (void 0) /* console.debug */;
  523. this._isPortrait = true;
  524. this._pH = innerHeight;
  525. }
  526. }
  527. else {
  528. // the device is in landscape
  529. if (this._lW !== innerWidth) {
  530. (void 0) /* console.debug */;
  531. this._isPortrait = false;
  532. this._lW = innerWidth;
  533. }
  534. if (this._lH !== innerHeight) {
  535. (void 0) /* console.debug */;
  536. this._isPortrait = false;
  537. this._lH = innerHeight;
  538. }
  539. }
  540. }
  541. }
  542. };
  543. /**
  544. * @hidden
  545. * This requestAnimationFrame will NOT be wrapped by zone.
  546. */
  547. Platform.prototype.raf = function (callback) {
  548. var win = this._win;
  549. return win['__zone_symbol__requestAnimationFrame'](callback);
  550. };
  551. /**
  552. * @hidden
  553. */
  554. Platform.prototype.cancelRaf = function (rafId) {
  555. var win = this._win;
  556. return win['__zone_symbol__cancelAnimationFrame'](rafId);
  557. };
  558. /**
  559. * @hidden
  560. * This setTimeout will NOT be wrapped by zone.
  561. */
  562. Platform.prototype.timeout = function (callback, timeout) {
  563. var win = this._win;
  564. return win['__zone_symbol__setTimeout'](callback, timeout);
  565. };
  566. /**
  567. * @hidden
  568. * This setTimeout will NOT be wrapped by zone.
  569. */
  570. Platform.prototype.cancelTimeout = function (timeoutId) {
  571. var win = this._win;
  572. win['__zone_symbol__clearTimeout'](timeoutId);
  573. };
  574. /**
  575. * @hidden
  576. * Built to use modern event listener options, like "passive".
  577. * If options are not supported, then just return a boolean which
  578. * represents "capture". Returns a method to remove the listener.
  579. */
  580. Platform.prototype.registerListener = function (ele, eventName, callback, opts, unregisterListenersCollection) {
  581. // use event listener options when supported
  582. // otherwise it's just a boolean for the "capture" arg
  583. var listenerOpts = this._uiEvtOpts ? {
  584. 'capture': !!opts.capture,
  585. 'passive': !!opts.passive,
  586. } : !!opts.capture;
  587. var unReg;
  588. if (!opts.zone && ele['__zone_symbol__addEventListener']) {
  589. // do not wrap this event in zone and we've verified we can use the raw addEventListener
  590. ele['__zone_symbol__addEventListener'](eventName, callback, listenerOpts);
  591. unReg = function unregisterListener() {
  592. ele['__zone_symbol__removeEventListener'](eventName, callback, listenerOpts);
  593. };
  594. }
  595. else {
  596. // use the native addEventListener, which is wrapped with zone
  597. ele['addEventListener'](eventName, callback, listenerOpts);
  598. unReg = function unregisterListener() {
  599. ele['removeEventListener'](eventName, callback, listenerOpts);
  600. };
  601. }
  602. if (unregisterListenersCollection) {
  603. unregisterListenersCollection.push(unReg);
  604. }
  605. return unReg;
  606. };
  607. /**
  608. * @hidden
  609. */
  610. Platform.prototype.transitionEnd = function (el, callback, zone) {
  611. if (zone === void 0) { zone = true; }
  612. var unRegs = [];
  613. function unregister() {
  614. unRegs.forEach(function (unReg) {
  615. unReg();
  616. });
  617. }
  618. function onTransitionEnd(ev) {
  619. if (el === ev.target) {
  620. unregister();
  621. callback(ev);
  622. }
  623. }
  624. if (el) {
  625. this.registerListener(el, 'webkitTransitionEnd', onTransitionEnd, { zone: zone }, unRegs);
  626. this.registerListener(el, 'transitionend', onTransitionEnd, { zone: zone }, unRegs);
  627. }
  628. return unregister;
  629. };
  630. /**
  631. * @hidden
  632. */
  633. Platform.prototype.windowLoad = function (callback) {
  634. var win = this._win;
  635. var doc = this._doc;
  636. var unreg;
  637. if (doc.readyState === 'complete') {
  638. callback(win, doc);
  639. }
  640. else {
  641. unreg = this.registerListener(win, 'load', function () {
  642. unreg && unreg();
  643. callback(win, doc);
  644. }, { zone: false });
  645. }
  646. };
  647. /**
  648. * @hidden
  649. */
  650. Platform.prototype.isActiveElement = function (ele) {
  651. return !!(ele && (this.getActiveElement() === ele));
  652. };
  653. /**
  654. * @hidden
  655. */
  656. Platform.prototype.getActiveElement = function () {
  657. return this._doc['activeElement'];
  658. };
  659. /**
  660. * @hidden
  661. */
  662. Platform.prototype.hasFocus = function (ele) {
  663. return !!((ele && (this.getActiveElement() === ele)) && (ele.parentElement.querySelector(':focus') === ele));
  664. };
  665. /**
  666. * @hidden
  667. */
  668. Platform.prototype.hasFocusedTextInput = function () {
  669. var ele = this.getActiveElement();
  670. if (dom_1.isTextInput(ele)) {
  671. return (ele.parentElement.querySelector(':focus') === ele);
  672. }
  673. return false;
  674. };
  675. /**
  676. * @hidden
  677. */
  678. Platform.prototype.focusOutActiveElement = function () {
  679. var activeElement = this.getActiveElement();
  680. activeElement && activeElement.blur && activeElement.blur();
  681. };
  682. Platform.prototype._initEvents = function () {
  683. var _this = this;
  684. // Test via a getter in the options object to see if the passive property is accessed
  685. try {
  686. var opts = Object.defineProperty({}, 'passive', {
  687. get: function () {
  688. _this._uiEvtOpts = true;
  689. }
  690. });
  691. this._win.addEventListener('optsTest', null, opts);
  692. }
  693. catch (e) { }
  694. // add the window resize event listener XXms after
  695. this.timeout(function () {
  696. var timerId;
  697. _this.registerListener(_this._win, 'resize', function () {
  698. clearTimeout(timerId);
  699. timerId = setTimeout(function () {
  700. // setting _isPortrait to null means the
  701. // dimensions will need to be looked up again
  702. if (_this.hasFocusedTextInput() === false) {
  703. _this._isPortrait = null;
  704. }
  705. _this.zone.run(function () { return _this.resize.emit(); });
  706. }, 200);
  707. }, { passive: true, zone: false });
  708. }, 2000);
  709. };
  710. // Platform Registry
  711. // **********************************************
  712. /**
  713. * @hidden
  714. */
  715. Platform.prototype.setPlatformConfigs = function (platformConfigs) {
  716. this._registry = platformConfigs || {};
  717. };
  718. /**
  719. * @hidden
  720. */
  721. Platform.prototype.getPlatformConfig = function (platformName) {
  722. return this._registry[platformName] || {};
  723. };
  724. /**
  725. * @hidden
  726. */
  727. Platform.prototype.registry = function () {
  728. return this._registry;
  729. };
  730. /**
  731. * @hidden
  732. */
  733. Platform.prototype.setDefault = function (platformName) {
  734. this._default = platformName;
  735. };
  736. /**
  737. * @hidden
  738. */
  739. Platform.prototype.testQuery = function (queryValue, queryTestValue) {
  740. var valueSplit = queryValue.toLowerCase().split(';');
  741. return valueSplit.indexOf(queryTestValue) > -1;
  742. };
  743. /**
  744. * @hidden
  745. */
  746. Platform.prototype.testNavigatorPlatform = function (navigatorPlatformExpression) {
  747. var rgx = new RegExp(navigatorPlatformExpression, 'i');
  748. return rgx.test(this._nPlt);
  749. };
  750. /**
  751. * @hidden
  752. */
  753. Platform.prototype.matchUserAgentVersion = function (userAgentExpression) {
  754. if (this._ua && userAgentExpression) {
  755. var val = this._ua.match(userAgentExpression);
  756. if (val) {
  757. return {
  758. major: val[1],
  759. minor: val[2]
  760. };
  761. }
  762. }
  763. };
  764. Platform.prototype.testUserAgent = function (expression) {
  765. if (this._ua) {
  766. return this._ua.indexOf(expression) >= 0;
  767. }
  768. return false;
  769. };
  770. /**
  771. * @hidden
  772. */
  773. Platform.prototype.isPlatformMatch = function (queryStringName, userAgentAtLeastHas, userAgentMustNotHave) {
  774. if (userAgentMustNotHave === void 0) { userAgentMustNotHave = []; }
  775. var queryValue = this._qp.get('ionicplatform');
  776. if (queryValue) {
  777. return this.testQuery(queryValue, queryStringName);
  778. }
  779. userAgentAtLeastHas = userAgentAtLeastHas || [queryStringName];
  780. var userAgent = this._ua.toLowerCase();
  781. for (var i = 0; i < userAgentAtLeastHas.length; i++) {
  782. if (userAgent.indexOf(userAgentAtLeastHas[i]) > -1) {
  783. for (var j = 0; j < userAgentMustNotHave.length; j++) {
  784. if (userAgent.indexOf(userAgentMustNotHave[j]) > -1) {
  785. return false;
  786. }
  787. }
  788. return true;
  789. }
  790. }
  791. return false;
  792. };
  793. /** @hidden */
  794. Platform.prototype.init = function () {
  795. this._initEvents();
  796. var rootPlatformNode;
  797. var enginePlatformNode;
  798. // figure out the most specific platform and active engine
  799. var tmpPlt;
  800. for (var platformName in this._registry) {
  801. tmpPlt = this.matchPlatform(platformName);
  802. if (tmpPlt) {
  803. // we found a platform match!
  804. // check if its more specific than the one we already have
  805. if (tmpPlt.isEngine) {
  806. // because it matched then this should be the active engine
  807. // you cannot have more than one active engine
  808. enginePlatformNode = tmpPlt;
  809. }
  810. else if (!rootPlatformNode || tmpPlt.depth > rootPlatformNode.depth) {
  811. // only find the root node for platforms that are not engines
  812. // set this node as the root since we either don't already
  813. // have one, or this one is more specific that the current one
  814. rootPlatformNode = tmpPlt;
  815. }
  816. }
  817. }
  818. if (!rootPlatformNode) {
  819. rootPlatformNode = new PlatformNode(this._registry, this._default);
  820. }
  821. // build a Platform instance filled with the
  822. // hierarchy of active platforms and settings
  823. if (rootPlatformNode) {
  824. // check if we found an engine node (cordova/node-webkit/etc)
  825. if (enginePlatformNode) {
  826. // add the engine to the first in the platform hierarchy
  827. // the original rootPlatformNode now becomes a child
  828. // of the engineNode, which is not the new root
  829. enginePlatformNode.child = rootPlatformNode;
  830. rootPlatformNode.parent = enginePlatformNode;
  831. rootPlatformNode = enginePlatformNode;
  832. }
  833. var platformNode = rootPlatformNode;
  834. while (platformNode) {
  835. insertSuperset(this._registry, platformNode);
  836. platformNode = platformNode.child;
  837. }
  838. // make sure the root noot is actually the root
  839. // incase a node was inserted before the root
  840. platformNode = rootPlatformNode.parent;
  841. while (platformNode) {
  842. rootPlatformNode = platformNode;
  843. platformNode = platformNode.parent;
  844. }
  845. platformNode = rootPlatformNode;
  846. while (platformNode) {
  847. platformNode.initialize(this);
  848. // extra check for ipad pro issue
  849. // https://forums.developer.apple.com/thread/25948
  850. if (platformNode.name === 'iphone' && this.navigatorPlatform() === 'iPad') {
  851. // this is an ipad pro so push ipad and tablet to platforms
  852. // and then return as we are done
  853. this._platforms.push('tablet');
  854. this._platforms.push('ipad');
  855. return;
  856. }
  857. // set the array of active platforms with
  858. // the last one in the array the most important
  859. this._platforms.push(platformNode.name);
  860. // get the platforms version if a version parser was provided
  861. this._versions[platformNode.name] = platformNode.version(this);
  862. // go to the next platform child
  863. platformNode = platformNode.child;
  864. }
  865. }
  866. if (this._platforms.indexOf('mobile') > -1 && this._platforms.indexOf('cordova') === -1) {
  867. this._platforms.push('mobileweb');
  868. }
  869. };
  870. /**
  871. * @hidden
  872. */
  873. Platform.prototype.matchPlatform = function (platformName) {
  874. // build a PlatformNode and assign config data to it
  875. // use it's getRoot method to build up its hierarchy
  876. // depending on which platforms match
  877. var platformNode = new PlatformNode(this._registry, platformName);
  878. var rootNode = platformNode.getRoot(this);
  879. if (rootNode) {
  880. rootNode.depth = 0;
  881. var childPlatform = rootNode.child;
  882. while (childPlatform) {
  883. rootNode.depth++;
  884. childPlatform = childPlatform.child;
  885. }
  886. }
  887. return rootNode;
  888. };
  889. return Platform;
  890. }());
  891. exports.Platform = Platform;
  892. function insertSuperset(registry, platformNode) {
  893. var supersetPlaformName = platformNode.superset();
  894. if (supersetPlaformName) {
  895. // add a platform in between two exist platforms
  896. // so we can build the correct hierarchy of active platforms
  897. var supersetPlatform = new PlatformNode(registry, supersetPlaformName);
  898. supersetPlatform.parent = platformNode.parent;
  899. supersetPlatform.child = platformNode;
  900. if (supersetPlatform.parent) {
  901. supersetPlatform.parent.child = supersetPlatform;
  902. }
  903. platformNode.parent = supersetPlatform;
  904. }
  905. }
  906. /**
  907. * @hidden
  908. */
  909. var PlatformNode = (function () {
  910. function PlatformNode(registry, platformName) {
  911. this.registry = registry;
  912. this.c = registry[platformName];
  913. this.name = platformName;
  914. this.isEngine = this.c.isEngine;
  915. }
  916. PlatformNode.prototype.settings = function () {
  917. return this.c.settings || {};
  918. };
  919. PlatformNode.prototype.superset = function () {
  920. return this.c.superset;
  921. };
  922. PlatformNode.prototype.isMatch = function (p) {
  923. return this.c.isMatch && this.c.isMatch(p) || false;
  924. };
  925. PlatformNode.prototype.initialize = function (plt) {
  926. this.c.initialize && this.c.initialize(plt);
  927. };
  928. PlatformNode.prototype.version = function (plt) {
  929. if (this.c.versionParser) {
  930. var v = this.c.versionParser(plt);
  931. if (v) {
  932. var str = v.major + '.' + v.minor;
  933. return {
  934. str: str,
  935. num: parseFloat(str),
  936. major: parseInt(v.major, 10),
  937. minor: parseInt(v.minor, 10)
  938. };
  939. }
  940. }
  941. };
  942. PlatformNode.prototype.getRoot = function (plt) {
  943. if (this.isMatch(plt)) {
  944. var parents = this.getSubsetParents(this.name);
  945. if (!parents.length) {
  946. return this;
  947. }
  948. var platformNode = null;
  949. var rootPlatformNode = null;
  950. for (var i = 0; i < parents.length; i++) {
  951. platformNode = new PlatformNode(this.registry, parents[i]);
  952. platformNode.child = this;
  953. rootPlatformNode = platformNode.getRoot(plt);
  954. if (rootPlatformNode) {
  955. this.parent = platformNode;
  956. return rootPlatformNode;
  957. }
  958. }
  959. }
  960. return null;
  961. };
  962. PlatformNode.prototype.getSubsetParents = function (subsetPlatformName) {
  963. var parentPlatformNames = [];
  964. var pltConfig = null;
  965. for (var platformName in this.registry) {
  966. pltConfig = this.registry[platformName];
  967. if (pltConfig.subsets && pltConfig.subsets.indexOf(subsetPlatformName) > -1) {
  968. parentPlatformNames.push(platformName);
  969. }
  970. }
  971. return parentPlatformNames;
  972. };
  973. return PlatformNode;
  974. }());
  975. /**
  976. * @hidden
  977. */
  978. function setupPlatform(doc, platformConfigs, zone) {
  979. var plt = new Platform();
  980. plt.setDefault('core');
  981. plt.setPlatformConfigs(platformConfigs);
  982. plt.setZone(zone);
  983. // set values from "document"
  984. var docElement = doc.documentElement;
  985. plt.setDocument(doc);
  986. var dir = docElement.dir;
  987. plt.setDir(dir === 'rtl' ? 'rtl' : 'ltr', !dir);
  988. plt.setLang(docElement.lang, false);
  989. // set css properties
  990. plt.setCssProps(docElement);
  991. // set values from "window"
  992. var win = doc.defaultView;
  993. plt.setWindow(win);
  994. plt.setNavigatorPlatform(win.navigator.platform);
  995. plt.setUserAgent(win.navigator.userAgent);
  996. // set location values
  997. plt.setQueryParams(win.location.href);
  998. plt.init();
  999. // add the platform obj to the window
  1000. win['Ionic'] = win['Ionic'] || {};
  1001. win['Ionic']['platform'] = plt;
  1002. return plt;
  1003. }
  1004. exports.setupPlatform = setupPlatform;
  1005. });
  1006. //# sourceMappingURL=platform.js.map