UNPKG

md2

Version:

Angular2 based Material Design components, directives and services are Accordion, Autocomplete, Chips(Tags), Collapse, Colorpicker, Data Table, Datepicker, Dialog(Modal), Menu, Multiselect, Select, Tabs, Tags(Chips), Toast and Tooltip.

974 lines (960 loc) 664 kB
/** * @license Md2 v0.0.33 * Copyright (c) 2017 Promact, Inc. http://code.promactinfo.com/md2/ * License: MIT */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/platform-browser'), require('rxjs/Subject'), require('rxjs/add/operator/debounceTime'), require('@angular/common'), require('rxjs/Observable'), require('rxjs/Subscription'), require('rxjs/add/observable/fromEvent'), require('rxjs/add/observable/merge'), require('rxjs/add/operator/auditTime'), require('rxjs/add/operator/first'), require('rxjs/add/observable/of'), require('@angular/animations'), require('@angular/forms'), require('rxjs/add/operator/startWith'), require('rxjs/add/operator/filter')) : typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular/platform-browser', 'rxjs/Subject', 'rxjs/add/operator/debounceTime', '@angular/common', 'rxjs/Observable', 'rxjs/Subscription', 'rxjs/add/observable/fromEvent', 'rxjs/add/observable/merge', 'rxjs/add/operator/auditTime', 'rxjs/add/operator/first', 'rxjs/add/observable/of', '@angular/animations', '@angular/forms', 'rxjs/add/operator/startWith', 'rxjs/add/operator/filter'], factory) : (factory((global.ng = global.ng || {}, global.ng.md2 = global.ng.md2 || {}),global.ng.core,global.ng.platformBrowser,global.Rx,global.Rx.Observable.prototype,global.ng.common,global.Rx,global.Rx,global.Rx.Observable,global.Rx.Observable,global.Rx.Observable.prototype,global.Rx.Observable.prototype,global.Rx.Observable,global.ng.animations,global.ng.forms)); }(this, (function (exports,_angular_core,_angular_platformBrowser,rxjs_Subject,rxjs_add_operator_debounceTime,_angular_common,rxjs_Observable,rxjs_Subscription,rxjs_add_observable_fromEvent,rxjs_add_observable_merge,rxjs_add_operator_auditTime,rxjs_add_operator_first,rxjs_add_observable_of,_angular_animations,_angular_forms) { 'use strict'; var __decorate$3 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata$1 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param$1 = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var MATERIAL_COMPATIBILITY_MODE = new _angular_core.InjectionToken('md-compatibility-mode'); /** * Returns an exception to be thrown if the consumer has used * an invalid Material prefix on a component. * @docs-private */ function getMdCompatibilityInvalidPrefixError(prefix, nodeName) { return Error("The \"" + prefix + "-\" prefix cannot be used in ng-material v1 compatibility mode. " + ("It was used on an \"" + nodeName.toLowerCase() + "\" element.")); } /** Selector that matches all elements that may have style collisions with AngularJS Material. */ var MAT_ELEMENTS_SELECTOR = "\n [mat-button],\n [mat-fab],\n [mat-icon-button],\n [mat-mini-fab],\n [mat-raised-button],\n [matCardSubtitle],\n [matCardTitle],\n [matDialogActions],\n [matDialogClose],\n [matDialogContent],\n [matDialogTitle],\n [matLine],\n [matTabLabel],\n [matTabLink],\n [matTabNav],\n [matTooltip],\n mat-autocomplete,\n mat-button-toggle,\n mat-button-toggle,\n mat-button-toggle-group,\n mat-card,\n mat-card-actions,\n mat-card-content,\n mat-card-footer,\n mat-card-header,\n mat-card-subtitle,\n mat-card-title,\n mat-card-title-group,\n mat-checkbox,\n mat-chip,\n mat-dialog-actions,\n mat-dialog-container,\n mat-dialog-content,\n mat-divider,\n mat-error,\n mat-grid-list,\n mat-grid-tile,\n mat-grid-tile-footer,\n mat-grid-tile-header,\n mat-hint,\n mat-icon,\n mat-list,\n mat-list-item,\n mat-menu,\n mat-nav-list,\n mat-option,\n mat-placeholder,\n mat-progress-bar,\n mat-pseudo-checkbox,\n mat-radio-button,\n mat-radio-group,\n mat-select,\n mat-sidenav,\n mat-sidenav-container,\n mat-slider,\n mat-spinner,\n mat-tab,\n mat-tab-group,\n mat-toolbar"; /** Selector that matches all elements that may have style collisions with AngularJS Material. */ var MD_ELEMENTS_SELECTOR = "\n [md-button],\n [md-fab],\n [md-icon-button],\n [md-mini-fab],\n [md-raised-button],\n [mdCardSubtitle],\n [mdCardTitle],\n [mdDialogActions],\n [mdDialogClose],\n [mdDialogContent],\n [mdDialogTitle],\n [mdLine],\n [mdTabLabel],\n [mdTabLink],\n [mdTabNav],\n [mdTooltip],\n md-autocomplete,\n md-button-toggle,\n md-button-toggle,\n md-button-toggle-group,\n md-card,\n md-card-actions,\n md-card-content,\n md-card-footer,\n md-card-header,\n md-card-subtitle,\n md-card-title,\n md-card-title-group,\n md-checkbox,\n md-chip,\n md-dialog-actions,\n md-dialog-container,\n md-dialog-content,\n md-divider,\n md-error,\n md-grid-list,\n md-grid-tile,\n md-grid-tile-footer,\n md-grid-tile-header,\n md-hint,\n md-icon,\n md-list,\n md-list-item,\n md-menu,\n md-nav-list,\n md-option,\n md-placeholder,\n md-progress-bar,\n md-pseudo-checkbox,\n md-radio-button,\n md-radio-group,\n md-select,\n md-sidenav,\n md-sidenav-container,\n md-slider,\n md-spinner,\n md-tab,\n md-tab-group,\n md-toolbar"; /** Directive that enforces that the `mat-` prefix cannot be used. */ exports.MatPrefixRejector = (function () { function MatPrefixRejector(isCompatibilityMode, elementRef) { if (!isCompatibilityMode) { throw getMdCompatibilityInvalidPrefixError('mat', elementRef.nativeElement.nodeName); } } return MatPrefixRejector; }()); exports.MatPrefixRejector = __decorate$3([ _angular_core.Directive({ selector: MAT_ELEMENTS_SELECTOR }), __param$1(0, _angular_core.Optional()), __param$1(0, _angular_core.Inject(MATERIAL_COMPATIBILITY_MODE)), __metadata$1("design:paramtypes", [Boolean, _angular_core.ElementRef]) ], exports.MatPrefixRejector); /** Directive that enforces that the `md-` prefix cannot be used. */ exports.MdPrefixRejector = (function () { function MdPrefixRejector(isCompatibilityMode, elementRef) { if (isCompatibilityMode) { throw getMdCompatibilityInvalidPrefixError('md', elementRef.nativeElement.nodeName); } } return MdPrefixRejector; }()); exports.MdPrefixRejector = __decorate$3([ _angular_core.Directive({ selector: MD_ELEMENTS_SELECTOR }), __param$1(0, _angular_core.Optional()), __param$1(0, _angular_core.Inject(MATERIAL_COMPATIBILITY_MODE)), __metadata$1("design:paramtypes", [Boolean, _angular_core.ElementRef]) ], exports.MdPrefixRejector); /** * Module that enforces the default compatibility mode settings. When this module is loaded * without NoConflictStyleCompatibilityMode also being imported, it will throw an error if * there are any uses of the `mat-` prefix. */ exports.CompatibilityModule = (function () { function CompatibilityModule() { } return CompatibilityModule; }()); exports.CompatibilityModule = __decorate$3([ _angular_core.NgModule({ declarations: [exports.MatPrefixRejector, exports.MdPrefixRejector], exports: [exports.MatPrefixRejector, exports.MdPrefixRejector], }) ], exports.CompatibilityModule); /** * Module that enforces "no-conflict" compatibility mode settings. When this module is loaded, * it will throw an error if there are any uses of the `md-` prefix. */ exports.NoConflictStyleCompatibilityMode = (function () { function NoConflictStyleCompatibilityMode() { } return NoConflictStyleCompatibilityMode; }()); exports.NoConflictStyleCompatibilityMode = __decorate$3([ _angular_core.NgModule({ providers: [{ provide: MATERIAL_COMPATIBILITY_MODE, useValue: true, }], }) ], exports.NoConflictStyleCompatibilityMode); var __decorate$2 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; /** Injection token that configures whether the Material sanity checks are enabled. */ var MATERIAL_SANITY_CHECKS = new _angular_core.InjectionToken('md-sanity-checks'); /** * Module that captures anything that should be loaded and/or run for *all* Angular Material * components. This includes Bidi, compatibility mode, etc. * * This module should be imported to each top-level component module (e.g., MdTabsModule). */ exports.MdCommonModule = (function () { function MdCommonModule(_document, _sanityChecksEnabled) { this._document = _document; /** Whether we've done the global sanity checks (e.g. a theme is loaded, there is a doctype). */ this._hasDoneGlobalChecks = false; if (_sanityChecksEnabled && !this._hasDoneGlobalChecks && _document && _angular_core.isDevMode()) { this._checkDoctype(); this._checkTheme(); this._hasDoneGlobalChecks = true; } } MdCommonModule.prototype._checkDoctype = function () { if (!this._document.doctype) { console.warn('Current document does not have a doctype. This may cause ' + 'some Angular Material components not to behave as expected.'); } }; MdCommonModule.prototype._checkTheme = function () { if (typeof getComputedStyle === 'function') { var testElement = this._document.createElement('div'); testElement.classList.add('mat-theme-loaded-marker'); this._document.body.appendChild(testElement); if (getComputedStyle(testElement).display !== 'none') { console.warn('Could not find Angular Material core theme. Most Material ' + 'components may not work as expected. For more info refer ' + 'to the theming guide: https://material.angular.io/guide/theming'); } this._document.body.removeChild(testElement); } }; return MdCommonModule; }()); exports.MdCommonModule = __decorate$2([ _angular_core.NgModule({ imports: [exports.CompatibilityModule], exports: [exports.CompatibilityModule], providers: [{ provide: MATERIAL_SANITY_CHECKS, useValue: true, }], }), __param(0, _angular_core.Optional()), __param(0, _angular_core.Inject(_angular_platformBrowser.DOCUMENT)), __param(1, _angular_core.Optional()), __param(1, _angular_core.Inject(MATERIAL_SANITY_CHECKS)), __metadata("design:paramtypes", [Object, Boolean]) ], exports.MdCommonModule); var __decorate$1 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * Shared directive to count lines inside a text area, such as a list item. * Line elements can be extracted with a @ContentChildren(MdLine) query, then * counted by checking the query list's length. */ exports.MdLine = (function () { function MdLine() { } return MdLine; }()); exports.MdLine = __decorate$1([ _angular_core.Directive({ selector: '[md-line], [mat-line], [mdLine], [matLine]', host: { 'class': 'mat-line' } }) ], exports.MdLine); /** * Helper that takes a query list of lines and sets the correct class on the host. * @docs-private */ var MdLineSetter = (function () { function MdLineSetter(_lines, _renderer, _element) { var _this = this; this._lines = _lines; this._renderer = _renderer; this._element = _element; this._setLineClass(this._lines.length); this._lines.changes.subscribe(function () { _this._setLineClass(_this._lines.length); }); } MdLineSetter.prototype._setLineClass = function (count) { this._resetClasses(); if (count === 2 || count === 3) { this._setClass("mat-" + count + "-line", true); } else if (count > 3) { this._setClass("mat-multi-line", true); } }; MdLineSetter.prototype._resetClasses = function () { this._setClass('mat-2-line', false); this._setClass('mat-3-line', false); this._setClass('mat-multi-line', false); }; MdLineSetter.prototype._setClass = function (className, isAdd) { if (isAdd) { this._renderer.addClass(this._element.nativeElement, className); } else { this._renderer.removeClass(this._element.nativeElement, className); } }; return MdLineSetter; }()); exports.MdLineModule = (function () { function MdLineModule() { } return MdLineModule; }()); exports.MdLineModule = __decorate$1([ _angular_core.NgModule({ imports: [exports.MdCommonModule], exports: [exports.MdLine, exports.MdCommonModule], declarations: [exports.MdLine], }) ], exports.MdLineModule); var __decorate$4 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata$2 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** * Directive to listen for changes of direction of part of the DOM. * * Applications should use this directive instead of the native attribute so that Material * components can listen on changes of direction. */ exports.Dir = (function () { function Dir() { /** Layout direction of the element. */ this._dir = 'ltr'; /** Event emitted when the direction changes. */ this.dirChange = new _angular_core.EventEmitter(); } Object.defineProperty(Dir.prototype, "dir", { /** @docs-private */ get: function () { return this._dir; }, set: function (v) { var old = this._dir; this._dir = v; if (old != this._dir) { this.dirChange.emit(); } }, enumerable: true, configurable: true }); Object.defineProperty(Dir.prototype, "value", { /** Current layout direction of the element. */ get: function () { return this.dir; }, set: function (v) { this.dir = v; }, enumerable: true, configurable: true }); return Dir; }()); __decorate$4([ _angular_core.Input('dir'), __metadata$2("design:type", String) ], exports.Dir.prototype, "_dir", void 0); __decorate$4([ _angular_core.Output(), __metadata$2("design:type", Object) ], exports.Dir.prototype, "dirChange", void 0); __decorate$4([ _angular_core.HostBinding('attr.dir'), __metadata$2("design:type", String), __metadata$2("design:paramtypes", [String]) ], exports.Dir.prototype, "dir", null); exports.Dir = __decorate$4([ _angular_core.Directive({ selector: '[dir]', // TODO(hansl): maybe `$implicit` isn't the best option here, but for now that's the best we got. exportAs: '$implicit' }) ], exports.Dir); exports.RtlModule = (function () { function RtlModule() { } return RtlModule; }()); exports.RtlModule = __decorate$4([ _angular_core.NgModule({ exports: [exports.Dir], declarations: [exports.Dir] }) ], exports.RtlModule); var __decorate$5 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata$3 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** * Factory that creates a new MutationObserver and allows us to stub it out in unit tests. * @docs-private */ var MdMutationObserverFactory = (function () { function MdMutationObserverFactory() { } MdMutationObserverFactory.prototype.create = function (callback) { return typeof MutationObserver === 'undefined' ? null : new MutationObserver(callback); }; return MdMutationObserverFactory; }()); MdMutationObserverFactory = __decorate$5([ _angular_core.Injectable() ], MdMutationObserverFactory); /** * Directive that triggers a callback whenever the content of * its associated element has changed. */ exports.ObserveContent = (function () { function ObserveContent(_mutationObserverFactory, _elementRef) { this._mutationObserverFactory = _mutationObserverFactory; this._elementRef = _elementRef; /** Event emitted for each change in the element's content. */ this.event = new _angular_core.EventEmitter(); /** Used for debouncing the emitted values to the observeContent event. */ this._debouncer = new rxjs_Subject.Subject(); } ObserveContent.prototype.ngAfterContentInit = function () { var _this = this; if (this.debounce > 0) { this._debouncer .debounceTime(this.debounce) .subscribe(function (mutations) { return _this.event.emit(mutations); }); } else { this._debouncer.subscribe(function (mutations) { return _this.event.emit(mutations); }); } this._observer = this._mutationObserverFactory.create(function (mutations) { _this._debouncer.next(mutations); }); if (this._observer) { this._observer.observe(this._elementRef.nativeElement, { characterData: true, childList: true, subtree: true }); } }; ObserveContent.prototype.ngOnDestroy = function () { if (this._observer) { this._observer.disconnect(); this._debouncer.complete(); this._debouncer = this._observer = null; } }; return ObserveContent; }()); __decorate$5([ _angular_core.Output('cdkObserveContent'), __metadata$3("design:type", Object) ], exports.ObserveContent.prototype, "event", void 0); __decorate$5([ _angular_core.Input(), __metadata$3("design:type", Number) ], exports.ObserveContent.prototype, "debounce", void 0); exports.ObserveContent = __decorate$5([ _angular_core.Directive({ selector: '[cdkObserveContent]' }), __metadata$3("design:paramtypes", [MdMutationObserverFactory, _angular_core.ElementRef]) ], exports.ObserveContent); exports.ObserveContentModule = (function () { function ObserveContentModule() { } return ObserveContentModule; }()); exports.ObserveContentModule = __decorate$5([ _angular_core.NgModule({ exports: [exports.ObserveContent], declarations: [exports.ObserveContent], providers: [MdMutationObserverFactory] }) ], exports.ObserveContentModule); /** Possible states for a ripple element. */ (function (RippleState) { RippleState[RippleState["FADING_IN"] = 0] = "FADING_IN"; RippleState[RippleState["VISIBLE"] = 1] = "VISIBLE"; RippleState[RippleState["FADING_OUT"] = 2] = "FADING_OUT"; RippleState[RippleState["HIDDEN"] = 3] = "HIDDEN"; })(exports.RippleState || (exports.RippleState = {})); /** * Reference to a previously launched ripple element. */ var RippleRef = (function () { function RippleRef(_renderer, element, config) { this._renderer = _renderer; this.element = element; this.config = config; /** Current state of the ripple reference. */ this.state = exports.RippleState.HIDDEN; } /** Fades out the ripple element. */ RippleRef.prototype.fadeOut = function () { this._renderer.fadeOutRipple(this); }; return RippleRef; }()); /** Fade-in duration for the ripples. Can be modified with the speedFactor option. */ var RIPPLE_FADE_IN_DURATION = 450; /** Fade-out duration for the ripples in milliseconds. This can't be modified by the speedFactor. */ var RIPPLE_FADE_OUT_DURATION = 400; /** * Helper service that performs DOM manipulations. Not intended to be used outside this module. * The constructor takes a reference to the ripple directive's host element and a map of DOM * event handlers to be installed on the element that triggers ripple animations. * This will eventually become a custom renderer once Angular support exists. * @docs-private */ var RippleRenderer = (function () { function RippleRenderer(elementRef, _ngZone, _ruler, platform) { this._ngZone = _ngZone; this._ruler = _ruler; /** Whether the mouse is currently down or not. */ this._isMousedown = false; /** Events to be registered on the trigger element. */ this._triggerEvents = new Map(); /** Set of currently active ripple references. */ this._activeRipples = new Set(); /** Ripple config for all ripples created by events. */ this.rippleConfig = {}; /** Whether mouse ripples should be created or not. */ this.rippleDisabled = false; // Only do anything if we're on the browser. if (platform.isBrowser) { this._containerElement = elementRef.nativeElement; // Specify events which need to be registered on the trigger. this._triggerEvents.set('mousedown', this.onMousedown.bind(this)); this._triggerEvents.set('mouseup', this.onMouseup.bind(this)); this._triggerEvents.set('mouseleave', this.onMouseLeave.bind(this)); // By default use the host element as trigger element. this.setTriggerElement(this._containerElement); } } /** Fades in a ripple at the given coordinates. */ RippleRenderer.prototype.fadeInRipple = function (pageX, pageY, config) { var _this = this; if (config === void 0) { config = {}; } var containerRect = this._containerElement.getBoundingClientRect(); if (config.centered) { pageX = containerRect.left + containerRect.width / 2; pageY = containerRect.top + containerRect.height / 2; } else { // Subtract scroll values from the coordinates because calculations below // are always relative to the viewport rectangle. var scrollPosition = this._ruler.getViewportScrollPosition(); pageX -= scrollPosition.left; pageY -= scrollPosition.top; } var radius = config.radius || distanceToFurthestCorner(pageX, pageY, containerRect); var duration = RIPPLE_FADE_IN_DURATION * (1 / (config.speedFactor || 1)); var offsetX = pageX - containerRect.left; var offsetY = pageY - containerRect.top; var ripple = document.createElement('div'); ripple.classList.add('mat-ripple-element'); ripple.style.left = offsetX - radius + "px"; ripple.style.top = offsetY - radius + "px"; ripple.style.height = radius * 2 + "px"; ripple.style.width = radius * 2 + "px"; // If the color is not set, the default CSS color will be used. ripple.style.backgroundColor = config.color; ripple.style.transitionDuration = duration + "ms"; this._containerElement.appendChild(ripple); // By default the browser does not recalculate the styles of dynamically created // ripple elements. This is critical because then the `scale` would not animate properly. enforceStyleRecalculation(ripple); ripple.style.transform = 'scale(1)'; // Exposed reference to the ripple that will be returned. var rippleRef = new RippleRef(this, ripple, config); rippleRef.state = exports.RippleState.FADING_IN; // Add the ripple reference to the list of all active ripples. this._activeRipples.add(rippleRef); // Wait for the ripple element to be completely faded in. // Once it's faded in, the ripple can be hidden immediately if the mouse is released. this.runTimeoutOutsideZone(function () { rippleRef.state = exports.RippleState.VISIBLE; if (!config.persistent && !_this._isMousedown) { rippleRef.fadeOut(); } }, duration); return rippleRef; }; /** Fades out a ripple reference. */ RippleRenderer.prototype.fadeOutRipple = function (rippleRef) { // For ripples that are not active anymore, don't re-un the fade-out animation. if (!this._activeRipples.delete(rippleRef)) { return; } var rippleEl = rippleRef.element; rippleEl.style.transitionDuration = RIPPLE_FADE_OUT_DURATION + "ms"; rippleEl.style.opacity = '0'; rippleRef.state = exports.RippleState.FADING_OUT; // Once the ripple faded out, the ripple can be safely removed from the DOM. this.runTimeoutOutsideZone(function () { rippleRef.state = exports.RippleState.HIDDEN; rippleEl.parentNode.removeChild(rippleEl); }, RIPPLE_FADE_OUT_DURATION); }; /** Fades out all currently active ripples. */ RippleRenderer.prototype.fadeOutAll = function () { this._activeRipples.forEach(function (ripple) { return ripple.fadeOut(); }); }; /** Sets the trigger element and registers the mouse events. */ RippleRenderer.prototype.setTriggerElement = function (element) { var _this = this; // Remove all previously register event listeners from the trigger element. if (this._triggerElement) { this._triggerEvents.forEach(function (fn, type) { return _this._triggerElement.removeEventListener(type, fn); }); } if (element) { // If the element is not null, register all event listeners on the trigger element. this._ngZone.runOutsideAngular(function () { _this._triggerEvents.forEach(function (fn, type) { return element.addEventListener(type, fn); }); }); } this._triggerElement = element; }; /** Listener being called on mousedown event. */ RippleRenderer.prototype.onMousedown = function (event) { if (!this.rippleDisabled) { this._isMousedown = true; this.fadeInRipple(event.pageX, event.pageY, this.rippleConfig); } }; /** Listener being called on mouseup event. */ RippleRenderer.prototype.onMouseup = function () { this._isMousedown = false; // Fade-out all ripples that are completely visible and not persistent. this._activeRipples.forEach(function (ripple) { if (!ripple.config.persistent && ripple.state === exports.RippleState.VISIBLE) { ripple.fadeOut(); } }); }; /** Listener being called on mouseleave event. */ RippleRenderer.prototype.onMouseLeave = function () { if (this._isMousedown) { this.onMouseup(); } }; /** Runs a timeout outside of the Angular zone to avoid triggering the change detection. */ RippleRenderer.prototype.runTimeoutOutsideZone = function (fn, delay) { if (delay === void 0) { delay = 0; } this._ngZone.runOutsideAngular(function () { return setTimeout(fn, delay); }); }; return RippleRenderer; }()); /** Enforces a style recalculation of a DOM element by computing its styles. */ // TODO(devversion): Move into global utility function. function enforceStyleRecalculation(element) { // Enforce a style recalculation by calling `getComputedStyle` and accessing any property. // Calling `getPropertyValue` is important to let optimizers know that this is not a noop. // See: https://gist.github.com/paulirish/5d52fb081b3570c81e3a window.getComputedStyle(element).getPropertyValue('opacity'); } /** * Returns the distance from the point (x, y) to the furthest corner of a rectangle. */ function distanceToFurthestCorner(x, y, rect) { var distX = Math.max(Math.abs(x - rect.left), Math.abs(x - rect.right)); var distY = Math.max(Math.abs(y - rect.top), Math.abs(y - rect.bottom)); return Math.sqrt(distX * distX + distY * distY); } var __decorate$12 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; // Whether the current platform supports the V8 Break Iterator. The V8 check // is necessary to detect all Blink based browsers. var hasV8BreakIterator = (typeof (Intl) !== 'undefined' && Intl.v8BreakIterator); /** * Service to detect the current platform by comparing the userAgent strings and * checking browser-specific global properties. * @docs-private */ exports.Platform = (function () { function Platform() { this.isBrowser = typeof document === 'object' && !!document; /** Layout Engines */ this.EDGE = this.isBrowser && /(edge)/i.test(navigator.userAgent); this.TRIDENT = this.isBrowser && /(msie|trident)/i.test(navigator.userAgent); // EdgeHTML and Trident mock Blink specific things and need to be excluded from this check. this.BLINK = this.isBrowser && (!!(window.chrome || hasV8BreakIterator) && !!CSS && !this.EDGE && !this.TRIDENT); // Webkit is part of the userAgent in EdgeHTML, Blink and Trident. Therefore we need to // ensure that Webkit runs standalone and is not used as another engine's base. this.WEBKIT = this.isBrowser && /AppleWebKit/i.test(navigator.userAgent) && !this.BLINK && !this.EDGE && !this.TRIDENT; /** Browsers and Platform Types */ this.IOS = this.isBrowser && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; // It's difficult to detect the plain Gecko engine, because most of the browsers identify // them self as Gecko-like browsers and modify the userAgent's according to that. // Since we only cover one explicit Firefox case, we can simply check for Firefox // instead of having an unstable check for Gecko. this.FIREFOX = this.isBrowser && /(firefox|minefield)/i.test(navigator.userAgent); // Trident on mobile adds the android platform to the userAgent to trick detections. this.ANDROID = this.isBrowser && /android/i.test(navigator.userAgent) && !this.TRIDENT; // Safari browsers will include the Safari keyword in their userAgent. Some browsers may fake // this and just place the Safari keyword in the userAgent. To be more safe about Safari every // Safari browser should also use Webkit as its layout engine. this.SAFARI = this.isBrowser && /safari/i.test(navigator.userAgent) && this.WEBKIT; } return Platform; }()); exports.Platform = __decorate$12([ _angular_core.Injectable() ], exports.Platform); /** Cached result Set of input types support by the current browser. */ var supportedInputTypes; /** Types of <input> that *might* be supported. */ var candidateInputTypes = [ // `color` must come first. Chrome 56 shows a warning if we change the type to `color` after // first changing it to something else: // The specified value "" does not conform to the required format. // The format is "#rrggbb" where rr, gg, bb are two-digit hexadecimal numbers. 'color', 'button', 'checkbox', 'date', 'datetime-local', 'email', 'file', 'hidden', 'image', 'month', 'number', 'password', 'radio', 'range', 'reset', 'search', 'submit', 'tel', 'text', 'time', 'url', 'week', ]; /** @returns The input types supported by this browser. */ function getSupportedInputTypes() { // Result is cached. if (supportedInputTypes) { return supportedInputTypes; } // We can't check if an input type is not supported until we're on the browser, so say that // everything is supported when not on the browser. We don't use `Platform` here since it's // just a helper function and can't inject it. if (typeof document !== 'object' || !document) { supportedInputTypes = new Set(candidateInputTypes); return supportedInputTypes; } var featureTestInput = document.createElement('input'); supportedInputTypes = new Set(candidateInputTypes.filter(function (value) { featureTestInput.setAttribute('type', value); return featureTestInput.type === value; })); return supportedInputTypes; } var __decorate$11 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; exports.PlatformModule = (function () { function PlatformModule() { } return PlatformModule; }()); exports.PlatformModule = __decorate$11([ _angular_core.NgModule({ providers: [exports.Platform] }) ], exports.PlatformModule); var __decorate$10 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata$6 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** Time in ms to throttle the scrolling events by default. */ var DEFAULT_SCROLL_TIME = 20; /** * Service contained all registered Scrollable references and emits an event when any one of the * Scrollable references emit a scrolled event. */ exports.ScrollDispatcher = (function () { function ScrollDispatcher(_ngZone, _platform) { this._ngZone = _ngZone; this._platform = _platform; /** Subject for notifying that a registered scrollable reference element has been scrolled. */ this._scrolled = new rxjs_Subject.Subject(); /** Keeps track of the global `scroll` and `resize` subscriptions. */ this._globalSubscription = null; /** Keeps track of the amount of subscriptions to `scrolled`. Used for cleaning up afterwards. */ this._scrolledCount = 0; /** * Map of all the scrollable references that are registered with the service and their * scroll event subscriptions. */ this.scrollableReferences = new Map(); } /** * Registers a Scrollable with the service and listens for its scrolled events. When the * scrollable is scrolled, the service emits the event in its scrolled observable. * @param scrollable Scrollable instance to be registered. */ ScrollDispatcher.prototype.register = function (scrollable) { var _this = this; var scrollSubscription = scrollable.elementScrolled().subscribe(function () { return _this._notify(); }); this.scrollableReferences.set(scrollable, scrollSubscription); }; /** * Deregisters a Scrollable reference and unsubscribes from its scroll event observable. * @param scrollable Scrollable instance to be deregistered. */ ScrollDispatcher.prototype.deregister = function (scrollable) { if (this.scrollableReferences.has(scrollable)) { this.scrollableReferences.get(scrollable).unsubscribe(); this.scrollableReferences.delete(scrollable); } }; /** * Subscribes to an observable that emits an event whenever any of the registered Scrollable * references (or window, document, or body) fire a scrolled event. Can provide a time in ms * to override the default "throttle" time. */ ScrollDispatcher.prototype.scrolled = function (auditTimeInMs, callback) { var _this = this; if (auditTimeInMs === void 0) { auditTimeInMs = DEFAULT_SCROLL_TIME; } // Scroll events can only happen on the browser, so do nothing if we're not on the browser. if (!this._platform.isBrowser) { return rxjs_Subscription.Subscription.EMPTY; } // In the case of a 0ms delay, use an observable without auditTime // since it does add a perceptible delay in processing overhead. var observable = auditTimeInMs > 0 ? this._scrolled.asObservable().auditTime(auditTimeInMs) : this._scrolled.asObservable(); this._scrolledCount++; if (!this._globalSubscription) { this._globalSubscription = this._ngZone.runOutsideAngular(function () { return rxjs_Observable.Observable.merge(rxjs_Observable.Observable.fromEvent(window.document, 'scroll'), rxjs_Observable.Observable.fromEvent(window, 'resize')).subscribe(function () { return _this._notify(); }); }); } // Note that we need to do the subscribing from here, in order to be able to remove // the global event listeners once there are no more subscriptions. var subscription = observable.subscribe(callback); subscription.add(function () { _this._scrolledCount--; if (_this._globalSubscription && !_this.scrollableReferences.size && !_this._scrolledCount) { _this._globalSubscription.unsubscribe(); _this._globalSubscription = null; } }); return subscription; }; /** Returns all registered Scrollables that contain the provided element. */ ScrollDispatcher.prototype.getScrollContainers = function (elementRef) { var _this = this; var scrollingContainers = []; this.scrollableReferences.forEach(function (_subscription, scrollable) { if (_this.scrollableContainsElement(scrollable, elementRef)) { scrollingContainers.push(scrollable); } }); return scrollingContainers; }; /** Returns true if the element is contained within the provided Scrollable. */ ScrollDispatcher.prototype.scrollableContainsElement = function (scrollable, elementRef) { var element = elementRef.nativeElement; var scrollableElement = scrollable.getElementRef().nativeElement; // Traverse through the element parents until we reach null, checking if any of the elements // are the scrollable's element. do { if (element == scrollableElement) { return true; } } while (element = element.parentElement); }; /** Sends a notification that a scroll event has been fired. */ ScrollDispatcher.prototype._notify = function () { this._scrolled.next(); }; return ScrollDispatcher; }()); exports.ScrollDispatcher = __decorate$10([ _angular_core.Injectable(), __metadata$6("design:paramtypes", [_angular_core.NgZone, exports.Platform]) ], exports.ScrollDispatcher); function SCROLL_DISPATCHER_PROVIDER_FACTORY(parentDispatcher, ngZone, platform) { return parentDispatcher || new exports.ScrollDispatcher(ngZone, platform); } var SCROLL_DISPATCHER_PROVIDER = { // If there is already a ScrollDispatcher available, use that. Otherwise, provide a new one. provide: exports.ScrollDispatcher, deps: [[new _angular_core.Optional(), new _angular_core.SkipSelf(), exports.ScrollDispatcher], _angular_core.NgZone, exports.Platform], useFactory: SCROLL_DISPATCHER_PROVIDER_FACTORY }; var __decorate$9 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata$5 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; /** * Simple utility for getting the bounds of the browser viewport. * @docs-private */ exports.ViewportRuler = (function () { function ViewportRuler(scrollDispatcher) { var _this = this; // Subscribe to scroll and resize events and update the document rectangle on changes. scrollDispatcher.scrolled(null, function () { return _this._cacheViewportGeometry(); }); } /** Gets a ClientRect for the viewport's bounds. */ ViewportRuler.prototype.getViewportRect = function (documentRect) { if (documentRect === void 0) { documentRect = this._documentRect; } // Cache the document bounding rect so that we don't recompute it for multiple calls. if (!documentRect) { this._cacheViewportGeometry(); documentRect = this._documentRect; } // Use the document element's bounding rect rather than the window scroll properties // (e.g. pageYOffset, scrollY) due to in issue in Chrome and IE where window scroll // properties and client coordinates (boundingClientRect, clientX/Y, etc.) are in different // conceptual viewports. Under most circumstances these viewports are equivalent, but they // can disagree when the page is pinch-zoomed (on devices that support touch). // See https://bugs.chromium.org/p/chromium/issues/detail?id=489206#c4 // We use the documentElement instead of the body because, by default (without a css reset) // browsers typically give the document body an 8px margin, which is not included in // getBoundingClientRect(). var scrollPosition = this.getViewportScrollPosition(documentRect); var height = window.innerHeight; var width = window.innerWidth; return { top: scrollPosition.top, left: scrollPosition.left, bottom: scrollPosition.top + height, right: scrollPosition.left + width, height: height, width: width, }; }; /** * Gets the (top, left) scroll position of the viewport. * @param documentRect */ ViewportRuler.prototype.getViewportScrollPosition = function (documentRect) { if (documentRect === void 0) { documentRect = this._documentRect; } // Cache the document bounding rect so that we don't recompute it for multiple calls. if (!documentRect) { this._cacheViewportGeometry(); documentRect = this._documentRect; } // The top-left-corner of the viewport is determined by the scroll position of the document // body, normally just (scrollLeft, scrollTop). However, Chrome and Firefox disagree about // whether `document.body` or `document.documentElement` is the scrolled element, so reading // `scrollTop` and `scrollLeft` is inconsistent. However, using the bounding rect of // `document.documentElement` works consistently, where the `top` and `left` values will // equal negative the scroll position. var top = -documentRect.top || document.body.scrollTop || window.scrollY || document.documentElement.scrollTop || 0; var left = -documentRect.left || document.body.scrollLeft || window.scrollX || document.documentElement.scrollLeft || 0; return { top: top, left: left }; }; /** Caches the latest client rectangle of the document element. */ ViewportRuler.prototype._cacheViewportGeometry = function () { this._documentRect = document.documentElement.getBoundingClientRect(); }; return ViewportRuler; }()); exports.ViewportRuler = __decorate$9([ _angular_core.Injectable(), __metadata$5("design:paramtypes", [exports.ScrollDispatcher]) ], exports.ViewportRuler); function VIEWPORT_RULER_PROVIDER_FACTORY(parentRuler, scrollDispatcher) { return parentRuler || new exports.ViewportRuler(scrollDispatcher); } var VIEWPORT_RULER_PROVIDER = { // If there is already a ViewportRuler available, use that. Otherwise, provide a new one. provide: exports.ViewportRuler, deps: [[new _angular_core.Optional(), new _angular_core.SkipSelf(), exports.ViewportRuler], exports.ScrollDispatcher], useFactory: VIEWPORT_RULER_PROVIDER_FACTORY }; var __decorate$8 = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata$4 = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param$2 = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; /** Injection token that can be used to specify the global ripple options. */ var MD_RIPPLE_GLOBAL_OPTIONS = new _angular_core.InjectionToken('md-ripple-global-options'); exports.MdRipple = (function () { function MdRipple(elementRef, ngZone, ruler, platform, globalOptions) { /** * If set, the radius in pixels of foreground ripples when fully expanded. If unset, the radius * will be the distance from the center of the ripple to the furthest corner of the host element's * bounding rectangle. */ this.radius = 0; /** * If set, the normal duration of ripple animations is divided by this value. For example, * setting it to 0.5 will cause the animations to take twice as long. * A changed speedFactor will not modify the fade-out duration of the ripples. */ this.speedFactor = 1; this._rippleRenderer = new RippleRenderer(elementRef, ngZone, ruler, platform); this._globalOptions = globalOptions ? globalOptions : {}; this._updateRippleRenderer(); } MdRipple.prototype.ngOnChanges = function (changes) { if (changes['trigger'] && this.trigger) { this._rippleRenderer.