| /** |
| * @license Angular v5.2.0 |
| * (c) 2010-2018 Google, Inc. https://angular.io/ |
| * License: MIT |
| */ |
| import { CommonModule, DOCUMENT, PlatformLocation, ɵPLATFORM_BROWSER_ID, ɵparseCookieValue } from '@angular/common'; |
| import { APP_ID, APP_INITIALIZER, ApplicationInitStatus, ApplicationModule, ApplicationRef, ErrorHandler, Inject, Injectable, InjectionToken, Injector, NgModule, NgProbeToken, NgZone, Optional, PLATFORM_ID, PLATFORM_INITIALIZER, RendererFactory2, RendererStyleFlags2, Sanitizer, SecurityContext, SkipSelf, Testability, Version, ViewEncapsulation, createPlatformFactory, getDebugNode, isDevMode, platformCore, setTestabilityGetter, ɵglobal } from '@angular/core'; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| let _DOM = /** @type {?} */ ((null)); |
| /** |
| * @return {?} |
| */ |
| function getDOM() { |
| return _DOM; |
| } |
| /** |
| * @param {?} adapter |
| * @return {?} |
| */ |
| |
| /** |
| * @param {?} adapter |
| * @return {?} |
| */ |
| function setRootDomAdapter(adapter) { |
| if (!_DOM) { |
| _DOM = adapter; |
| } |
| } |
| /** |
| * Provides DOM operations in an environment-agnostic way. |
| * |
| * \@security Tread carefully! Interacting with the DOM directly is dangerous and |
| * can introduce XSS risks. |
| * @abstract |
| */ |
| class DomAdapter { |
| constructor() { |
| this.resourceLoaderType = /** @type {?} */ ((null)); |
| } |
| /** |
| * Maps attribute names to their corresponding property names for cases |
| * where attribute name doesn't match property name. |
| * @return {?} |
| */ |
| get attrToPropMap() { return this._attrToPropMap; } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| set attrToPropMap(value) { this._attrToPropMap = value; } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * Provides DOM operations in any browser environment. |
| * |
| * \@security Tread carefully! Interacting with the DOM directly is dangerous and |
| * can introduce XSS risks. |
| * @abstract |
| */ |
| class GenericBrowserDomAdapter extends DomAdapter { |
| constructor() { |
| super(); |
| this._animationPrefix = null; |
| this._transitionEnd = null; |
| try { |
| const /** @type {?} */ element = this.createElement('div', document); |
| if (this.getStyle(element, 'animationName') != null) { |
| this._animationPrefix = ''; |
| } |
| else { |
| const /** @type {?} */ domPrefixes = ['Webkit', 'Moz', 'O', 'ms']; |
| for (let /** @type {?} */ i = 0; i < domPrefixes.length; i++) { |
| if (this.getStyle(element, domPrefixes[i] + 'AnimationName') != null) { |
| this._animationPrefix = '-' + domPrefixes[i].toLowerCase() + '-'; |
| break; |
| } |
| } |
| } |
| const /** @type {?} */ transEndEventNames = { |
| WebkitTransition: 'webkitTransitionEnd', |
| MozTransition: 'transitionend', |
| OTransition: 'oTransitionEnd otransitionend', |
| transition: 'transitionend' |
| }; |
| Object.keys(transEndEventNames).forEach((key) => { |
| if (this.getStyle(element, key) != null) { |
| this._transitionEnd = transEndEventNames[key]; |
| } |
| }); |
| } |
| catch (/** @type {?} */ e) { |
| this._animationPrefix = null; |
| this._transitionEnd = null; |
| } |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getDistributedNodes(el) { return (/** @type {?} */ (el)).getDistributedNodes(); } |
| /** |
| * @param {?} el |
| * @param {?} baseUrl |
| * @param {?} href |
| * @return {?} |
| */ |
| resolveAndSetHref(el, baseUrl, href) { |
| el.href = href == null ? baseUrl : baseUrl + '/../' + href; |
| } |
| /** |
| * @return {?} |
| */ |
| supportsDOMEvents() { return true; } |
| /** |
| * @return {?} |
| */ |
| supportsNativeShadowDOM() { |
| return typeof (/** @type {?} */ (document.body)).createShadowRoot === 'function'; |
| } |
| /** |
| * @return {?} |
| */ |
| getAnimationPrefix() { return this._animationPrefix ? this._animationPrefix : ''; } |
| /** |
| * @return {?} |
| */ |
| getTransitionEnd() { return this._transitionEnd ? this._transitionEnd : ''; } |
| /** |
| * @return {?} |
| */ |
| supportsAnimation() { |
| return this._animationPrefix != null && this._transitionEnd != null; |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const _attrToPropMap = { |
| 'class': 'className', |
| 'innerHtml': 'innerHTML', |
| 'readonly': 'readOnly', |
| 'tabindex': 'tabIndex', |
| }; |
| const DOM_KEY_LOCATION_NUMPAD = 3; |
| // Map to convert some key or keyIdentifier values to what will be returned by getEventKey |
| const _keyMap = { |
| // The following values are here for cross-browser compatibility and to match the W3C standard |
| // cf http://www.w3.org/TR/DOM-Level-3-Events-key/ |
| '\b': 'Backspace', |
| '\t': 'Tab', |
| '\x7F': 'Delete', |
| '\x1B': 'Escape', |
| 'Del': 'Delete', |
| 'Esc': 'Escape', |
| 'Left': 'ArrowLeft', |
| 'Right': 'ArrowRight', |
| 'Up': 'ArrowUp', |
| 'Down': 'ArrowDown', |
| 'Menu': 'ContextMenu', |
| 'Scroll': 'ScrollLock', |
| 'Win': 'OS' |
| }; |
| // There is a bug in Chrome for numeric keypad keys: |
| // https://code.google.com/p/chromium/issues/detail?id=155654 |
| // 1, 2, 3 ... are reported as A, B, C ... |
| const _chromeNumKeyPadMap = { |
| 'A': '1', |
| 'B': '2', |
| 'C': '3', |
| 'D': '4', |
| 'E': '5', |
| 'F': '6', |
| 'G': '7', |
| 'H': '8', |
| 'I': '9', |
| 'J': '*', |
| 'K': '+', |
| 'M': '-', |
| 'N': '.', |
| 'O': '/', |
| '\x60': '0', |
| '\x90': 'NumLock' |
| }; |
| let nodeContains; |
| if (ɵglobal['Node']) { |
| nodeContains = ɵglobal['Node'].prototype.contains || function (node) { |
| return !!(this.compareDocumentPosition(node) & 16); |
| }; |
| } |
| /** |
| * A `DomAdapter` powered by full browser DOM APIs. |
| * |
| * \@security Tread carefully! Interacting with the DOM directly is dangerous and |
| * can introduce XSS risks. |
| */ |
| class BrowserDomAdapter extends GenericBrowserDomAdapter { |
| /** |
| * @param {?} templateHtml |
| * @return {?} |
| */ |
| parse(templateHtml) { throw new Error('parse not implemented'); } |
| /** |
| * @return {?} |
| */ |
| static makeCurrent() { setRootDomAdapter(new BrowserDomAdapter()); } |
| /** |
| * @param {?} element |
| * @param {?} name |
| * @return {?} |
| */ |
| hasProperty(element, name) { return name in element; } |
| /** |
| * @param {?} el |
| * @param {?} name |
| * @param {?} value |
| * @return {?} |
| */ |
| setProperty(el, name, value) { (/** @type {?} */ (el))[name] = value; } |
| /** |
| * @param {?} el |
| * @param {?} name |
| * @return {?} |
| */ |
| getProperty(el, name) { return (/** @type {?} */ (el))[name]; } |
| /** |
| * @param {?} el |
| * @param {?} methodName |
| * @param {?} args |
| * @return {?} |
| */ |
| invoke(el, methodName, args) { (/** @type {?} */ (el))[methodName](...args); } |
| /** |
| * @param {?} error |
| * @return {?} |
| */ |
| logError(error) { |
| if (window.console) { |
| if (console.error) { |
| console.error(error); |
| } |
| else { |
| console.log(error); |
| } |
| } |
| } |
| /** |
| * @param {?} error |
| * @return {?} |
| */ |
| log(error) { |
| if (window.console) { |
| window.console.log && window.console.log(error); |
| } |
| } |
| /** |
| * @param {?} error |
| * @return {?} |
| */ |
| logGroup(error) { |
| if (window.console) { |
| window.console.group && window.console.group(error); |
| } |
| } |
| /** |
| * @return {?} |
| */ |
| logGroupEnd() { |
| if (window.console) { |
| window.console.groupEnd && window.console.groupEnd(); |
| } |
| } |
| /** |
| * @return {?} |
| */ |
| get attrToPropMap() { return _attrToPropMap; } |
| /** |
| * @param {?} nodeA |
| * @param {?} nodeB |
| * @return {?} |
| */ |
| contains(nodeA, nodeB) { return nodeContains.call(nodeA, nodeB); } |
| /** |
| * @param {?} el |
| * @param {?} selector |
| * @return {?} |
| */ |
| querySelector(el, selector) { return el.querySelector(selector); } |
| /** |
| * @param {?} el |
| * @param {?} selector |
| * @return {?} |
| */ |
| querySelectorAll(el, selector) { return el.querySelectorAll(selector); } |
| /** |
| * @param {?} el |
| * @param {?} evt |
| * @param {?} listener |
| * @return {?} |
| */ |
| on(el, evt, listener) { el.addEventListener(evt, listener, false); } |
| /** |
| * @param {?} el |
| * @param {?} evt |
| * @param {?} listener |
| * @return {?} |
| */ |
| onAndCancel(el, evt, listener) { |
| el.addEventListener(evt, listener, false); |
| // Needed to follow Dart's subscription semantic, until fix of |
| // https://code.google.com/p/dart/issues/detail?id=17406 |
| return () => { el.removeEventListener(evt, listener, false); }; |
| } |
| /** |
| * @param {?} el |
| * @param {?} evt |
| * @return {?} |
| */ |
| dispatchEvent(el, evt) { el.dispatchEvent(evt); } |
| /** |
| * @param {?} eventType |
| * @return {?} |
| */ |
| createMouseEvent(eventType) { |
| const /** @type {?} */ evt = this.getDefaultDocument().createEvent('MouseEvent'); |
| evt.initEvent(eventType, true, true); |
| return evt; |
| } |
| /** |
| * @param {?} eventType |
| * @return {?} |
| */ |
| createEvent(eventType) { |
| const /** @type {?} */ evt = this.getDefaultDocument().createEvent('Event'); |
| evt.initEvent(eventType, true, true); |
| return evt; |
| } |
| /** |
| * @param {?} evt |
| * @return {?} |
| */ |
| preventDefault(evt) { |
| evt.preventDefault(); |
| evt.returnValue = false; |
| } |
| /** |
| * @param {?} evt |
| * @return {?} |
| */ |
| isPrevented(evt) { |
| return evt.defaultPrevented || evt.returnValue != null && !evt.returnValue; |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getInnerHTML(el) { return el.innerHTML; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getTemplateContent(el) { |
| return 'content' in el && this.isTemplateElement(el) ? (/** @type {?} */ (el)).content : null; |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getOuterHTML(el) { return el.outerHTML; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| nodeName(node) { return node.nodeName; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| nodeValue(node) { return node.nodeValue; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| type(node) { return node.type; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| content(node) { |
| if (this.hasProperty(node, 'content')) { |
| return (/** @type {?} */ (node)).content; |
| } |
| else { |
| return node; |
| } |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| firstChild(el) { return el.firstChild; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| nextSibling(el) { return el.nextSibling; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| parentElement(el) { return el.parentNode; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| childNodes(el) { return el.childNodes; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| childNodesAsList(el) { |
| const /** @type {?} */ childNodes = el.childNodes; |
| const /** @type {?} */ res = new Array(childNodes.length); |
| for (let /** @type {?} */ i = 0; i < childNodes.length; i++) { |
| res[i] = childNodes[i]; |
| } |
| return res; |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| clearNodes(el) { |
| while (el.firstChild) { |
| el.removeChild(el.firstChild); |
| } |
| } |
| /** |
| * @param {?} el |
| * @param {?} node |
| * @return {?} |
| */ |
| appendChild(el, node) { el.appendChild(node); } |
| /** |
| * @param {?} el |
| * @param {?} node |
| * @return {?} |
| */ |
| removeChild(el, node) { el.removeChild(node); } |
| /** |
| * @param {?} el |
| * @param {?} newChild |
| * @param {?} oldChild |
| * @return {?} |
| */ |
| replaceChild(el, newChild, oldChild) { el.replaceChild(newChild, oldChild); } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| remove(node) { |
| if (node.parentNode) { |
| node.parentNode.removeChild(node); |
| } |
| return node; |
| } |
| /** |
| * @param {?} parent |
| * @param {?} ref |
| * @param {?} node |
| * @return {?} |
| */ |
| insertBefore(parent, ref, node) { parent.insertBefore(node, ref); } |
| /** |
| * @param {?} parent |
| * @param {?} ref |
| * @param {?} nodes |
| * @return {?} |
| */ |
| insertAllBefore(parent, ref, nodes) { |
| nodes.forEach((n) => parent.insertBefore(n, ref)); |
| } |
| /** |
| * @param {?} parent |
| * @param {?} ref |
| * @param {?} node |
| * @return {?} |
| */ |
| insertAfter(parent, ref, node) { parent.insertBefore(node, ref.nextSibling); } |
| /** |
| * @param {?} el |
| * @param {?} value |
| * @return {?} |
| */ |
| setInnerHTML(el, value) { el.innerHTML = value; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getText(el) { return el.textContent; } |
| /** |
| * @param {?} el |
| * @param {?} value |
| * @return {?} |
| */ |
| setText(el, value) { el.textContent = value; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getValue(el) { return el.value; } |
| /** |
| * @param {?} el |
| * @param {?} value |
| * @return {?} |
| */ |
| setValue(el, value) { el.value = value; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getChecked(el) { return el.checked; } |
| /** |
| * @param {?} el |
| * @param {?} value |
| * @return {?} |
| */ |
| setChecked(el, value) { el.checked = value; } |
| /** |
| * @param {?} text |
| * @return {?} |
| */ |
| createComment(text) { return this.getDefaultDocument().createComment(text); } |
| /** |
| * @param {?} html |
| * @return {?} |
| */ |
| createTemplate(html) { |
| const /** @type {?} */ t = this.getDefaultDocument().createElement('template'); |
| t.innerHTML = html; |
| return t; |
| } |
| /** |
| * @param {?} tagName |
| * @param {?=} doc |
| * @return {?} |
| */ |
| createElement(tagName, doc) { |
| doc = doc || this.getDefaultDocument(); |
| return doc.createElement(tagName); |
| } |
| /** |
| * @param {?} ns |
| * @param {?} tagName |
| * @param {?=} doc |
| * @return {?} |
| */ |
| createElementNS(ns, tagName, doc) { |
| doc = doc || this.getDefaultDocument(); |
| return doc.createElementNS(ns, tagName); |
| } |
| /** |
| * @param {?} text |
| * @param {?=} doc |
| * @return {?} |
| */ |
| createTextNode(text, doc) { |
| doc = doc || this.getDefaultDocument(); |
| return doc.createTextNode(text); |
| } |
| /** |
| * @param {?} attrName |
| * @param {?} attrValue |
| * @param {?=} doc |
| * @return {?} |
| */ |
| createScriptTag(attrName, attrValue, doc) { |
| doc = doc || this.getDefaultDocument(); |
| const /** @type {?} */ el = /** @type {?} */ (doc.createElement('SCRIPT')); |
| el.setAttribute(attrName, attrValue); |
| return el; |
| } |
| /** |
| * @param {?} css |
| * @param {?=} doc |
| * @return {?} |
| */ |
| createStyleElement(css, doc) { |
| doc = doc || this.getDefaultDocument(); |
| const /** @type {?} */ style = /** @type {?} */ (doc.createElement('style')); |
| this.appendChild(style, this.createTextNode(css, doc)); |
| return style; |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| createShadowRoot(el) { return (/** @type {?} */ (el)).createShadowRoot(); } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getShadowRoot(el) { return (/** @type {?} */ (el)).shadowRoot; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getHost(el) { return (/** @type {?} */ (el)).host; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| clone(node) { return node.cloneNode(true); } |
| /** |
| * @param {?} element |
| * @param {?} name |
| * @return {?} |
| */ |
| getElementsByClassName(element, name) { |
| return element.getElementsByClassName(name); |
| } |
| /** |
| * @param {?} element |
| * @param {?} name |
| * @return {?} |
| */ |
| getElementsByTagName(element, name) { |
| return element.getElementsByTagName(name); |
| } |
| /** |
| * @param {?} element |
| * @return {?} |
| */ |
| classList(element) { return Array.prototype.slice.call(element.classList, 0); } |
| /** |
| * @param {?} element |
| * @param {?} className |
| * @return {?} |
| */ |
| addClass(element, className) { element.classList.add(className); } |
| /** |
| * @param {?} element |
| * @param {?} className |
| * @return {?} |
| */ |
| removeClass(element, className) { element.classList.remove(className); } |
| /** |
| * @param {?} element |
| * @param {?} className |
| * @return {?} |
| */ |
| hasClass(element, className) { |
| return element.classList.contains(className); |
| } |
| /** |
| * @param {?} element |
| * @param {?} styleName |
| * @param {?} styleValue |
| * @return {?} |
| */ |
| setStyle(element, styleName, styleValue) { |
| element.style[styleName] = styleValue; |
| } |
| /** |
| * @param {?} element |
| * @param {?} stylename |
| * @return {?} |
| */ |
| removeStyle(element, stylename) { |
| // IE requires '' instead of null |
| // see https://github.com/angular/angular/issues/7916 |
| element.style[stylename] = ''; |
| } |
| /** |
| * @param {?} element |
| * @param {?} stylename |
| * @return {?} |
| */ |
| getStyle(element, stylename) { return element.style[stylename]; } |
| /** |
| * @param {?} element |
| * @param {?} styleName |
| * @param {?=} styleValue |
| * @return {?} |
| */ |
| hasStyle(element, styleName, styleValue) { |
| const /** @type {?} */ value = this.getStyle(element, styleName) || ''; |
| return styleValue ? value == styleValue : value.length > 0; |
| } |
| /** |
| * @param {?} element |
| * @return {?} |
| */ |
| tagName(element) { return element.tagName; } |
| /** |
| * @param {?} element |
| * @return {?} |
| */ |
| attributeMap(element) { |
| const /** @type {?} */ res = new Map(); |
| const /** @type {?} */ elAttrs = element.attributes; |
| for (let /** @type {?} */ i = 0; i < elAttrs.length; i++) { |
| const /** @type {?} */ attrib = elAttrs.item(i); |
| res.set(attrib.name, attrib.value); |
| } |
| return res; |
| } |
| /** |
| * @param {?} element |
| * @param {?} attribute |
| * @return {?} |
| */ |
| hasAttribute(element, attribute) { |
| return element.hasAttribute(attribute); |
| } |
| /** |
| * @param {?} element |
| * @param {?} ns |
| * @param {?} attribute |
| * @return {?} |
| */ |
| hasAttributeNS(element, ns, attribute) { |
| return element.hasAttributeNS(ns, attribute); |
| } |
| /** |
| * @param {?} element |
| * @param {?} attribute |
| * @return {?} |
| */ |
| getAttribute(element, attribute) { |
| return element.getAttribute(attribute); |
| } |
| /** |
| * @param {?} element |
| * @param {?} ns |
| * @param {?} name |
| * @return {?} |
| */ |
| getAttributeNS(element, ns, name) { |
| return element.getAttributeNS(ns, name); |
| } |
| /** |
| * @param {?} element |
| * @param {?} name |
| * @param {?} value |
| * @return {?} |
| */ |
| setAttribute(element, name, value) { element.setAttribute(name, value); } |
| /** |
| * @param {?} element |
| * @param {?} ns |
| * @param {?} name |
| * @param {?} value |
| * @return {?} |
| */ |
| setAttributeNS(element, ns, name, value) { |
| element.setAttributeNS(ns, name, value); |
| } |
| /** |
| * @param {?} element |
| * @param {?} attribute |
| * @return {?} |
| */ |
| removeAttribute(element, attribute) { element.removeAttribute(attribute); } |
| /** |
| * @param {?} element |
| * @param {?} ns |
| * @param {?} name |
| * @return {?} |
| */ |
| removeAttributeNS(element, ns, name) { |
| element.removeAttributeNS(ns, name); |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| templateAwareRoot(el) { return this.isTemplateElement(el) ? this.content(el) : el; } |
| /** |
| * @return {?} |
| */ |
| createHtmlDocument() { |
| return document.implementation.createHTMLDocument('fakeTitle'); |
| } |
| /** |
| * @return {?} |
| */ |
| getDefaultDocument() { return document; } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getBoundingClientRect(el) { |
| try { |
| return el.getBoundingClientRect(); |
| } |
| catch (/** @type {?} */ e) { |
| return { top: 0, bottom: 0, left: 0, right: 0, width: 0, height: 0 }; |
| } |
| } |
| /** |
| * @param {?} doc |
| * @return {?} |
| */ |
| getTitle(doc) { return doc.title; } |
| /** |
| * @param {?} doc |
| * @param {?} newTitle |
| * @return {?} |
| */ |
| setTitle(doc, newTitle) { doc.title = newTitle || ''; } |
| /** |
| * @param {?} n |
| * @param {?} selector |
| * @return {?} |
| */ |
| elementMatches(n, selector) { |
| if (this.isElementNode(n)) { |
| return n.matches && n.matches(selector) || |
| n.msMatchesSelector && n.msMatchesSelector(selector) || |
| n.webkitMatchesSelector && n.webkitMatchesSelector(selector); |
| } |
| return false; |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| isTemplateElement(el) { |
| return this.isElementNode(el) && el.nodeName === 'TEMPLATE'; |
| } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| isTextNode(node) { return node.nodeType === Node.TEXT_NODE; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| isCommentNode(node) { return node.nodeType === Node.COMMENT_NODE; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| isElementNode(node) { return node.nodeType === Node.ELEMENT_NODE; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| hasShadowRoot(node) { |
| return node.shadowRoot != null && node instanceof HTMLElement; |
| } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| isShadowRoot(node) { return node instanceof DocumentFragment; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| importIntoDoc(node) { return document.importNode(this.templateAwareRoot(node), true); } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| adoptNode(node) { return document.adoptNode(node); } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| getHref(el) { return /** @type {?} */ ((el.getAttribute('href'))); } |
| /** |
| * @param {?} event |
| * @return {?} |
| */ |
| getEventKey(event) { |
| let /** @type {?} */ key = event.key; |
| if (key == null) { |
| key = event.keyIdentifier; |
| // keyIdentifier is defined in the old draft of DOM Level 3 Events implemented by Chrome and |
| // Safari cf |
| // http://www.w3.org/TR/2007/WD-DOM-Level-3-Events-20071221/events.html#Events-KeyboardEvents-Interfaces |
| if (key == null) { |
| return 'Unidentified'; |
| } |
| if (key.startsWith('U+')) { |
| key = String.fromCharCode(parseInt(key.substring(2), 16)); |
| if (event.location === DOM_KEY_LOCATION_NUMPAD && _chromeNumKeyPadMap.hasOwnProperty(key)) { |
| // There is a bug in Chrome for numeric keypad keys: |
| // https://code.google.com/p/chromium/issues/detail?id=155654 |
| // 1, 2, 3 ... are reported as A, B, C ... |
| key = (/** @type {?} */ (_chromeNumKeyPadMap))[key]; |
| } |
| } |
| } |
| return _keyMap[key] || key; |
| } |
| /** |
| * @param {?} doc |
| * @param {?} target |
| * @return {?} |
| */ |
| getGlobalEventTarget(doc, target) { |
| if (target === 'window') { |
| return window; |
| } |
| if (target === 'document') { |
| return doc; |
| } |
| if (target === 'body') { |
| return doc.body; |
| } |
| return null; |
| } |
| /** |
| * @return {?} |
| */ |
| getHistory() { return window.history; } |
| /** |
| * @return {?} |
| */ |
| getLocation() { return window.location; } |
| /** |
| * @param {?} doc |
| * @return {?} |
| */ |
| getBaseHref(doc) { |
| const /** @type {?} */ href = getBaseElementHref(); |
| return href == null ? null : relativePath(href); |
| } |
| /** |
| * @return {?} |
| */ |
| resetBaseElement() { baseElement = null; } |
| /** |
| * @return {?} |
| */ |
| getUserAgent() { return window.navigator.userAgent; } |
| /** |
| * @param {?} element |
| * @param {?} name |
| * @param {?} value |
| * @return {?} |
| */ |
| setData(element, name, value) { |
| this.setAttribute(element, 'data-' + name, value); |
| } |
| /** |
| * @param {?} element |
| * @param {?} name |
| * @return {?} |
| */ |
| getData(element, name) { |
| return this.getAttribute(element, 'data-' + name); |
| } |
| /** |
| * @param {?} element |
| * @return {?} |
| */ |
| getComputedStyle(element) { return getComputedStyle(element); } |
| /** |
| * @return {?} |
| */ |
| supportsWebAnimation() { |
| return typeof (/** @type {?} */ (Element)).prototype['animate'] === 'function'; |
| } |
| /** |
| * @return {?} |
| */ |
| performanceNow() { |
| // performance.now() is not available in all browsers, see |
| // http://caniuse.com/#search=performance.now |
| return window.performance && window.performance.now ? window.performance.now() : |
| new Date().getTime(); |
| } |
| /** |
| * @return {?} |
| */ |
| supportsCookies() { return true; } |
| /** |
| * @param {?} name |
| * @return {?} |
| */ |
| getCookie(name) { return ɵparseCookieValue(document.cookie, name); } |
| /** |
| * @param {?} name |
| * @param {?} value |
| * @return {?} |
| */ |
| setCookie(name, value) { |
| // document.cookie is magical, assigning into it assigns/overrides one cookie value, but does |
| // not clear other cookies. |
| document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value); |
| } |
| } |
| let baseElement = null; |
| /** |
| * @return {?} |
| */ |
| function getBaseElementHref() { |
| if (!baseElement) { |
| baseElement = /** @type {?} */ ((document.querySelector('base'))); |
| if (!baseElement) { |
| return null; |
| } |
| } |
| return baseElement.getAttribute('href'); |
| } |
| // based on urlUtils.js in AngularJS 1 |
| let urlParsingNode; |
| /** |
| * @param {?} url |
| * @return {?} |
| */ |
| function relativePath(url) { |
| if (!urlParsingNode) { |
| urlParsingNode = document.createElement('a'); |
| } |
| urlParsingNode.setAttribute('href', url); |
| return (urlParsingNode.pathname.charAt(0) === '/') ? urlParsingNode.pathname : |
| '/' + urlParsingNode.pathname; |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * A DI Token representing the main rendering context. In a browser this is the DOM Document. |
| * |
| * Note: Document might not be available in the Application Context when Application and Rendering |
| * Contexts are not the same (e.g. when running the application into a Web Worker). |
| * |
| * @deprecated import from `\@angular/common` instead. |
| */ |
| const DOCUMENT$1 = DOCUMENT; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * @return {?} |
| */ |
| function supportsState() { |
| return !!window.history.pushState; |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * `PlatformLocation` encapsulates all of the direct calls to platform APIs. |
| * This class should not be used directly by an application developer. Instead, use |
| * {\@link Location}. |
| */ |
| class BrowserPlatformLocation extends PlatformLocation { |
| /** |
| * @param {?} _doc |
| */ |
| constructor(_doc) { |
| super(); |
| this._doc = _doc; |
| this._init(); |
| } |
| /** |
| * \@internal |
| * @return {?} |
| */ |
| _init() { |
| (/** @type {?} */ (this)).location = getDOM().getLocation(); |
| this._history = getDOM().getHistory(); |
| } |
| /** |
| * @return {?} |
| */ |
| getBaseHrefFromDOM() { return /** @type {?} */ ((getDOM().getBaseHref(this._doc))); } |
| /** |
| * @param {?} fn |
| * @return {?} |
| */ |
| onPopState(fn) { |
| getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('popstate', fn, false); |
| } |
| /** |
| * @param {?} fn |
| * @return {?} |
| */ |
| onHashChange(fn) { |
| getDOM().getGlobalEventTarget(this._doc, 'window').addEventListener('hashchange', fn, false); |
| } |
| /** |
| * @return {?} |
| */ |
| get pathname() { return this.location.pathname; } |
| /** |
| * @return {?} |
| */ |
| get search() { return this.location.search; } |
| /** |
| * @return {?} |
| */ |
| get hash() { return this.location.hash; } |
| /** |
| * @param {?} newPath |
| * @return {?} |
| */ |
| set pathname(newPath) { this.location.pathname = newPath; } |
| /** |
| * @param {?} state |
| * @param {?} title |
| * @param {?} url |
| * @return {?} |
| */ |
| pushState(state, title, url) { |
| if (supportsState()) { |
| this._history.pushState(state, title, url); |
| } |
| else { |
| this.location.hash = url; |
| } |
| } |
| /** |
| * @param {?} state |
| * @param {?} title |
| * @param {?} url |
| * @return {?} |
| */ |
| replaceState(state, title, url) { |
| if (supportsState()) { |
| this._history.replaceState(state, title, url); |
| } |
| else { |
| this.location.hash = url; |
| } |
| } |
| /** |
| * @return {?} |
| */ |
| forward() { this._history.forward(); } |
| /** |
| * @return {?} |
| */ |
| back() { this._history.back(); } |
| } |
| BrowserPlatformLocation.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| BrowserPlatformLocation.ctorParameters = () => [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * A service that can be used to get and add meta tags. |
| * |
| * \@experimental |
| */ |
| class Meta { |
| /** |
| * @param {?} _doc |
| */ |
| constructor(_doc) { |
| this._doc = _doc; |
| this._dom = getDOM(); |
| } |
| /** |
| * @param {?} tag |
| * @param {?=} forceCreation |
| * @return {?} |
| */ |
| addTag(tag, forceCreation = false) { |
| if (!tag) |
| return null; |
| return this._getOrCreateElement(tag, forceCreation); |
| } |
| /** |
| * @param {?} tags |
| * @param {?=} forceCreation |
| * @return {?} |
| */ |
| addTags(tags, forceCreation = false) { |
| if (!tags) |
| return []; |
| return tags.reduce((result, tag) => { |
| if (tag) { |
| result.push(this._getOrCreateElement(tag, forceCreation)); |
| } |
| return result; |
| }, []); |
| } |
| /** |
| * @param {?} attrSelector |
| * @return {?} |
| */ |
| getTag(attrSelector) { |
| if (!attrSelector) |
| return null; |
| return this._dom.querySelector(this._doc, `meta[${attrSelector}]`) || null; |
| } |
| /** |
| * @param {?} attrSelector |
| * @return {?} |
| */ |
| getTags(attrSelector) { |
| if (!attrSelector) |
| return []; |
| const /** @type {?} */ list = this._dom.querySelectorAll(this._doc, `meta[${attrSelector}]`); |
| return list ? [].slice.call(list) : []; |
| } |
| /** |
| * @param {?} tag |
| * @param {?=} selector |
| * @return {?} |
| */ |
| updateTag(tag, selector) { |
| if (!tag) |
| return null; |
| selector = selector || this._parseSelector(tag); |
| const /** @type {?} */ meta = /** @type {?} */ ((this.getTag(selector))); |
| if (meta) { |
| return this._setMetaElementAttributes(tag, meta); |
| } |
| return this._getOrCreateElement(tag, true); |
| } |
| /** |
| * @param {?} attrSelector |
| * @return {?} |
| */ |
| removeTag(attrSelector) { this.removeTagElement(/** @type {?} */ ((this.getTag(attrSelector)))); } |
| /** |
| * @param {?} meta |
| * @return {?} |
| */ |
| removeTagElement(meta) { |
| if (meta) { |
| this._dom.remove(meta); |
| } |
| } |
| /** |
| * @param {?} meta |
| * @param {?=} forceCreation |
| * @return {?} |
| */ |
| _getOrCreateElement(meta, forceCreation = false) { |
| if (!forceCreation) { |
| const /** @type {?} */ selector = this._parseSelector(meta); |
| const /** @type {?} */ elem = /** @type {?} */ ((this.getTag(selector))); |
| // It's allowed to have multiple elements with the same name so it's not enough to |
| // just check that element with the same name already present on the page. We also need to |
| // check if element has tag attributes |
| if (elem && this._containsAttributes(meta, elem)) |
| return elem; |
| } |
| const /** @type {?} */ element = /** @type {?} */ (this._dom.createElement('meta')); |
| this._setMetaElementAttributes(meta, element); |
| const /** @type {?} */ head = this._dom.getElementsByTagName(this._doc, 'head')[0]; |
| this._dom.appendChild(head, element); |
| return element; |
| } |
| /** |
| * @param {?} tag |
| * @param {?} el |
| * @return {?} |
| */ |
| _setMetaElementAttributes(tag, el) { |
| Object.keys(tag).forEach((prop) => this._dom.setAttribute(el, prop, tag[prop])); |
| return el; |
| } |
| /** |
| * @param {?} tag |
| * @return {?} |
| */ |
| _parseSelector(tag) { |
| const /** @type {?} */ attr = tag.name ? 'name' : 'property'; |
| return `${attr}="${tag[attr]}"`; |
| } |
| /** |
| * @param {?} tag |
| * @param {?} elem |
| * @return {?} |
| */ |
| _containsAttributes(tag, elem) { |
| return Object.keys(tag).every((key) => this._dom.getAttribute(elem, key) === tag[key]); |
| } |
| } |
| Meta.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| Meta.ctorParameters = () => [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * An id that identifies a particular application being bootstrapped, that should |
| * match across the client/server boundary. |
| */ |
| const TRANSITION_ID = new InjectionToken('TRANSITION_ID'); |
| /** |
| * @param {?} transitionId |
| * @param {?} document |
| * @param {?} injector |
| * @return {?} |
| */ |
| function appInitializerFactory(transitionId, document, injector) { |
| return () => { |
| // Wait for all application initializers to be completed before removing the styles set by |
| // the server. |
| injector.get(ApplicationInitStatus).donePromise.then(() => { |
| const /** @type {?} */ dom = getDOM(); |
| const /** @type {?} */ styles = Array.prototype.slice.apply(dom.querySelectorAll(document, `style[ng-transition]`)); |
| styles.filter(el => dom.getAttribute(el, 'ng-transition') === transitionId) |
| .forEach(el => dom.remove(el)); |
| }); |
| }; |
| } |
| const SERVER_TRANSITION_PROVIDERS = [ |
| { |
| provide: APP_INITIALIZER, |
| useFactory: appInitializerFactory, |
| deps: [TRANSITION_ID, DOCUMENT$1, Injector], |
| multi: true |
| }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| class BrowserGetTestability { |
| /** |
| * @return {?} |
| */ |
| static init() { setTestabilityGetter(new BrowserGetTestability()); } |
| /** |
| * @param {?} registry |
| * @return {?} |
| */ |
| addToWindow(registry) { |
| ɵglobal['getAngularTestability'] = (elem, findInAncestors = true) => { |
| const /** @type {?} */ testability = registry.findTestabilityInTree(elem, findInAncestors); |
| if (testability == null) { |
| throw new Error('Could not find testability for element.'); |
| } |
| return testability; |
| }; |
| ɵglobal['getAllAngularTestabilities'] = () => registry.getAllTestabilities(); |
| ɵglobal['getAllAngularRootElements'] = () => registry.getAllRootElements(); |
| const /** @type {?} */ whenAllStable = (callback /** TODO #9100 */) => { |
| const /** @type {?} */ testabilities = ɵglobal['getAllAngularTestabilities'](); |
| let /** @type {?} */ count = testabilities.length; |
| let /** @type {?} */ didWork = false; |
| const /** @type {?} */ decrement = function (didWork_ /** TODO #9100 */) { |
| didWork = didWork || didWork_; |
| count--; |
| if (count == 0) { |
| callback(didWork); |
| } |
| }; |
| testabilities.forEach(function (testability /** TODO #9100 */) { |
| testability.whenStable(decrement); |
| }); |
| }; |
| if (!ɵglobal['frameworkStabilizers']) { |
| ɵglobal['frameworkStabilizers'] = []; |
| } |
| ɵglobal['frameworkStabilizers'].push(whenAllStable); |
| } |
| /** |
| * @param {?} registry |
| * @param {?} elem |
| * @param {?} findInAncestors |
| * @return {?} |
| */ |
| findTestabilityInTree(registry, elem, findInAncestors) { |
| if (elem == null) { |
| return null; |
| } |
| const /** @type {?} */ t = registry.getTestability(elem); |
| if (t != null) { |
| return t; |
| } |
| else if (!findInAncestors) { |
| return null; |
| } |
| if (getDOM().isShadowRoot(elem)) { |
| return this.findTestabilityInTree(registry, getDOM().getHost(elem), true); |
| } |
| return this.findTestabilityInTree(registry, getDOM().parentElement(elem), true); |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * A service that can be used to get and set the title of a current HTML document. |
| * |
| * Since an Angular application can't be bootstrapped on the entire HTML document (`<html>` tag) |
| * it is not possible to bind to the `text` property of the `HTMLTitleElement` elements |
| * (representing the `<title>` tag). Instead, this service can be used to set and get the current |
| * title value. |
| * |
| * \@experimental |
| */ |
| class Title { |
| /** |
| * @param {?} _doc |
| */ |
| constructor(_doc) { |
| this._doc = _doc; |
| } |
| /** |
| * Get the title of the current HTML document. |
| * @return {?} |
| */ |
| getTitle() { return getDOM().getTitle(this._doc); } |
| /** |
| * Set the title of the current HTML document. |
| * @param {?} newTitle |
| * @return {?} |
| */ |
| setTitle(newTitle) { getDOM().setTitle(this._doc, newTitle); } |
| } |
| Title.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| Title.ctorParameters = () => [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * @param {?} input |
| * @return {?} |
| */ |
| |
| /** |
| * @param {?} input |
| * @return {?} |
| */ |
| |
| /** |
| * Exports the value under a given `name` in the global property `ng`. For example `ng.probe` if |
| * `name` is `'probe'`. |
| * @param {?} name Name under which it will be exported. Keep in mind this will be a property of the |
| * global `ng` object. |
| * @param {?} value The value to export. |
| * @return {?} |
| */ |
| function exportNgVar(name, value) { |
| if (typeof COMPILED === 'undefined' || !COMPILED) { |
| // Note: we can't export `ng` when using closure enhanced optimization as: |
| // - closure declares globals itself for minified names, which sometimes clobber our `ng` global |
| // - we can't declare a closure extern as the namespace `ng` is already used within Google |
| // for typings for angularJS (via `goog.provide('ng....')`). |
| const /** @type {?} */ ng = ɵglobal['ng'] = (/** @type {?} */ (ɵglobal['ng'])) || {}; |
| ng[name] = value; |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const CORE_TOKENS = { |
| 'ApplicationRef': ApplicationRef, |
| 'NgZone': NgZone, |
| }; |
| const INSPECT_GLOBAL_NAME = 'probe'; |
| const CORE_TOKENS_GLOBAL_NAME = 'coreTokens'; |
| /** |
| * Returns a {\@link DebugElement} for the given native DOM element, or |
| * null if the given native element does not have an Angular view associated |
| * with it. |
| * @param {?} element |
| * @return {?} |
| */ |
| function inspectNativeElement(element) { |
| return getDebugNode(element); |
| } |
| /** |
| * @param {?} coreTokens |
| * @return {?} |
| */ |
| function _createNgProbe(coreTokens) { |
| exportNgVar(INSPECT_GLOBAL_NAME, inspectNativeElement); |
| exportNgVar(CORE_TOKENS_GLOBAL_NAME, Object.assign({}, CORE_TOKENS, _ngProbeTokensToMap(coreTokens || []))); |
| return () => inspectNativeElement; |
| } |
| /** |
| * @param {?} tokens |
| * @return {?} |
| */ |
| function _ngProbeTokensToMap(tokens) { |
| return tokens.reduce((prev, t) => (prev[t.name] = t.token, prev), {}); |
| } |
| /** |
| * Providers which support debugging Angular applications (e.g. via `ng.probe`). |
| */ |
| const ELEMENT_PROBE_PROVIDERS = [ |
| { |
| provide: APP_INITIALIZER, |
| useFactory: _createNgProbe, |
| deps: [ |
| [NgProbeToken, new Optional()], |
| ], |
| multi: true, |
| }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * \@stable |
| */ |
| const EVENT_MANAGER_PLUGINS = new InjectionToken('EventManagerPlugins'); |
| /** |
| * \@stable |
| */ |
| class EventManager { |
| /** |
| * @param {?} plugins |
| * @param {?} _zone |
| */ |
| constructor(plugins, _zone) { |
| this._zone = _zone; |
| this._eventNameToPlugin = new Map(); |
| plugins.forEach(p => p.manager = this); |
| this._plugins = plugins.slice().reverse(); |
| } |
| /** |
| * @param {?} element |
| * @param {?} eventName |
| * @param {?} handler |
| * @return {?} |
| */ |
| addEventListener(element, eventName, handler) { |
| const /** @type {?} */ plugin = this._findPluginFor(eventName); |
| return plugin.addEventListener(element, eventName, handler); |
| } |
| /** |
| * @param {?} target |
| * @param {?} eventName |
| * @param {?} handler |
| * @return {?} |
| */ |
| addGlobalEventListener(target, eventName, handler) { |
| const /** @type {?} */ plugin = this._findPluginFor(eventName); |
| return plugin.addGlobalEventListener(target, eventName, handler); |
| } |
| /** |
| * @return {?} |
| */ |
| getZone() { return this._zone; } |
| /** |
| * \@internal |
| * @param {?} eventName |
| * @return {?} |
| */ |
| _findPluginFor(eventName) { |
| const /** @type {?} */ plugin = this._eventNameToPlugin.get(eventName); |
| if (plugin) { |
| return plugin; |
| } |
| const /** @type {?} */ plugins = this._plugins; |
| for (let /** @type {?} */ i = 0; i < plugins.length; i++) { |
| const /** @type {?} */ plugin = plugins[i]; |
| if (plugin.supports(eventName)) { |
| this._eventNameToPlugin.set(eventName, plugin); |
| return plugin; |
| } |
| } |
| throw new Error(`No event manager plugin found for event ${eventName}`); |
| } |
| } |
| EventManager.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| EventManager.ctorParameters = () => [ |
| { type: Array, decorators: [{ type: Inject, args: [EVENT_MANAGER_PLUGINS,] },] }, |
| { type: NgZone, }, |
| ]; |
| /** |
| * @abstract |
| */ |
| class EventManagerPlugin { |
| /** |
| * @param {?} _doc |
| */ |
| constructor(_doc) { |
| this._doc = _doc; |
| } |
| /** |
| * @param {?} element |
| * @param {?} eventName |
| * @param {?} handler |
| * @return {?} |
| */ |
| addGlobalEventListener(element, eventName, handler) { |
| const /** @type {?} */ target = getDOM().getGlobalEventTarget(this._doc, element); |
| if (!target) { |
| throw new Error(`Unsupported event target ${target} for event ${eventName}`); |
| } |
| return this.addEventListener(target, eventName, handler); |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| class SharedStylesHost { |
| constructor() { |
| /** |
| * \@internal |
| */ |
| this._stylesSet = new Set(); |
| } |
| /** |
| * @param {?} styles |
| * @return {?} |
| */ |
| addStyles(styles) { |
| const /** @type {?} */ additions = new Set(); |
| styles.forEach(style => { |
| if (!this._stylesSet.has(style)) { |
| this._stylesSet.add(style); |
| additions.add(style); |
| } |
| }); |
| this.onStylesAdded(additions); |
| } |
| /** |
| * @param {?} additions |
| * @return {?} |
| */ |
| onStylesAdded(additions) { } |
| /** |
| * @return {?} |
| */ |
| getAllStyles() { return Array.from(this._stylesSet); } |
| } |
| SharedStylesHost.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| SharedStylesHost.ctorParameters = () => []; |
| class DomSharedStylesHost extends SharedStylesHost { |
| /** |
| * @param {?} _doc |
| */ |
| constructor(_doc) { |
| super(); |
| this._doc = _doc; |
| this._hostNodes = new Set(); |
| this._styleNodes = new Set(); |
| this._hostNodes.add(_doc.head); |
| } |
| /** |
| * @param {?} styles |
| * @param {?} host |
| * @return {?} |
| */ |
| _addStylesToHost(styles, host) { |
| styles.forEach((style) => { |
| const /** @type {?} */ styleEl = this._doc.createElement('style'); |
| styleEl.textContent = style; |
| this._styleNodes.add(host.appendChild(styleEl)); |
| }); |
| } |
| /** |
| * @param {?} hostNode |
| * @return {?} |
| */ |
| addHost(hostNode) { |
| this._addStylesToHost(this._stylesSet, hostNode); |
| this._hostNodes.add(hostNode); |
| } |
| /** |
| * @param {?} hostNode |
| * @return {?} |
| */ |
| removeHost(hostNode) { this._hostNodes.delete(hostNode); } |
| /** |
| * @param {?} additions |
| * @return {?} |
| */ |
| onStylesAdded(additions) { |
| this._hostNodes.forEach(hostNode => this._addStylesToHost(additions, hostNode)); |
| } |
| /** |
| * @return {?} |
| */ |
| ngOnDestroy() { this._styleNodes.forEach(styleNode => getDOM().remove(styleNode)); } |
| } |
| DomSharedStylesHost.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| DomSharedStylesHost.ctorParameters = () => [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const NAMESPACE_URIS = { |
| 'svg': 'http://www.w3.org/2000/svg', |
| 'xhtml': 'http://www.w3.org/1999/xhtml', |
| 'xlink': 'http://www.w3.org/1999/xlink', |
| 'xml': 'http://www.w3.org/XML/1998/namespace', |
| 'xmlns': 'http://www.w3.org/2000/xmlns/', |
| }; |
| const COMPONENT_REGEX = /%COMP%/g; |
| const COMPONENT_VARIABLE = '%COMP%'; |
| const HOST_ATTR = `_nghost-${COMPONENT_VARIABLE}`; |
| const CONTENT_ATTR = `_ngcontent-${COMPONENT_VARIABLE}`; |
| /** |
| * @param {?} componentShortId |
| * @return {?} |
| */ |
| function shimContentAttribute(componentShortId) { |
| return CONTENT_ATTR.replace(COMPONENT_REGEX, componentShortId); |
| } |
| /** |
| * @param {?} componentShortId |
| * @return {?} |
| */ |
| function shimHostAttribute(componentShortId) { |
| return HOST_ATTR.replace(COMPONENT_REGEX, componentShortId); |
| } |
| /** |
| * @param {?} compId |
| * @param {?} styles |
| * @param {?} target |
| * @return {?} |
| */ |
| function flattenStyles(compId, styles, target) { |
| for (let /** @type {?} */ i = 0; i < styles.length; i++) { |
| let /** @type {?} */ style = styles[i]; |
| if (Array.isArray(style)) { |
| flattenStyles(compId, style, target); |
| } |
| else { |
| style = style.replace(COMPONENT_REGEX, compId); |
| target.push(style); |
| } |
| } |
| return target; |
| } |
| /** |
| * @param {?} eventHandler |
| * @return {?} |
| */ |
| function decoratePreventDefault(eventHandler) { |
| return (event) => { |
| const /** @type {?} */ allowDefaultBehavior = eventHandler(event); |
| if (allowDefaultBehavior === false) { |
| // TODO(tbosch): move preventDefault into event plugins... |
| event.preventDefault(); |
| event.returnValue = false; |
| } |
| }; |
| } |
| class DomRendererFactory2 { |
| /** |
| * @param {?} eventManager |
| * @param {?} sharedStylesHost |
| */ |
| constructor(eventManager, sharedStylesHost) { |
| this.eventManager = eventManager; |
| this.sharedStylesHost = sharedStylesHost; |
| this.rendererByCompId = new Map(); |
| this.defaultRenderer = new DefaultDomRenderer2(eventManager); |
| } |
| /** |
| * @param {?} element |
| * @param {?} type |
| * @return {?} |
| */ |
| createRenderer(element, type) { |
| if (!element || !type) { |
| return this.defaultRenderer; |
| } |
| switch (type.encapsulation) { |
| case ViewEncapsulation.Emulated: { |
| let /** @type {?} */ renderer = this.rendererByCompId.get(type.id); |
| if (!renderer) { |
| renderer = |
| new EmulatedEncapsulationDomRenderer2(this.eventManager, this.sharedStylesHost, type); |
| this.rendererByCompId.set(type.id, renderer); |
| } |
| (/** @type {?} */ (renderer)).applyToHost(element); |
| return renderer; |
| } |
| case ViewEncapsulation.Native: |
| return new ShadowDomRenderer(this.eventManager, this.sharedStylesHost, element, type); |
| default: { |
| if (!this.rendererByCompId.has(type.id)) { |
| const /** @type {?} */ styles = flattenStyles(type.id, type.styles, []); |
| this.sharedStylesHost.addStyles(styles); |
| this.rendererByCompId.set(type.id, this.defaultRenderer); |
| } |
| return this.defaultRenderer; |
| } |
| } |
| } |
| /** |
| * @return {?} |
| */ |
| begin() { } |
| /** |
| * @return {?} |
| */ |
| end() { } |
| } |
| DomRendererFactory2.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| DomRendererFactory2.ctorParameters = () => [ |
| { type: EventManager, }, |
| { type: DomSharedStylesHost, }, |
| ]; |
| class DefaultDomRenderer2 { |
| /** |
| * @param {?} eventManager |
| */ |
| constructor(eventManager) { |
| this.eventManager = eventManager; |
| this.data = Object.create(null); |
| } |
| /** |
| * @return {?} |
| */ |
| destroy() { } |
| /** |
| * @param {?} name |
| * @param {?=} namespace |
| * @return {?} |
| */ |
| createElement(name, namespace) { |
| if (namespace) { |
| return document.createElementNS(NAMESPACE_URIS[namespace], name); |
| } |
| return document.createElement(name); |
| } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| createComment(value) { return document.createComment(value); } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| createText(value) { return document.createTextNode(value); } |
| /** |
| * @param {?} parent |
| * @param {?} newChild |
| * @return {?} |
| */ |
| appendChild(parent, newChild) { parent.appendChild(newChild); } |
| /** |
| * @param {?} parent |
| * @param {?} newChild |
| * @param {?} refChild |
| * @return {?} |
| */ |
| insertBefore(parent, newChild, refChild) { |
| if (parent) { |
| parent.insertBefore(newChild, refChild); |
| } |
| } |
| /** |
| * @param {?} parent |
| * @param {?} oldChild |
| * @return {?} |
| */ |
| removeChild(parent, oldChild) { |
| if (parent) { |
| parent.removeChild(oldChild); |
| } |
| } |
| /** |
| * @param {?} selectorOrNode |
| * @return {?} |
| */ |
| selectRootElement(selectorOrNode) { |
| let /** @type {?} */ el = typeof selectorOrNode === 'string' ? document.querySelector(selectorOrNode) : |
| selectorOrNode; |
| if (!el) { |
| throw new Error(`The selector "${selectorOrNode}" did not match any elements`); |
| } |
| el.textContent = ''; |
| return el; |
| } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| parentNode(node) { return node.parentNode; } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| nextSibling(node) { return node.nextSibling; } |
| /** |
| * @param {?} el |
| * @param {?} name |
| * @param {?} value |
| * @param {?=} namespace |
| * @return {?} |
| */ |
| setAttribute(el, name, value, namespace) { |
| if (namespace) { |
| name = `${namespace}:${name}`; |
| const /** @type {?} */ namespaceUri = NAMESPACE_URIS[namespace]; |
| if (namespaceUri) { |
| el.setAttributeNS(namespaceUri, name, value); |
| } |
| else { |
| el.setAttribute(name, value); |
| } |
| } |
| else { |
| el.setAttribute(name, value); |
| } |
| } |
| /** |
| * @param {?} el |
| * @param {?} name |
| * @param {?=} namespace |
| * @return {?} |
| */ |
| removeAttribute(el, name, namespace) { |
| if (namespace) { |
| const /** @type {?} */ namespaceUri = NAMESPACE_URIS[namespace]; |
| if (namespaceUri) { |
| el.removeAttributeNS(namespaceUri, name); |
| } |
| else { |
| el.removeAttribute(`${namespace}:${name}`); |
| } |
| } |
| else { |
| el.removeAttribute(name); |
| } |
| } |
| /** |
| * @param {?} el |
| * @param {?} name |
| * @return {?} |
| */ |
| addClass(el, name) { el.classList.add(name); } |
| /** |
| * @param {?} el |
| * @param {?} name |
| * @return {?} |
| */ |
| removeClass(el, name) { el.classList.remove(name); } |
| /** |
| * @param {?} el |
| * @param {?} style |
| * @param {?} value |
| * @param {?} flags |
| * @return {?} |
| */ |
| setStyle(el, style, value, flags) { |
| if (flags & RendererStyleFlags2.DashCase) { |
| el.style.setProperty(style, value, !!(flags & RendererStyleFlags2.Important) ? 'important' : ''); |
| } |
| else { |
| el.style[style] = value; |
| } |
| } |
| /** |
| * @param {?} el |
| * @param {?} style |
| * @param {?} flags |
| * @return {?} |
| */ |
| removeStyle(el, style, flags) { |
| if (flags & RendererStyleFlags2.DashCase) { |
| el.style.removeProperty(style); |
| } |
| else { |
| // IE requires '' instead of null |
| // see https://github.com/angular/angular/issues/7916 |
| el.style[style] = ''; |
| } |
| } |
| /** |
| * @param {?} el |
| * @param {?} name |
| * @param {?} value |
| * @return {?} |
| */ |
| setProperty(el, name, value) { |
| checkNoSyntheticProp(name, 'property'); |
| el[name] = value; |
| } |
| /** |
| * @param {?} node |
| * @param {?} value |
| * @return {?} |
| */ |
| setValue(node, value) { node.nodeValue = value; } |
| /** |
| * @param {?} target |
| * @param {?} event |
| * @param {?} callback |
| * @return {?} |
| */ |
| listen(target, event, callback) { |
| checkNoSyntheticProp(event, 'listener'); |
| if (typeof target === 'string') { |
| return /** @type {?} */ (this.eventManager.addGlobalEventListener(target, event, decoratePreventDefault(callback))); |
| } |
| return /** @type {?} */ ((this.eventManager.addEventListener(target, event, decoratePreventDefault(callback)))); |
| } |
| } |
| const AT_CHARCODE = '@'.charCodeAt(0); |
| /** |
| * @param {?} name |
| * @param {?} nameKind |
| * @return {?} |
| */ |
| function checkNoSyntheticProp(name, nameKind) { |
| if (name.charCodeAt(0) === AT_CHARCODE) { |
| throw new Error(`Found the synthetic ${nameKind} ${name}. Please include either "BrowserAnimationsModule" or "NoopAnimationsModule" in your application.`); |
| } |
| } |
| class EmulatedEncapsulationDomRenderer2 extends DefaultDomRenderer2 { |
| /** |
| * @param {?} eventManager |
| * @param {?} sharedStylesHost |
| * @param {?} component |
| */ |
| constructor(eventManager, sharedStylesHost, component) { |
| super(eventManager); |
| this.component = component; |
| const /** @type {?} */ styles = flattenStyles(component.id, component.styles, []); |
| sharedStylesHost.addStyles(styles); |
| this.contentAttr = shimContentAttribute(component.id); |
| this.hostAttr = shimHostAttribute(component.id); |
| } |
| /** |
| * @param {?} element |
| * @return {?} |
| */ |
| applyToHost(element) { super.setAttribute(element, this.hostAttr, ''); } |
| /** |
| * @param {?} parent |
| * @param {?} name |
| * @return {?} |
| */ |
| createElement(parent, name) { |
| const /** @type {?} */ el = super.createElement(parent, name); |
| super.setAttribute(el, this.contentAttr, ''); |
| return el; |
| } |
| } |
| class ShadowDomRenderer extends DefaultDomRenderer2 { |
| /** |
| * @param {?} eventManager |
| * @param {?} sharedStylesHost |
| * @param {?} hostEl |
| * @param {?} component |
| */ |
| constructor(eventManager, sharedStylesHost, hostEl, component) { |
| super(eventManager); |
| this.sharedStylesHost = sharedStylesHost; |
| this.hostEl = hostEl; |
| this.component = component; |
| this.shadowRoot = (/** @type {?} */ (hostEl)).createShadowRoot(); |
| this.sharedStylesHost.addHost(this.shadowRoot); |
| const /** @type {?} */ styles = flattenStyles(component.id, component.styles, []); |
| for (let /** @type {?} */ i = 0; i < styles.length; i++) { |
| const /** @type {?} */ styleEl = document.createElement('style'); |
| styleEl.textContent = styles[i]; |
| this.shadowRoot.appendChild(styleEl); |
| } |
| } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| nodeOrShadowRoot(node) { return node === this.hostEl ? this.shadowRoot : node; } |
| /** |
| * @return {?} |
| */ |
| destroy() { this.sharedStylesHost.removeHost(this.shadowRoot); } |
| /** |
| * @param {?} parent |
| * @param {?} newChild |
| * @return {?} |
| */ |
| appendChild(parent, newChild) { |
| return super.appendChild(this.nodeOrShadowRoot(parent), newChild); |
| } |
| /** |
| * @param {?} parent |
| * @param {?} newChild |
| * @param {?} refChild |
| * @return {?} |
| */ |
| insertBefore(parent, newChild, refChild) { |
| return super.insertBefore(this.nodeOrShadowRoot(parent), newChild, refChild); |
| } |
| /** |
| * @param {?} parent |
| * @param {?} oldChild |
| * @return {?} |
| */ |
| removeChild(parent, oldChild) { |
| return super.removeChild(this.nodeOrShadowRoot(parent), oldChild); |
| } |
| /** |
| * @param {?} node |
| * @return {?} |
| */ |
| parentNode(node) { |
| return this.nodeOrShadowRoot(super.parentNode(this.nodeOrShadowRoot(node))); |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const ɵ0 = function (v) { |
| return '__zone_symbol__' + v; |
| }; |
| /** |
| * Detect if Zone is present. If it is then use simple zone aware 'addEventListener' |
| * since Angular can do much more |
| * efficient bookkeeping than Zone can, because we have additional information. This speeds up |
| * addEventListener by 3x. |
| */ |
| const __symbol__ = (typeof Zone !== 'undefined') && (/** @type {?} */ (Zone))['__symbol__'] || ɵ0; |
| const ADD_EVENT_LISTENER = __symbol__('addEventListener'); |
| const REMOVE_EVENT_LISTENER = __symbol__('removeEventListener'); |
| const symbolNames = {}; |
| const FALSE = 'FALSE'; |
| const ANGULAR = 'ANGULAR'; |
| const NATIVE_ADD_LISTENER = 'addEventListener'; |
| const NATIVE_REMOVE_LISTENER = 'removeEventListener'; |
| // use the same symbol string which is used in zone.js |
| const stopSymbol = '__zone_symbol__propagationStopped'; |
| const stopMethodSymbol = '__zone_symbol__stopImmediatePropagation'; |
| const blackListedEvents = (typeof Zone !== 'undefined') && (/** @type {?} */ (Zone))[__symbol__('BLACK_LISTED_EVENTS')]; |
| let blackListedMap; |
| if (blackListedEvents) { |
| blackListedMap = {}; |
| blackListedEvents.forEach(eventName => { blackListedMap[eventName] = eventName; }); |
| } |
| const isBlackListedEvent = function (eventName) { |
| if (!blackListedMap) { |
| return false; |
| } |
| return blackListedMap.hasOwnProperty(eventName); |
| }; |
| // a global listener to handle all dom event, |
| // so we do not need to create a closure everytime |
| const globalListener = function (event) { |
| const /** @type {?} */ symbolName = symbolNames[event.type]; |
| if (!symbolName) { |
| return; |
| } |
| const /** @type {?} */ taskDatas = this[symbolName]; |
| if (!taskDatas) { |
| return; |
| } |
| const /** @type {?} */ args = [event]; |
| if (taskDatas.length === 1) { |
| // if taskDatas only have one element, just invoke it |
| const /** @type {?} */ taskData = taskDatas[0]; |
| if (taskData.zone !== Zone.current) { |
| // only use Zone.run when Zone.current not equals to stored zone |
| return taskData.zone.run(taskData.handler, this, args); |
| } |
| else { |
| return taskData.handler.apply(this, args); |
| } |
| } |
| else { |
| // copy tasks as a snapshot to avoid event handlers remove |
| // itself or others |
| const /** @type {?} */ copiedTasks = taskDatas.slice(); |
| for (let /** @type {?} */ i = 0; i < copiedTasks.length; i++) { |
| // if other listener call event.stopImmediatePropagation |
| // just break |
| if ((/** @type {?} */ (event))[stopSymbol] === true) { |
| break; |
| } |
| const /** @type {?} */ taskData = copiedTasks[i]; |
| if (taskData.zone !== Zone.current) { |
| // only use Zone.run when Zone.current not equals to stored zone |
| taskData.zone.run(taskData.handler, this, args); |
| } |
| else { |
| taskData.handler.apply(this, args); |
| } |
| } |
| } |
| }; |
| class DomEventsPlugin extends EventManagerPlugin { |
| /** |
| * @param {?} doc |
| * @param {?} ngZone |
| */ |
| constructor(doc, ngZone) { |
| super(doc); |
| this.ngZone = ngZone; |
| this.patchEvent(); |
| } |
| /** |
| * @return {?} |
| */ |
| patchEvent() { |
| if (!Event || !Event.prototype) { |
| return; |
| } |
| if ((/** @type {?} */ (Event.prototype))[stopMethodSymbol]) { |
| // already patched by zone.js |
| return; |
| } |
| const /** @type {?} */ delegate = (/** @type {?} */ (Event.prototype))[stopMethodSymbol] = |
| Event.prototype.stopImmediatePropagation; |
| Event.prototype.stopImmediatePropagation = function () { |
| if (this) { |
| this[stopSymbol] = true; |
| } |
| // should call native delegate in case |
| // in some enviroment part of the application |
| // will not use the patched Event |
| delegate && delegate.apply(this, arguments); |
| }; |
| } |
| /** |
| * @param {?} eventName |
| * @return {?} |
| */ |
| supports(eventName) { return true; } |
| /** |
| * @param {?} element |
| * @param {?} eventName |
| * @param {?} handler |
| * @return {?} |
| */ |
| addEventListener(element, eventName, handler) { |
| /** |
| * This code is about to add a listener to the DOM. If Zone.js is present, than |
| * `addEventListener` has been patched. The patched code adds overhead in both |
| * memory and speed (3x slower) than native. For this reason if we detect that |
| * Zone.js is present we use a simple version of zone aware addEventListener instead. |
| * The result is faster registration and the zone will be restored. |
| * But ZoneSpec.onScheduleTask, ZoneSpec.onInvokeTask, ZoneSpec.onCancelTask |
| * will not be invoked |
| * We also do manual zone restoration in element.ts renderEventHandlerClosure method. |
| * |
| * NOTE: it is possible that the element is from different iframe, and so we |
| * have to check before we execute the method. |
| */ |
| const /** @type {?} */ self = this; |
| const /** @type {?} */ zoneJsLoaded = element[ADD_EVENT_LISTENER]; |
| let /** @type {?} */ callback = /** @type {?} */ (handler); |
| // if zonejs is loaded and current zone is not ngZone |
| // we keep Zone.current on target for later restoration. |
| if (zoneJsLoaded && (!NgZone.isInAngularZone() || isBlackListedEvent(eventName))) { |
| let /** @type {?} */ symbolName = symbolNames[eventName]; |
| if (!symbolName) { |
| symbolName = symbolNames[eventName] = __symbol__(ANGULAR + eventName + FALSE); |
| } |
| let /** @type {?} */ taskDatas = (/** @type {?} */ (element))[symbolName]; |
| const /** @type {?} */ globalListenerRegistered = taskDatas && taskDatas.length > 0; |
| if (!taskDatas) { |
| taskDatas = (/** @type {?} */ (element))[symbolName] = []; |
| } |
| const /** @type {?} */ zone = isBlackListedEvent(eventName) ? Zone.root : Zone.current; |
| if (taskDatas.length === 0) { |
| taskDatas.push({ zone: zone, handler: callback }); |
| } |
| else { |
| let /** @type {?} */ callbackRegistered = false; |
| for (let /** @type {?} */ i = 0; i < taskDatas.length; i++) { |
| if (taskDatas[i].handler === callback) { |
| callbackRegistered = true; |
| break; |
| } |
| } |
| if (!callbackRegistered) { |
| taskDatas.push({ zone: zone, handler: callback }); |
| } |
| } |
| if (!globalListenerRegistered) { |
| element[ADD_EVENT_LISTENER](eventName, globalListener, false); |
| } |
| } |
| else { |
| element[NATIVE_ADD_LISTENER](eventName, callback, false); |
| } |
| return () => this.removeEventListener(element, eventName, callback); |
| } |
| /** |
| * @param {?} target |
| * @param {?} eventName |
| * @param {?} callback |
| * @return {?} |
| */ |
| removeEventListener(target, eventName, callback) { |
| let /** @type {?} */ underlyingRemove = target[REMOVE_EVENT_LISTENER]; |
| // zone.js not loaded, use native removeEventListener |
| if (!underlyingRemove) { |
| return target[NATIVE_REMOVE_LISTENER].apply(target, [eventName, callback, false]); |
| } |
| let /** @type {?} */ symbolName = symbolNames[eventName]; |
| let /** @type {?} */ taskDatas = symbolName && target[symbolName]; |
| if (!taskDatas) { |
| // addEventListener not using patched version |
| // just call native removeEventListener |
| return target[NATIVE_REMOVE_LISTENER].apply(target, [eventName, callback, false]); |
| } |
| // fix issue 20532, should be able to remove |
| // listener which was added inside of ngZone |
| let /** @type {?} */ found = false; |
| for (let /** @type {?} */ i = 0; i < taskDatas.length; i++) { |
| // remove listener from taskDatas if the callback equals |
| if (taskDatas[i].handler === callback) { |
| found = true; |
| taskDatas.splice(i, 1); |
| break; |
| } |
| } |
| if (found) { |
| if (taskDatas.length === 0) { |
| // all listeners are removed, we can remove the globalListener from target |
| underlyingRemove.apply(target, [eventName, globalListener, false]); |
| } |
| } |
| else { |
| // not found in taskDatas, the callback may be added inside of ngZone |
| // use native remove listener to remove the calback |
| target[NATIVE_REMOVE_LISTENER].apply(target, [eventName, callback, false]); |
| } |
| } |
| } |
| DomEventsPlugin.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| DomEventsPlugin.ctorParameters = () => [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] }, |
| { type: NgZone, }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const EVENT_NAMES = { |
| // pan |
| 'pan': true, |
| 'panstart': true, |
| 'panmove': true, |
| 'panend': true, |
| 'pancancel': true, |
| 'panleft': true, |
| 'panright': true, |
| 'panup': true, |
| 'pandown': true, |
| // pinch |
| 'pinch': true, |
| 'pinchstart': true, |
| 'pinchmove': true, |
| 'pinchend': true, |
| 'pinchcancel': true, |
| 'pinchin': true, |
| 'pinchout': true, |
| // press |
| 'press': true, |
| 'pressup': true, |
| // rotate |
| 'rotate': true, |
| 'rotatestart': true, |
| 'rotatemove': true, |
| 'rotateend': true, |
| 'rotatecancel': true, |
| // swipe |
| 'swipe': true, |
| 'swipeleft': true, |
| 'swiperight': true, |
| 'swipeup': true, |
| 'swipedown': true, |
| // tap |
| 'tap': true, |
| }; |
| /** |
| * A DI token that you can use to provide{\@link HammerGestureConfig} to Angular. Use it to configure |
| * Hammer gestures. |
| * |
| * \@experimental |
| */ |
| const HAMMER_GESTURE_CONFIG = new InjectionToken('HammerGestureConfig'); |
| /** |
| * @record |
| */ |
| |
| /** |
| * \@experimental |
| */ |
| class HammerGestureConfig { |
| constructor() { |
| this.events = []; |
| this.overrides = {}; |
| } |
| /** |
| * @param {?} element |
| * @return {?} |
| */ |
| buildHammer(element) { |
| const /** @type {?} */ mc = new Hammer(element); |
| mc.get('pinch').set({ enable: true }); |
| mc.get('rotate').set({ enable: true }); |
| for (const /** @type {?} */ eventName in this.overrides) { |
| mc.get(eventName).set(this.overrides[eventName]); |
| } |
| return mc; |
| } |
| } |
| HammerGestureConfig.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| HammerGestureConfig.ctorParameters = () => []; |
| class HammerGesturesPlugin extends EventManagerPlugin { |
| /** |
| * @param {?} doc |
| * @param {?} _config |
| */ |
| constructor(doc, _config) { |
| super(doc); |
| this._config = _config; |
| } |
| /** |
| * @param {?} eventName |
| * @return {?} |
| */ |
| supports(eventName) { |
| if (!EVENT_NAMES.hasOwnProperty(eventName.toLowerCase()) && !this.isCustomEvent(eventName)) { |
| return false; |
| } |
| if (!(/** @type {?} */ (window)).Hammer) { |
| throw new Error(`Hammer.js is not loaded, can not bind ${eventName} event`); |
| } |
| return true; |
| } |
| /** |
| * @param {?} element |
| * @param {?} eventName |
| * @param {?} handler |
| * @return {?} |
| */ |
| addEventListener(element, eventName, handler) { |
| const /** @type {?} */ zone = this.manager.getZone(); |
| eventName = eventName.toLowerCase(); |
| return zone.runOutsideAngular(() => { |
| // Creating the manager bind events, must be done outside of angular |
| const /** @type {?} */ mc = this._config.buildHammer(element); |
| const /** @type {?} */ callback = function (eventObj) { |
| zone.runGuarded(function () { handler(eventObj); }); |
| }; |
| mc.on(eventName, callback); |
| return () => mc.off(eventName, callback); |
| }); |
| } |
| /** |
| * @param {?} eventName |
| * @return {?} |
| */ |
| isCustomEvent(eventName) { return this._config.events.indexOf(eventName) > -1; } |
| } |
| HammerGesturesPlugin.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| HammerGesturesPlugin.ctorParameters = () => [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] }, |
| { type: HammerGestureConfig, decorators: [{ type: Inject, args: [HAMMER_GESTURE_CONFIG,] },] }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const MODIFIER_KEYS = ['alt', 'control', 'meta', 'shift']; |
| const ɵ0$1 = (event) => event.altKey; |
| const ɵ1$1 = (event) => event.ctrlKey; |
| const ɵ2$1 = (event) => event.metaKey; |
| const ɵ3 = (event) => event.shiftKey; |
| const MODIFIER_KEY_GETTERS = { |
| 'alt': ɵ0$1, |
| 'control': ɵ1$1, |
| 'meta': ɵ2$1, |
| 'shift': ɵ3 |
| }; |
| /** |
| * \@experimental |
| */ |
| class KeyEventsPlugin extends EventManagerPlugin { |
| /** |
| * @param {?} doc |
| */ |
| constructor(doc) { super(doc); } |
| /** |
| * @param {?} eventName |
| * @return {?} |
| */ |
| supports(eventName) { return KeyEventsPlugin.parseEventName(eventName) != null; } |
| /** |
| * @param {?} element |
| * @param {?} eventName |
| * @param {?} handler |
| * @return {?} |
| */ |
| addEventListener(element, eventName, handler) { |
| const /** @type {?} */ parsedEvent = /** @type {?} */ ((KeyEventsPlugin.parseEventName(eventName))); |
| const /** @type {?} */ outsideHandler = KeyEventsPlugin.eventCallback(parsedEvent['fullKey'], handler, this.manager.getZone()); |
| return this.manager.getZone().runOutsideAngular(() => { |
| return getDOM().onAndCancel(element, parsedEvent['domEventName'], outsideHandler); |
| }); |
| } |
| /** |
| * @param {?} eventName |
| * @return {?} |
| */ |
| static parseEventName(eventName) { |
| const /** @type {?} */ parts = eventName.toLowerCase().split('.'); |
| const /** @type {?} */ domEventName = parts.shift(); |
| if ((parts.length === 0) || !(domEventName === 'keydown' || domEventName === 'keyup')) { |
| return null; |
| } |
| const /** @type {?} */ key = KeyEventsPlugin._normalizeKey(/** @type {?} */ ((parts.pop()))); |
| let /** @type {?} */ fullKey = ''; |
| MODIFIER_KEYS.forEach(modifierName => { |
| const /** @type {?} */ index = parts.indexOf(modifierName); |
| if (index > -1) { |
| parts.splice(index, 1); |
| fullKey += modifierName + '.'; |
| } |
| }); |
| fullKey += key; |
| if (parts.length != 0 || key.length === 0) { |
| // returning null instead of throwing to let another plugin process the event |
| return null; |
| } |
| const /** @type {?} */ result = {}; |
| result['domEventName'] = domEventName; |
| result['fullKey'] = fullKey; |
| return result; |
| } |
| /** |
| * @param {?} event |
| * @return {?} |
| */ |
| static getEventFullKey(event) { |
| let /** @type {?} */ fullKey = ''; |
| let /** @type {?} */ key = getDOM().getEventKey(event); |
| key = key.toLowerCase(); |
| if (key === ' ') { |
| key = 'space'; // for readability |
| } |
| else if (key === '.') { |
| key = 'dot'; // because '.' is used as a separator in event names |
| } |
| MODIFIER_KEYS.forEach(modifierName => { |
| if (modifierName != key) { |
| const /** @type {?} */ modifierGetter = MODIFIER_KEY_GETTERS[modifierName]; |
| if (modifierGetter(event)) { |
| fullKey += modifierName + '.'; |
| } |
| } |
| }); |
| fullKey += key; |
| return fullKey; |
| } |
| /** |
| * @param {?} fullKey |
| * @param {?} handler |
| * @param {?} zone |
| * @return {?} |
| */ |
| static eventCallback(fullKey, handler, zone) { |
| return (event /** TODO #9100 */) => { |
| if (KeyEventsPlugin.getEventFullKey(event) === fullKey) { |
| zone.runGuarded(() => handler(event)); |
| } |
| }; |
| } |
| /** |
| * \@internal |
| * @param {?} keyName |
| * @return {?} |
| */ |
| static _normalizeKey(keyName) { |
| // TODO: switch to a Map if the mapping grows too much |
| switch (keyName) { |
| case 'esc': |
| return 'escape'; |
| default: |
| return keyName; |
| } |
| } |
| } |
| KeyEventsPlugin.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| KeyEventsPlugin.ctorParameters = () => [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * A pattern that recognizes a commonly useful subset of URLs that are safe. |
| * |
| * This regular expression matches a subset of URLs that will not cause script |
| * execution if used in URL context within a HTML document. Specifically, this |
| * regular expression matches if (comment from here on and regex copied from |
| * Soy's EscapingConventions): |
| * (1) Either a protocol in a whitelist (http, https, mailto or ftp). |
| * (2) or no protocol. A protocol must be followed by a colon. The below |
| * allows that by allowing colons only after one of the characters [/?#]. |
| * A colon after a hash (#) must be in the fragment. |
| * Otherwise, a colon after a (?) must be in a query. |
| * Otherwise, a colon after a single solidus (/) must be in a path. |
| * Otherwise, a colon after a double solidus (//) must be in the authority |
| * (before port). |
| * |
| * The pattern disallows &, used in HTML entity declarations before |
| * one of the characters in [/?#]. This disallows HTML entities used in the |
| * protocol name, which should never happen, e.g. "http" for "http". |
| * It also disallows HTML entities in the first path part of a relative path, |
| * e.g. "foo<bar/baz". Our existing escaping functions should not produce |
| * that. More importantly, it disallows masking of a colon, |
| * e.g. "javascript:...". |
| * |
| * This regular expression was taken from the Closure sanitization library. |
| */ |
| const SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi; |
| /** |
| * A pattern that matches safe data URLs. Only matches image, video and audio types. |
| */ |
| const DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+\/]+=*$/i; |
| /** |
| * @param {?} url |
| * @return {?} |
| */ |
| function sanitizeUrl(url) { |
| url = String(url); |
| if (url.match(SAFE_URL_PATTERN) || url.match(DATA_URL_PATTERN)) |
| return url; |
| if (isDevMode()) { |
| getDOM().log(`WARNING: sanitizing unsafe URL value ${url} (see http://g.co/ng/security#xss)`); |
| } |
| return 'unsafe:' + url; |
| } |
| /** |
| * @param {?} srcset |
| * @return {?} |
| */ |
| function sanitizeSrcset(srcset) { |
| srcset = String(srcset); |
| return srcset.split(',').map((srcset) => sanitizeUrl(srcset.trim())).join(', '); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * A <body> element that can be safely used to parse untrusted HTML. Lazily initialized below. |
| */ |
| let inertElement = null; |
| /** |
| * Lazily initialized to make sure the DOM adapter gets set before use. |
| */ |
| let DOM = /** @type {?} */ ((null)); |
| /** |
| * Returns an HTML element that is guaranteed to not execute code when creating elements in it. |
| * @return {?} |
| */ |
| function getInertElement() { |
| if (inertElement) |
| return inertElement; |
| DOM = getDOM(); |
| // Prefer using <template> element if supported. |
| const /** @type {?} */ templateEl = DOM.createElement('template'); |
| if ('content' in templateEl) |
| return templateEl; |
| const /** @type {?} */ doc = DOM.createHtmlDocument(); |
| inertElement = DOM.querySelector(doc, 'body'); |
| if (inertElement == null) { |
| // usually there should be only one body element in the document, but IE doesn't have any, so we |
| // need to create one. |
| const /** @type {?} */ html = DOM.createElement('html', doc); |
| inertElement = DOM.createElement('body', doc); |
| DOM.appendChild(html, inertElement); |
| DOM.appendChild(doc, html); |
| } |
| return inertElement; |
| } |
| /** |
| * @param {?} tags |
| * @return {?} |
| */ |
| function tagSet(tags) { |
| const /** @type {?} */ res = {}; |
| for (const /** @type {?} */ t of tags.split(',')) |
| res[t] = true; |
| return res; |
| } |
| /** |
| * @param {...?} sets |
| * @return {?} |
| */ |
| function merge(...sets) { |
| const /** @type {?} */ res = {}; |
| for (const /** @type {?} */ s of sets) { |
| for (const /** @type {?} */ v in s) { |
| if (s.hasOwnProperty(v)) |
| res[v] = true; |
| } |
| } |
| return res; |
| } |
| // Good source of info about elements and attributes |
| // http://dev.w3.org/html5/spec/Overview.html#semantics |
| // http://simon.html5.org/html-elements |
| // Safe Void Elements - HTML5 |
| // http://dev.w3.org/html5/spec/Overview.html#void-elements |
| const VOID_ELEMENTS = tagSet('area,br,col,hr,img,wbr'); |
| // Elements that you can, intentionally, leave open (and which close themselves) |
| // http://dev.w3.org/html5/spec/Overview.html#optional-tags |
| const OPTIONAL_END_TAG_BLOCK_ELEMENTS = tagSet('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'); |
| const OPTIONAL_END_TAG_INLINE_ELEMENTS = tagSet('rp,rt'); |
| const OPTIONAL_END_TAG_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, OPTIONAL_END_TAG_BLOCK_ELEMENTS); |
| // Safe Block Elements - HTML5 |
| const BLOCK_ELEMENTS = merge(OPTIONAL_END_TAG_BLOCK_ELEMENTS, tagSet('address,article,' + |
| 'aside,blockquote,caption,center,del,details,dialog,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' + |
| 'h6,header,hgroup,hr,ins,main,map,menu,nav,ol,pre,section,summary,table,ul')); |
| // Inline Elements - HTML5 |
| const INLINE_ELEMENTS = merge(OPTIONAL_END_TAG_INLINE_ELEMENTS, tagSet('a,abbr,acronym,audio,b,' + |
| 'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,picture,q,ruby,rp,rt,s,' + |
| 'samp,small,source,span,strike,strong,sub,sup,time,track,tt,u,var,video')); |
| const VALID_ELEMENTS = merge(VOID_ELEMENTS, BLOCK_ELEMENTS, INLINE_ELEMENTS, OPTIONAL_END_TAG_ELEMENTS); |
| // Attributes that have href and hence need to be sanitized |
| const URI_ATTRS = tagSet('background,cite,href,itemtype,longdesc,poster,src,xlink:href'); |
| // Attributes that have special href set hence need to be sanitized |
| const SRCSET_ATTRS = tagSet('srcset'); |
| const HTML_ATTRS = tagSet('abbr,accesskey,align,alt,autoplay,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,' + |
| 'compact,controls,coords,datetime,default,dir,download,face,headers,height,hidden,hreflang,hspace,' + |
| 'ismap,itemscope,itemprop,kind,label,lang,language,loop,media,muted,nohref,nowrap,open,preload,rel,rev,role,rows,rowspan,rules,' + |
| 'scope,scrolling,shape,size,sizes,span,srclang,start,summary,tabindex,target,title,translate,type,usemap,' + |
| 'valign,value,vspace,width'); |
| // NB: This currently consciously doesn't support SVG. SVG sanitization has had several security |
| // issues in the past, so it seems safer to leave it out if possible. If support for binding SVG via |
| // innerHTML is required, SVG attributes should be added here. |
| // NB: Sanitization does not allow <form> elements or other active elements (<button> etc). Those |
| // can be sanitized, but they increase security surface area without a legitimate use case, so they |
| // are left out here. |
| const VALID_ATTRS = merge(URI_ATTRS, SRCSET_ATTRS, HTML_ATTRS); |
| /** |
| * SanitizingHtmlSerializer serializes a DOM fragment, stripping out any unsafe elements and unsafe |
| * attributes. |
| */ |
| class SanitizingHtmlSerializer { |
| constructor() { |
| this.sanitizedSomething = false; |
| this.buf = []; |
| } |
| /** |
| * @param {?} el |
| * @return {?} |
| */ |
| sanitizeChildren(el) { |
| // This cannot use a TreeWalker, as it has to run on Angular's various DOM adapters. |
| // However this code never accesses properties off of `document` before deleting its contents |
| // again, so it shouldn't be vulnerable to DOM clobbering. |
| let /** @type {?} */ current = /** @type {?} */ ((el.firstChild)); |
| while (current) { |
| if (DOM.isElementNode(current)) { |
| this.startElement(/** @type {?} */ (current)); |
| } |
| else if (DOM.isTextNode(current)) { |
| this.chars(/** @type {?} */ ((DOM.nodeValue(current)))); |
| } |
| else { |
| // Strip non-element, non-text nodes. |
| this.sanitizedSomething = true; |
| } |
| if (DOM.firstChild(current)) { |
| current = /** @type {?} */ ((DOM.firstChild(current))); |
| continue; |
| } |
| while (current) { |
| // Leaving the element. Walk up and to the right, closing tags as we go. |
| if (DOM.isElementNode(current)) { |
| this.endElement(/** @type {?} */ (current)); |
| } |
| let /** @type {?} */ next = checkClobberedElement(current, /** @type {?} */ ((DOM.nextSibling(current)))); |
| if (next) { |
| current = next; |
| break; |
| } |
| current = checkClobberedElement(current, /** @type {?} */ ((DOM.parentElement(current)))); |
| } |
| } |
| return this.buf.join(''); |
| } |
| /** |
| * @param {?} element |
| * @return {?} |
| */ |
| startElement(element) { |
| const /** @type {?} */ tagName = DOM.nodeName(element).toLowerCase(); |
| if (!VALID_ELEMENTS.hasOwnProperty(tagName)) { |
| this.sanitizedSomething = true; |
| return; |
| } |
| this.buf.push('<'); |
| this.buf.push(tagName); |
| DOM.attributeMap(element).forEach((value, attrName) => { |
| const /** @type {?} */ lower = attrName.toLowerCase(); |
| if (!VALID_ATTRS.hasOwnProperty(lower)) { |
| this.sanitizedSomething = true; |
| return; |
| } |
| // TODO(martinprobst): Special case image URIs for data:image/... |
| if (URI_ATTRS[lower]) |
| value = sanitizeUrl(value); |
| if (SRCSET_ATTRS[lower]) |
| value = sanitizeSrcset(value); |
| this.buf.push(' '); |
| this.buf.push(attrName); |
| this.buf.push('="'); |
| this.buf.push(encodeEntities(value)); |
| this.buf.push('"'); |
| }); |
| this.buf.push('>'); |
| } |
| /** |
| * @param {?} current |
| * @return {?} |
| */ |
| endElement(current) { |
| const /** @type {?} */ tagName = DOM.nodeName(current).toLowerCase(); |
| if (VALID_ELEMENTS.hasOwnProperty(tagName) && !VOID_ELEMENTS.hasOwnProperty(tagName)) { |
| this.buf.push('</'); |
| this.buf.push(tagName); |
| this.buf.push('>'); |
| } |
| } |
| /** |
| * @param {?} chars |
| * @return {?} |
| */ |
| chars(chars) { this.buf.push(encodeEntities(chars)); } |
| } |
| /** |
| * @param {?} node |
| * @param {?} nextNode |
| * @return {?} |
| */ |
| function checkClobberedElement(node, nextNode) { |
| if (nextNode && DOM.contains(node, nextNode)) { |
| throw new Error(`Failed to sanitize html because the element is clobbered: ${DOM.getOuterHTML(node)}`); |
| } |
| return nextNode; |
| } |
| // Regular Expressions for parsing tags and attributes |
| const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; |
| // ! to ~ is the ASCII range. |
| const NON_ALPHANUMERIC_REGEXP = /([^\#-~ |!])/g; |
| /** |
| * Escapes all potentially dangerous characters, so that the |
| * resulting string can be safely inserted into attribute or |
| * element text. |
| * @param {?} value |
| * @return {?} |
| */ |
| function encodeEntities(value) { |
| return value.replace(/&/g, '&') |
| .replace(SURROGATE_PAIR_REGEXP, function (match) { |
| const /** @type {?} */ hi = match.charCodeAt(0); |
| const /** @type {?} */ low = match.charCodeAt(1); |
| return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';'; |
| }) |
| .replace(NON_ALPHANUMERIC_REGEXP, function (match) { return '&#' + match.charCodeAt(0) + ';'; }) |
| .replace(/</g, '<') |
| .replace(/>/g, '>'); |
| } |
| /** |
| * When IE9-11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1' |
| * attribute to declare ns1 namespace and prefixes the attribute with 'ns1' (e.g. 'ns1:xlink:foo'). |
| * |
| * This is undesirable since we don't want to allow any of these custom attributes. This method |
| * strips them all. |
| * @param {?} el |
| * @return {?} |
| */ |
| function stripCustomNsAttrs(el) { |
| DOM.attributeMap(el).forEach((_, attrName) => { |
| if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) { |
| DOM.removeAttribute(el, attrName); |
| } |
| }); |
| for (const /** @type {?} */ n of DOM.childNodesAsList(el)) { |
| if (DOM.isElementNode(n)) |
| stripCustomNsAttrs(/** @type {?} */ (n)); |
| } |
| } |
| /** |
| * Sanitizes the given unsafe, untrusted HTML fragment, and returns HTML text that is safe to add to |
| * the DOM in a browser environment. |
| * @param {?} defaultDoc |
| * @param {?} unsafeHtmlInput |
| * @return {?} |
| */ |
| function sanitizeHtml(defaultDoc, unsafeHtmlInput) { |
| try { |
| const /** @type {?} */ containerEl = getInertElement(); |
| // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime). |
| let /** @type {?} */ unsafeHtml = unsafeHtmlInput ? String(unsafeHtmlInput) : ''; |
| // mXSS protection. Repeatedly parse the document to make sure it stabilizes, so that a browser |
| // trying to auto-correct incorrect HTML cannot cause formerly inert HTML to become dangerous. |
| let /** @type {?} */ mXSSAttempts = 5; |
| let /** @type {?} */ parsedHtml = unsafeHtml; |
| do { |
| if (mXSSAttempts === 0) { |
| throw new Error('Failed to sanitize html because the input is unstable'); |
| } |
| mXSSAttempts--; |
| unsafeHtml = parsedHtml; |
| DOM.setInnerHTML(containerEl, unsafeHtml); |
| if (defaultDoc.documentMode) { |
| // strip custom-namespaced attributes on IE<=11 |
| stripCustomNsAttrs(containerEl); |
| } |
| parsedHtml = DOM.getInnerHTML(containerEl); |
| } while (unsafeHtml !== parsedHtml); |
| const /** @type {?} */ sanitizer = new SanitizingHtmlSerializer(); |
| const /** @type {?} */ safeHtml = sanitizer.sanitizeChildren(DOM.getTemplateContent(containerEl) || containerEl); |
| // Clear out the body element. |
| const /** @type {?} */ parent = DOM.getTemplateContent(containerEl) || containerEl; |
| for (const /** @type {?} */ child of DOM.childNodesAsList(parent)) { |
| DOM.removeChild(parent, child); |
| } |
| if (isDevMode() && sanitizer.sanitizedSomething) { |
| DOM.log('WARNING: sanitizing HTML stripped some content (see http://g.co/ng/security#xss).'); |
| } |
| return safeHtml; |
| } |
| catch (/** @type {?} */ e) { |
| // In case anything goes wrong, clear out inertElement to reset the entire DOM structure. |
| inertElement = null; |
| throw e; |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * Regular expression for safe style values. |
| * |
| * Quotes (" and ') are allowed, but a check must be done elsewhere to ensure they're balanced. |
| * |
| * ',' allows multiple values to be assigned to the same property (e.g. background-attachment or |
| * font-family) and hence could allow multiple values to get injected, but that should pose no risk |
| * of XSS. |
| * |
| * The function expression checks only for XSS safety, not for CSS validity. |
| * |
| * This regular expression was taken from the Closure sanitization library, and augmented for |
| * transformation values. |
| */ |
| const VALUES = '[-,."\'%_!# a-zA-Z0-9]+'; |
| const TRANSFORMATION_FNS = '(?:matrix|translate|scale|rotate|skew|perspective)(?:X|Y|3d)?'; |
| const COLOR_FNS = '(?:rgb|hsl)a?'; |
| const GRADIENTS = '(?:repeating-)?(?:linear|radial)-gradient'; |
| const CSS3_FNS = '(?:calc|attr)'; |
| const FN_ARGS = '\\([-0-9.%, #a-zA-Z]+\\)'; |
| const SAFE_STYLE_VALUE = new RegExp(`^(${VALUES}|` + |
| `(?:${TRANSFORMATION_FNS}|${COLOR_FNS}|${GRADIENTS}|${CSS3_FNS})` + |
| `${FN_ARGS})$`, 'g'); |
| /** |
| * Matches a `url(...)` value with an arbitrary argument as long as it does |
| * not contain parentheses. |
| * |
| * The URL value still needs to be sanitized separately. |
| * |
| * `url(...)` values are a very common use case, e.g. for `background-image`. With carefully crafted |
| * CSS style rules, it is possible to construct an information leak with `url` values in CSS, e.g. |
| * by observing whether scroll bars are displayed, or character ranges used by a font face |
| * definition. |
| * |
| * Angular only allows binding CSS values (as opposed to entire CSS rules), so it is unlikely that |
| * binding a URL value without further cooperation from the page will cause an information leak, and |
| * if so, it is just a leak, not a full blown XSS vulnerability. |
| * |
| * Given the common use case, low likelihood of attack vector, and low impact of an attack, this |
| * code is permissive and allows URLs that sanitize otherwise. |
| */ |
| const URL_RE = /^url\(([^)]+)\)$/; |
| /** |
| * Checks that quotes (" and ') are properly balanced inside a string. Assumes |
| * that neither escape (\) nor any other character that could result in |
| * breaking out of a string parsing context are allowed; |
| * see http://www.w3.org/TR/css3-syntax/#string-token-diagram. |
| * |
| * This code was taken from the Closure sanitization library. |
| * @param {?} value |
| * @return {?} |
| */ |
| function hasBalancedQuotes(value) { |
| let /** @type {?} */ outsideSingle = true; |
| let /** @type {?} */ outsideDouble = true; |
| for (let /** @type {?} */ i = 0; i < value.length; i++) { |
| const /** @type {?} */ c = value.charAt(i); |
| if (c === '\'' && outsideDouble) { |
| outsideSingle = !outsideSingle; |
| } |
| else if (c === '"' && outsideSingle) { |
| outsideDouble = !outsideDouble; |
| } |
| } |
| return outsideSingle && outsideDouble; |
| } |
| /** |
| * Sanitizes the given untrusted CSS style property value (i.e. not an entire object, just a single |
| * value) and returns a value that is safe to use in a browser environment. |
| * @param {?} value |
| * @return {?} |
| */ |
| function sanitizeStyle(value) { |
| value = String(value).trim(); // Make sure it's actually a string. |
| if (!value) |
| return ''; |
| // Single url(...) values are supported, but only for URLs that sanitize cleanly. See above for |
| // reasoning behind this. |
| const /** @type {?} */ urlMatch = value.match(URL_RE); |
| if ((urlMatch && sanitizeUrl(urlMatch[1]) === urlMatch[1]) || |
| value.match(SAFE_STYLE_VALUE) && hasBalancedQuotes(value)) { |
| return value; // Safe style values. |
| } |
| if (isDevMode()) { |
| getDOM().log(`WARNING: sanitizing unsafe style value ${value} (see http://g.co/ng/security#xss).`); |
| } |
| return 'unsafe'; |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * Marker interface for a value that's safe to use in a particular context. |
| * |
| * \@stable |
| * @record |
| */ |
| |
| /** |
| * Marker interface for a value that's safe to use as HTML. |
| * |
| * \@stable |
| * @record |
| */ |
| |
| /** |
| * Marker interface for a value that's safe to use as style (CSS). |
| * |
| * \@stable |
| * @record |
| */ |
| |
| /** |
| * Marker interface for a value that's safe to use as JavaScript. |
| * |
| * \@stable |
| * @record |
| */ |
| |
| /** |
| * Marker interface for a value that's safe to use as a URL linking to a document. |
| * |
| * \@stable |
| * @record |
| */ |
| |
| /** |
| * Marker interface for a value that's safe to use as a URL to load executable code from. |
| * |
| * \@stable |
| * @record |
| */ |
| |
| /** |
| * DomSanitizer helps preventing Cross Site Scripting Security bugs (XSS) by sanitizing |
| * values to be safe to use in the different DOM contexts. |
| * |
| * For example, when binding a URL in an `<a [href]="someValue">` hyperlink, `someValue` will be |
| * sanitized so that an attacker cannot inject e.g. a `javascript:` URL that would execute code on |
| * the website. |
| * |
| * In specific situations, it might be necessary to disable sanitization, for example if the |
| * application genuinely needs to produce a `javascript:` style link with a dynamic value in it. |
| * Users can bypass security by constructing a value with one of the `bypassSecurityTrust...` |
| * methods, and then binding to that value from the template. |
| * |
| * These situations should be very rare, and extraordinary care must be taken to avoid creating a |
| * Cross Site Scripting (XSS) security bug! |
| * |
| * When using `bypassSecurityTrust...`, make sure to call the method as early as possible and as |
| * close as possible to the source of the value, to make it easy to verify no security bug is |
| * created by its use. |
| * |
| * It is not required (and not recommended) to bypass security if the value is safe, e.g. a URL that |
| * does not start with a suspicious protocol, or an HTML snippet that does not contain dangerous |
| * code. The sanitizer leaves safe values intact. |
| * |
| * \@security Calling any of the `bypassSecurityTrust...` APIs disables Angular's built-in |
| * sanitization for the value passed in. Carefully check and audit all values and code paths going |
| * into this call. Make sure any user data is appropriately escaped for this security context. |
| * For more detail, see the [Security Guide](http://g.co/ng/security). |
| * |
| * \@stable |
| * @abstract |
| */ |
| class DomSanitizer { |
| } |
| class DomSanitizerImpl extends DomSanitizer { |
| /** |
| * @param {?} _doc |
| */ |
| constructor(_doc) { |
| super(); |
| this._doc = _doc; |
| } |
| /** |
| * @param {?} ctx |
| * @param {?} value |
| * @return {?} |
| */ |
| sanitize(ctx, value) { |
| if (value == null) |
| return null; |
| switch (ctx) { |
| case SecurityContext.NONE: |
| return /** @type {?} */ (value); |
| case SecurityContext.HTML: |
| if (value instanceof SafeHtmlImpl) |
| return value.changingThisBreaksApplicationSecurity; |
| this.checkNotSafeValue(value, 'HTML'); |
| return sanitizeHtml(this._doc, String(value)); |
| case SecurityContext.STYLE: |
| if (value instanceof SafeStyleImpl) |
| return value.changingThisBreaksApplicationSecurity; |
| this.checkNotSafeValue(value, 'Style'); |
| return sanitizeStyle(/** @type {?} */ (value)); |
| case SecurityContext.SCRIPT: |
| if (value instanceof SafeScriptImpl) |
| return value.changingThisBreaksApplicationSecurity; |
| this.checkNotSafeValue(value, 'Script'); |
| throw new Error('unsafe value used in a script context'); |
| case SecurityContext.URL: |
| if (value instanceof SafeResourceUrlImpl || value instanceof SafeUrlImpl) { |
| // Allow resource URLs in URL contexts, they are strictly more trusted. |
| return value.changingThisBreaksApplicationSecurity; |
| } |
| this.checkNotSafeValue(value, 'URL'); |
| return sanitizeUrl(String(value)); |
| case SecurityContext.RESOURCE_URL: |
| if (value instanceof SafeResourceUrlImpl) { |
| return value.changingThisBreaksApplicationSecurity; |
| } |
| this.checkNotSafeValue(value, 'ResourceURL'); |
| throw new Error('unsafe value used in a resource URL context (see http://g.co/ng/security#xss)'); |
| default: |
| throw new Error(`Unexpected SecurityContext ${ctx} (see http://g.co/ng/security#xss)`); |
| } |
| } |
| /** |
| * @param {?} value |
| * @param {?} expectedType |
| * @return {?} |
| */ |
| checkNotSafeValue(value, expectedType) { |
| if (value instanceof SafeValueImpl) { |
| throw new Error(`Required a safe ${expectedType}, got a ${value.getTypeName()} ` + |
| `(see http://g.co/ng/security#xss)`); |
| } |
| } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| bypassSecurityTrustHtml(value) { return new SafeHtmlImpl(value); } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| bypassSecurityTrustStyle(value) { return new SafeStyleImpl(value); } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| bypassSecurityTrustScript(value) { return new SafeScriptImpl(value); } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| bypassSecurityTrustUrl(value) { return new SafeUrlImpl(value); } |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| bypassSecurityTrustResourceUrl(value) { |
| return new SafeResourceUrlImpl(value); |
| } |
| } |
| DomSanitizerImpl.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| DomSanitizerImpl.ctorParameters = () => [ |
| { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] }, |
| ]; |
| /** |
| * @abstract |
| */ |
| class SafeValueImpl { |
| /** |
| * @param {?} changingThisBreaksApplicationSecurity |
| */ |
| constructor(changingThisBreaksApplicationSecurity) { |
| // empty |
| this.changingThisBreaksApplicationSecurity = changingThisBreaksApplicationSecurity; |
| } |
| /** |
| * @return {?} |
| */ |
| toString() { |
| return `SafeValue must use [property]=binding: ${this.changingThisBreaksApplicationSecurity}` + |
| ` (see http://g.co/ng/security#xss)`; |
| } |
| } |
| class SafeHtmlImpl extends SafeValueImpl { |
| /** |
| * @return {?} |
| */ |
| getTypeName() { return 'HTML'; } |
| } |
| class SafeStyleImpl extends SafeValueImpl { |
| /** |
| * @return {?} |
| */ |
| getTypeName() { return 'Style'; } |
| } |
| class SafeScriptImpl extends SafeValueImpl { |
| /** |
| * @return {?} |
| */ |
| getTypeName() { return 'Script'; } |
| } |
| class SafeUrlImpl extends SafeValueImpl { |
| /** |
| * @return {?} |
| */ |
| getTypeName() { return 'URL'; } |
| } |
| class SafeResourceUrlImpl extends SafeValueImpl { |
| /** |
| * @return {?} |
| */ |
| getTypeName() { return 'ResourceURL'; } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const INTERNAL_BROWSER_PLATFORM_PROVIDERS = [ |
| { provide: PLATFORM_ID, useValue: ɵPLATFORM_BROWSER_ID }, |
| { provide: PLATFORM_INITIALIZER, useValue: initDomAdapter, multi: true }, |
| { provide: PlatformLocation, useClass: BrowserPlatformLocation, deps: [DOCUMENT$1] }, |
| { provide: DOCUMENT$1, useFactory: _document, deps: [] }, |
| ]; |
| /** |
| * \@security Replacing built-in sanitization providers exposes the application to XSS risks. |
| * Attacker-controlled data introduced by an unsanitized provider could expose your |
| * application to XSS risks. For more detail, see the [Security Guide](http://g.co/ng/security). |
| * \@experimental |
| */ |
| const BROWSER_SANITIZATION_PROVIDERS = [ |
| { provide: Sanitizer, useExisting: DomSanitizer }, |
| { provide: DomSanitizer, useClass: DomSanitizerImpl, deps: [DOCUMENT$1] }, |
| ]; |
| /** |
| * \@stable |
| */ |
| const platformBrowser = createPlatformFactory(platformCore, 'browser', INTERNAL_BROWSER_PLATFORM_PROVIDERS); |
| /** |
| * @return {?} |
| */ |
| function initDomAdapter() { |
| BrowserDomAdapter.makeCurrent(); |
| BrowserGetTestability.init(); |
| } |
| /** |
| * @return {?} |
| */ |
| function errorHandler() { |
| return new ErrorHandler(); |
| } |
| /** |
| * @return {?} |
| */ |
| function _document() { |
| return document; |
| } |
| /** |
| * The ng module for the browser. |
| * |
| * \@stable |
| */ |
| class BrowserModule { |
| /** |
| * @param {?} parentModule |
| */ |
| constructor(parentModule) { |
| if (parentModule) { |
| throw new Error(`BrowserModule has already been loaded. If you need access to common directives such as NgIf and NgFor from a lazy loaded module, import CommonModule instead.`); |
| } |
| } |
| /** |
| * Configures a browser-based application to transition from a server-rendered app, if |
| * one is present on the page. The specified parameters must include an application id, |
| * which must match between the client and server applications. |
| * |
| * \@experimental |
| * @param {?} params |
| * @return {?} |
| */ |
| static withServerTransition(params) { |
| return { |
| ngModule: BrowserModule, |
| providers: [ |
| { provide: APP_ID, useValue: params.appId }, |
| { provide: TRANSITION_ID, useExisting: APP_ID }, |
| SERVER_TRANSITION_PROVIDERS, |
| ], |
| }; |
| } |
| } |
| BrowserModule.decorators = [ |
| { type: NgModule, args: [{ |
| providers: [ |
| BROWSER_SANITIZATION_PROVIDERS, |
| { provide: ErrorHandler, useFactory: errorHandler, deps: [] }, |
| { provide: EVENT_MANAGER_PLUGINS, useClass: DomEventsPlugin, multi: true }, |
| { provide: EVENT_MANAGER_PLUGINS, useClass: KeyEventsPlugin, multi: true }, |
| { provide: EVENT_MANAGER_PLUGINS, useClass: HammerGesturesPlugin, multi: true }, |
| { provide: HAMMER_GESTURE_CONFIG, useClass: HammerGestureConfig }, |
| DomRendererFactory2, |
| { provide: RendererFactory2, useExisting: DomRendererFactory2 }, |
| { provide: SharedStylesHost, useExisting: DomSharedStylesHost }, |
| DomSharedStylesHost, |
| Testability, |
| EventManager, |
| ELEMENT_PROBE_PROVIDERS, |
| Meta, |
| Title, |
| ], |
| exports: [CommonModule, ApplicationModule] |
| },] }, |
| ]; |
| /** @nocollapse */ |
| BrowserModule.ctorParameters = () => [ |
| { type: BrowserModule, decorators: [{ type: Optional }, { type: SkipSelf },] }, |
| ]; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const win = typeof window !== 'undefined' && window || /** @type {?} */ ({}); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| class ChangeDetectionPerfRecord { |
| /** |
| * @param {?} msPerTick |
| * @param {?} numTicks |
| */ |
| constructor(msPerTick, numTicks) { |
| this.msPerTick = msPerTick; |
| this.numTicks = numTicks; |
| } |
| } |
| /** |
| * Entry point for all Angular profiling-related debug tools. This object |
| * corresponds to the `ng.profiler` in the dev console. |
| */ |
| class AngularProfiler { |
| /** |
| * @param {?} ref |
| */ |
| constructor(ref) { this.appRef = ref.injector.get(ApplicationRef); } |
| /** |
| * Exercises change detection in a loop and then prints the average amount of |
| * time in milliseconds how long a single round of change detection takes for |
| * the current state of the UI. It runs a minimum of 5 rounds for a minimum |
| * of 500 milliseconds. |
| * |
| * Optionally, a user may pass a `config` parameter containing a map of |
| * options. Supported options are: |
| * |
| * `record` (boolean) - causes the profiler to record a CPU profile while |
| * it exercises the change detector. Example: |
| * |
| * ``` |
| * ng.profiler.timeChangeDetection({record: true}) |
| * ``` |
| * @param {?} config |
| * @return {?} |
| */ |
| timeChangeDetection(config) { |
| const /** @type {?} */ record = config && config['record']; |
| const /** @type {?} */ profileName = 'Change Detection'; |
| // Profiler is not available in Android browsers, nor in IE 9 without dev tools opened |
| const /** @type {?} */ isProfilerAvailable = win.console.profile != null; |
| if (record && isProfilerAvailable) { |
| win.console.profile(profileName); |
| } |
| const /** @type {?} */ start = getDOM().performanceNow(); |
| let /** @type {?} */ numTicks = 0; |
| while (numTicks < 5 || (getDOM().performanceNow() - start) < 500) { |
| this.appRef.tick(); |
| numTicks++; |
| } |
| const /** @type {?} */ end = getDOM().performanceNow(); |
| if (record && isProfilerAvailable) { |
| // need to cast to <any> because type checker thinks there's no argument |
| // while in fact there is: |
| // |
| // https://developer.mozilla.org/en-US/docs/Web/API/Console/profileEnd |
| (/** @type {?} */ (win.console.profileEnd))(profileName); |
| } |
| const /** @type {?} */ msPerTick = (end - start) / numTicks; |
| win.console.log(`ran ${numTicks} change detection cycles`); |
| win.console.log(`${msPerTick.toFixed(2)} ms per check`); |
| return new ChangeDetectionPerfRecord(msPerTick, numTicks); |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| const PROFILER_GLOBAL_NAME = 'profiler'; |
| /** |
| * Enabled Angular debug tools that are accessible via your browser's |
| * developer console. |
| * |
| * Usage: |
| * |
| * 1. Open developer console (e.g. in Chrome Ctrl + Shift + j) |
| * 1. Type `ng.` (usually the console will show auto-complete suggestion) |
| * 1. Try the change detection profiler `ng.profiler.timeChangeDetection()` |
| * then hit Enter. |
| * |
| * \@experimental All debugging apis are currently experimental. |
| * @template T |
| * @param {?} ref |
| * @return {?} |
| */ |
| function enableDebugTools(ref) { |
| exportNgVar(PROFILER_GLOBAL_NAME, new AngularProfiler(ref)); |
| return ref; |
| } |
| /** |
| * Disables Angular tools. |
| * |
| * \@experimental All debugging apis are currently experimental. |
| * @return {?} |
| */ |
| function disableDebugTools() { |
| exportNgVar(PROFILER_GLOBAL_NAME, null); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * @param {?} text |
| * @return {?} |
| */ |
| function escapeHtml(text) { |
| const /** @type {?} */ escapedText = { |
| '&': '&a;', |
| '"': '&q;', |
| '\'': '&s;', |
| '<': '&l;', |
| '>': '&g;', |
| }; |
| return text.replace(/[&"'<>]/g, s => escapedText[s]); |
| } |
| /** |
| * @param {?} text |
| * @return {?} |
| */ |
| function unescapeHtml(text) { |
| const /** @type {?} */ unescapedText = { |
| '&a;': '&', |
| '&q;': '"', |
| '&s;': '\'', |
| '&l;': '<', |
| '&g;': '>', |
| }; |
| return text.replace(/&[^;]+;/g, s => unescapedText[s]); |
| } |
| /** |
| * Create a `StateKey<T>` that can be used to store value of type T with `TransferState`. |
| * |
| * Example: |
| * |
| * ``` |
| * const COUNTER_KEY = makeStateKey<number>('counter'); |
| * let value = 10; |
| * |
| * transferState.set(COUNTER_KEY, value); |
| * ``` |
| * |
| * \@experimental |
| * @template T |
| * @param {?} key |
| * @return {?} |
| */ |
| function makeStateKey(key) { |
| return /** @type {?} */ (key); |
| } |
| /** |
| * A key value store that is transferred from the application on the server side to the application |
| * on the client side. |
| * |
| * `TransferState` will be available as an injectable token. To use it import |
| * `ServerTransferStateModule` on the server and `BrowserTransferStateModule` on the client. |
| * |
| * The values in the store are serialized/deserialized using JSON.stringify/JSON.parse. So only |
| * boolean, number, string, null and non-class objects will be serialized and deserialzied in a |
| * non-lossy manner. |
| * |
| * \@experimental |
| */ |
| class TransferState { |
| constructor() { |
| this.store = {}; |
| this.onSerializeCallbacks = {}; |
| } |
| /** |
| * \@internal |
| * @param {?} initState |
| * @return {?} |
| */ |
| static init(initState) { |
| const /** @type {?} */ transferState = new TransferState(); |
| transferState.store = initState; |
| return transferState; |
| } |
| /** |
| * Get the value corresponding to a key. Return `defaultValue` if key is not found. |
| * @template T |
| * @param {?} key |
| * @param {?} defaultValue |
| * @return {?} |
| */ |
| get(key, defaultValue) { return /** @type {?} */ (this.store[key]) || defaultValue; } |
| /** |
| * Set the value corresponding to a key. |
| * @template T |
| * @param {?} key |
| * @param {?} value |
| * @return {?} |
| */ |
| set(key, value) { this.store[key] = value; } |
| /** |
| * Remove a key from the store. |
| * @template T |
| * @param {?} key |
| * @return {?} |
| */ |
| remove(key) { delete this.store[key]; } |
| /** |
| * Test whether a key exists in the store. |
| * @template T |
| * @param {?} key |
| * @return {?} |
| */ |
| hasKey(key) { return this.store.hasOwnProperty(key); } |
| /** |
| * Register a callback to provide the value for a key when `toJson` is called. |
| * @template T |
| * @param {?} key |
| * @param {?} callback |
| * @return {?} |
| */ |
| onSerialize(key, callback) { |
| this.onSerializeCallbacks[key] = callback; |
| } |
| /** |
| * Serialize the current state of the store to JSON. |
| * @return {?} |
| */ |
| toJson() { |
| // Call the onSerialize callbacks and put those values into the store. |
| for (const /** @type {?} */ key in this.onSerializeCallbacks) { |
| if (this.onSerializeCallbacks.hasOwnProperty(key)) { |
| try { |
| this.store[key] = this.onSerializeCallbacks[key](); |
| } |
| catch (/** @type {?} */ e) { |
| console.warn('Exception in onSerialize callback: ', e); |
| } |
| } |
| } |
| return JSON.stringify(this.store); |
| } |
| } |
| TransferState.decorators = [ |
| { type: Injectable }, |
| ]; |
| /** @nocollapse */ |
| TransferState.ctorParameters = () => []; |
| /** |
| * @param {?} doc |
| * @param {?} appId |
| * @return {?} |
| */ |
| function initTransferState(doc, appId) { |
| // Locate the script tag with the JSON data transferred from the server. |
| // The id of the script tag is set to the Angular appId + 'state'. |
| const /** @type {?} */ script = doc.getElementById(appId + '-state'); |
| let /** @type {?} */ initialState = {}; |
| if (script && script.textContent) { |
| try { |
| initialState = JSON.parse(unescapeHtml(script.textContent)); |
| } |
| catch (/** @type {?} */ e) { |
| console.warn('Exception while restoring TransferState for app ' + appId, e); |
| } |
| } |
| return TransferState.init(initialState); |
| } |
| /** |
| * NgModule to install on the client side while using the `TransferState` to transfer state from |
| * server to client. |
| * |
| * \@experimental |
| */ |
| class BrowserTransferStateModule { |
| } |
| BrowserTransferStateModule.decorators = [ |
| { type: NgModule, args: [{ |
| providers: [{ provide: TransferState, useFactory: initTransferState, deps: [DOCUMENT$1, APP_ID] }], |
| },] }, |
| ]; |
| /** @nocollapse */ |
| BrowserTransferStateModule.ctorParameters = () => []; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * Predicates for use with {\@link DebugElement}'s query functions. |
| * |
| * \@experimental All debugging apis are currently experimental. |
| */ |
| class By { |
| /** |
| * Match all elements. |
| * |
| * ## Example |
| * |
| * {\@example platform-browser/dom/debug/ts/by/by.ts region='by_all'} |
| * @return {?} |
| */ |
| static all() { return (debugElement) => true; } |
| /** |
| * Match elements by the given CSS selector. |
| * |
| * ## Example |
| * |
| * {\@example platform-browser/dom/debug/ts/by/by.ts region='by_css'} |
| * @param {?} selector |
| * @return {?} |
| */ |
| static css(selector) { |
| return (debugElement) => { |
| return debugElement.nativeElement != null ? |
| getDOM().elementMatches(debugElement.nativeElement, selector) : |
| false; |
| }; |
| } |
| /** |
| * Match elements that have the given directive present. |
| * |
| * ## Example |
| * |
| * {\@example platform-browser/dom/debug/ts/by/by.ts region='by_directive'} |
| * @param {?} type |
| * @return {?} |
| */ |
| static directive(type) { |
| return (debugElement) => /** @type {?} */ ((debugElement.providerTokens)).indexOf(type) !== -1; |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * \@stable |
| */ |
| const VERSION = new Version('5.2.0'); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * @module |
| * @description |
| * Entry point for all public APIs of this package. |
| */ |
| |
| // This file only reexports content of the `src` folder. Keep it that way. |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes} checked by tsc |
| */ |
| /** |
| * Generated bundle index. Do not edit. |
| */ |
| |
| export { BrowserModule, platformBrowser, Meta, Title, disableDebugTools, enableDebugTools, BrowserTransferStateModule, TransferState, makeStateKey, By, DOCUMENT$1 as DOCUMENT, EVENT_MANAGER_PLUGINS, EventManager, HAMMER_GESTURE_CONFIG, HammerGestureConfig, DomSanitizer, VERSION, BROWSER_SANITIZATION_PROVIDERS as ɵBROWSER_SANITIZATION_PROVIDERS, INTERNAL_BROWSER_PLATFORM_PROVIDERS as ɵINTERNAL_BROWSER_PLATFORM_PROVIDERS, initDomAdapter as ɵinitDomAdapter, BrowserDomAdapter as ɵBrowserDomAdapter, BrowserPlatformLocation as ɵBrowserPlatformLocation, TRANSITION_ID as ɵTRANSITION_ID, BrowserGetTestability as ɵBrowserGetTestability, escapeHtml as ɵescapeHtml, ELEMENT_PROBE_PROVIDERS as ɵELEMENT_PROBE_PROVIDERS, DomAdapter as ɵDomAdapter, getDOM as ɵgetDOM, setRootDomAdapter as ɵsetRootDomAdapter, DomRendererFactory2 as ɵDomRendererFactory2, NAMESPACE_URIS as ɵNAMESPACE_URIS, flattenStyles as ɵflattenStyles, shimContentAttribute as ɵshimContentAttribute, shimHostAttribute as ɵshimHostAttribute, DomEventsPlugin as ɵDomEventsPlugin, HammerGesturesPlugin as ɵHammerGesturesPlugin, KeyEventsPlugin as ɵKeyEventsPlugin, DomSharedStylesHost as ɵDomSharedStylesHost, SharedStylesHost as ɵSharedStylesHost, _document as ɵb, errorHandler as ɵa, GenericBrowserDomAdapter as ɵi, SERVER_TRANSITION_PROVIDERS as ɵg, appInitializerFactory as ɵf, initTransferState as ɵc, _createNgProbe as ɵh, EventManagerPlugin as ɵd, DomSanitizerImpl as ɵe }; |
| //# sourceMappingURL=platform-browser.js.map |