platform.es5.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /**
  2. * @license
  3. * Copyright Google LLC All Rights Reserved.
  4. *
  5. * Use of this source code is governed by an MIT-style license that can be
  6. * found in the LICENSE file at https://angular.io/license
  7. */
  8. import { Inject, Injectable, Optional, PLATFORM_ID, NgModule, ɵɵdefineInjectable, ɵɵinject } from '@angular/core';
  9. import { isPlatformBrowser } from '@angular/common';
  10. /**
  11. * @fileoverview added by tsickle
  12. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  13. */
  14. // Whether the current platform supports the V8 Break Iterator. The V8 check
  15. // is necessary to detect all Blink based browsers.
  16. /** @type {?} */
  17. var hasV8BreakIterator;
  18. // We need a try/catch around the reference to `Intl`, because accessing it in some cases can
  19. // cause IE to throw. These cases are tied to particular versions of Windows and can happen if
  20. // the consumer is providing a polyfilled `Map`. See:
  21. // https://github.com/Microsoft/ChakraCore/issues/3189
  22. // https://github.com/angular/components/issues/15687
  23. try {
  24. hasV8BreakIterator = (typeof Intl !== 'undefined' && ((/** @type {?} */ (Intl))).v8BreakIterator);
  25. }
  26. catch (_a) {
  27. hasV8BreakIterator = false;
  28. }
  29. /**
  30. * Service to detect the current platform by comparing the userAgent strings and
  31. * checking browser-specific global properties.
  32. */
  33. var Platform = /** @class */ (function () {
  34. /**
  35. * @breaking-change 8.0.0 remove optional decorator
  36. */
  37. function Platform(_platformId) {
  38. this._platformId = _platformId;
  39. /**
  40. * Whether the Angular application is being rendered in the browser.
  41. * We want to use the Angular platform check because if the Document is shimmed
  42. * without the navigator, the following checks will fail. This is preferred because
  43. * sometimes the Document may be shimmed without the user's knowledge or intention
  44. */
  45. this.isBrowser = this._platformId ?
  46. isPlatformBrowser(this._platformId) : typeof document === 'object' && !!document;
  47. /**
  48. * Whether the current browser is Microsoft Edge.
  49. */
  50. this.EDGE = this.isBrowser && /(edge)/i.test(navigator.userAgent);
  51. /**
  52. * Whether the current rendering engine is Microsoft Trident.
  53. */
  54. this.TRIDENT = this.isBrowser && /(msie|trident)/i.test(navigator.userAgent);
  55. /**
  56. * Whether the current rendering engine is Blink.
  57. */
  58. // EdgeHTML and Trident mock Blink specific things and need to be excluded from this check.
  59. this.BLINK = this.isBrowser && (!!(((/** @type {?} */ (window))).chrome || hasV8BreakIterator) &&
  60. typeof CSS !== 'undefined' && !this.EDGE && !this.TRIDENT);
  61. /**
  62. * Whether the current rendering engine is WebKit.
  63. */
  64. // Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to
  65. // ensure that Webkit runs standalone and is not used as another engine's base.
  66. this.WEBKIT = this.isBrowser &&
  67. /AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT;
  68. /**
  69. * Whether the current platform is Apple iOS.
  70. */
  71. this.IOS = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) &&
  72. !('MSStream' in window);
  73. /**
  74. * Whether the current browser is Firefox.
  75. */
  76. // It's difficult to detect the plain Gecko engine, because most of the browsers identify
  77. // them self as Gecko-like browsers and modify the userAgent's according to that.
  78. // Since we only cover one explicit Firefox case, we can simply check for Firefox
  79. // instead of having an unstable check for Gecko.
  80. this.FIREFOX = this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent);
  81. /**
  82. * Whether the current platform is Android.
  83. */
  84. // Trident on mobile adds the android platform to the userAgent to trick detections.
  85. this.ANDROID = this.isBrowser && /android/i.test(navigator.userAgent) && !this.TRIDENT;
  86. /**
  87. * Whether the current browser is Safari.
  88. */
  89. // Safari browsers will include the Safari keyword in their userAgent. Some browsers may fake
  90. // this and just place the Safari keyword in the userAgent. To be more safe about Safari every
  91. // Safari browser should also use Webkit as its layout engine.
  92. this.SAFARI = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT;
  93. }
  94. Platform.decorators = [
  95. { type: Injectable, args: [{ providedIn: 'root' },] },
  96. ];
  97. /** @nocollapse */
  98. Platform.ctorParameters = function () { return [
  99. { type: Object, decorators: [{ type: Optional }, { type: Inject, args: [PLATFORM_ID,] }] }
  100. ]; };
  101. /** @nocollapse */ Platform.ngInjectableDef = ɵɵdefineInjectable({ factory: function Platform_Factory() { return new Platform(ɵɵinject(PLATFORM_ID, 8)); }, token: Platform, providedIn: "root" });
  102. return Platform;
  103. }());
  104. /**
  105. * @fileoverview added by tsickle
  106. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  107. */
  108. var PlatformModule = /** @class */ (function () {
  109. function PlatformModule() {
  110. }
  111. PlatformModule.decorators = [
  112. { type: NgModule, args: [{},] },
  113. ];
  114. return PlatformModule;
  115. }());
  116. /**
  117. * @fileoverview added by tsickle
  118. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  119. */
  120. /**
  121. * Cached result Set of input types support by the current browser.
  122. * @type {?}
  123. */
  124. var supportedInputTypes;
  125. /**
  126. * Types of `<input>` that *might* be supported.
  127. * @type {?}
  128. */
  129. var candidateInputTypes = [
  130. // `color` must come first. Chrome 56 shows a warning if we change the type to `color` after
  131. // first changing it to something else:
  132. // The specified value "" does not conform to the required format.
  133. // The format is "#rrggbb" where rr, gg, bb are two-digit hexadecimal numbers.
  134. 'color',
  135. 'button',
  136. 'checkbox',
  137. 'date',
  138. 'datetime-local',
  139. 'email',
  140. 'file',
  141. 'hidden',
  142. 'image',
  143. 'month',
  144. 'number',
  145. 'password',
  146. 'radio',
  147. 'range',
  148. 'reset',
  149. 'search',
  150. 'submit',
  151. 'tel',
  152. 'text',
  153. 'time',
  154. 'url',
  155. 'week',
  156. ];
  157. /**
  158. * @return {?} The input types supported by this browser.
  159. */
  160. function getSupportedInputTypes() {
  161. // Result is cached.
  162. if (supportedInputTypes) {
  163. return supportedInputTypes;
  164. }
  165. // We can't check if an input type is not supported until we're on the browser, so say that
  166. // everything is supported when not on the browser. We don't use `Platform` here since it's
  167. // just a helper function and can't inject it.
  168. if (typeof document !== 'object' || !document) {
  169. supportedInputTypes = new Set(candidateInputTypes);
  170. return supportedInputTypes;
  171. }
  172. /** @type {?} */
  173. var featureTestInput = document.createElement('input');
  174. supportedInputTypes = new Set(candidateInputTypes.filter((/**
  175. * @param {?} value
  176. * @return {?}
  177. */
  178. function (value) {
  179. featureTestInput.setAttribute('type', value);
  180. return featureTestInput.type === value;
  181. })));
  182. return supportedInputTypes;
  183. }
  184. /**
  185. * @fileoverview added by tsickle
  186. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  187. */
  188. /**
  189. * Cached result of whether the user's browser supports passive event listeners.
  190. * @type {?}
  191. */
  192. var supportsPassiveEvents;
  193. /**
  194. * Checks whether the user's browser supports passive event listeners.
  195. * See: https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
  196. * @return {?}
  197. */
  198. function supportsPassiveEventListeners() {
  199. if (supportsPassiveEvents == null && typeof window !== 'undefined') {
  200. try {
  201. window.addEventListener('test', (/** @type {?} */ (null)), Object.defineProperty({}, 'passive', {
  202. get: (/**
  203. * @return {?}
  204. */
  205. function () { return supportsPassiveEvents = true; })
  206. }));
  207. }
  208. finally {
  209. supportsPassiveEvents = supportsPassiveEvents || false;
  210. }
  211. }
  212. return supportsPassiveEvents;
  213. }
  214. /**
  215. * Normalizes an `AddEventListener` object to something that can be passed
  216. * to `addEventListener` on any browser, no matter whether it supports the
  217. * `options` parameter.
  218. * @param {?} options Object to be normalized.
  219. * @return {?}
  220. */
  221. function normalizePassiveListenerOptions(options) {
  222. return supportsPassiveEventListeners() ? options : !!options.capture;
  223. }
  224. /**
  225. * @fileoverview added by tsickle
  226. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  227. */
  228. /** @enum {number} */
  229. var RtlScrollAxisType = {
  230. /**
  231. * scrollLeft is 0 when scrolled all the way left and (scrollWidth - clientWidth) when scrolled
  232. * all the way right.
  233. */
  234. NORMAL: 0,
  235. /**
  236. * scrollLeft is -(scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled
  237. * all the way right.
  238. */
  239. NEGATED: 1,
  240. /**
  241. * scrollLeft is (scrollWidth - clientWidth) when scrolled all the way left and 0 when scrolled
  242. * all the way right.
  243. */
  244. INVERTED: 2,
  245. };
  246. RtlScrollAxisType[RtlScrollAxisType.NORMAL] = 'NORMAL';
  247. RtlScrollAxisType[RtlScrollAxisType.NEGATED] = 'NEGATED';
  248. RtlScrollAxisType[RtlScrollAxisType.INVERTED] = 'INVERTED';
  249. /**
  250. * Cached result of the way the browser handles the horizontal scroll axis in RTL mode.
  251. * @type {?}
  252. */
  253. var rtlScrollAxisType;
  254. /**
  255. * Check whether the browser supports scroll behaviors.
  256. * @return {?}
  257. */
  258. function supportsScrollBehavior() {
  259. return !!(typeof document == 'object' && 'scrollBehavior' in (/** @type {?} */ (document.documentElement)).style);
  260. }
  261. /**
  262. * Checks the type of RTL scroll axis used by this browser. As of time of writing, Chrome is NORMAL,
  263. * Firefox & Safari are NEGATED, and IE & Edge are INVERTED.
  264. * @return {?}
  265. */
  266. function getRtlScrollAxisType() {
  267. // We can't check unless we're on the browser. Just assume 'normal' if we're not.
  268. if (typeof document !== 'object' || !document) {
  269. return RtlScrollAxisType.NORMAL;
  270. }
  271. if (!rtlScrollAxisType) {
  272. // Create a 1px wide scrolling container and a 2px wide content element.
  273. /** @type {?} */
  274. var scrollContainer = document.createElement('div');
  275. /** @type {?} */
  276. var containerStyle = scrollContainer.style;
  277. scrollContainer.dir = 'rtl';
  278. containerStyle.height = '1px';
  279. containerStyle.width = '1px';
  280. containerStyle.overflow = 'auto';
  281. containerStyle.visibility = 'hidden';
  282. containerStyle.pointerEvents = 'none';
  283. containerStyle.position = 'absolute';
  284. /** @type {?} */
  285. var content = document.createElement('div');
  286. /** @type {?} */
  287. var contentStyle = content.style;
  288. contentStyle.width = '2px';
  289. contentStyle.height = '1px';
  290. scrollContainer.appendChild(content);
  291. document.body.appendChild(scrollContainer);
  292. rtlScrollAxisType = RtlScrollAxisType.NORMAL;
  293. // The viewport starts scrolled all the way to the right in RTL mode. If we are in a NORMAL
  294. // browser this would mean that the scrollLeft should be 1. If it's zero instead we know we're
  295. // dealing with one of the other two types of browsers.
  296. if (scrollContainer.scrollLeft === 0) {
  297. // In a NEGATED browser the scrollLeft is always somewhere in [-maxScrollAmount, 0]. For an
  298. // INVERTED browser it is always somewhere in [0, maxScrollAmount]. We can determine which by
  299. // setting to the scrollLeft to 1. This is past the max for a NEGATED browser, so it will
  300. // return 0 when we read it again.
  301. scrollContainer.scrollLeft = 1;
  302. rtlScrollAxisType =
  303. scrollContainer.scrollLeft === 0 ? RtlScrollAxisType.NEGATED : RtlScrollAxisType.INVERTED;
  304. }
  305. (/** @type {?} */ (scrollContainer.parentNode)).removeChild(scrollContainer);
  306. }
  307. return rtlScrollAxisType;
  308. }
  309. /**
  310. * @fileoverview added by tsickle
  311. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  312. */
  313. /** @type {?} */
  314. var shadowDomIsSupported;
  315. /**
  316. * Checks whether the user's browser support Shadow DOM.
  317. * @return {?}
  318. */
  319. function _supportsShadowDom() {
  320. if (shadowDomIsSupported == null) {
  321. /** @type {?} */
  322. var head = typeof document !== 'undefined' ? document.head : null;
  323. shadowDomIsSupported = !!(head && (((/** @type {?} */ (head))).createShadowRoot || head.attachShadow));
  324. }
  325. return shadowDomIsSupported;
  326. }
  327. /**
  328. * @fileoverview added by tsickle
  329. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  330. */
  331. /**
  332. * @fileoverview added by tsickle
  333. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  334. */
  335. export { Platform, PlatformModule, getSupportedInputTypes, supportsPassiveEventListeners, normalizePassiveListenerOptions, supportsScrollBehavior, getRtlScrollAxisType, RtlScrollAxisType, _supportsShadowDom };
  336. //# sourceMappingURL=platform.es5.js.map