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
JavaScript
/**
* @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.