@angular2-material/core
Version:
Angular 2 Material core
1,828 lines • 80.2 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular2-material/core'), require('@angular/platform-browser')) :
typeof define === 'function' && define.amd ? define(['exports', '@angular/core', '@angular2-material/core', '@angular/platform-browser'], factory) :
(factory((global.md = global.md || {}, global.md.core = global.md.core || {}),global.ng.core,global.md.core,global.ng.platformBrowser));
}(this, (function (exports,_angular_core,_angular2Material_core,_angular_platformBrowser) { 'use strict';
var __decorate$1 = (window && window.__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 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/**
* 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.
*/
var MdLine = (function () {
function MdLine() {
}
MdLine = __decorate$1([
_angular_core.Directive({ selector: '[md-line]' }),
__metadata$1('design:paramtypes', [])
], MdLine);
return MdLine;
}());
/* Helper that takes a query list of lines and sets the correct class on the host */
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("md-" + count + "-line", true);
}
};
MdLineSetter.prototype._resetClasses = function () {
this._setClass('md-2-line', false);
this._setClass('md-3-line', false);
};
MdLineSetter.prototype._setClass = function (className, bool) {
this._renderer.setElementClass(this._element.nativeElement, className, bool);
};
return MdLineSetter;
}());
var MdLineModule = (function () {
function MdLineModule() {
}
MdLineModule = __decorate$1([
_angular_core.NgModule({
exports: [MdLine],
declarations: [MdLine],
}),
__metadata$1('design:paramtypes', [])
], MdLineModule);
return MdLineModule;
}());
var __decorate$2 = (window && window.__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 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/**
* Directive to listen to 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.
*/
var Dir = (function () {
function Dir() {
this._dir = 'ltr';
this.dirChange = new _angular_core.EventEmitter();
}
Object.defineProperty(Dir.prototype, "dir", {
get: function () {
return this._dir;
},
set: function (v) {
var old = this._dir;
this._dir = v;
if (old != this._dir) {
this.dirChange.emit(null);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dir.prototype, "value", {
get: function () { return this.dir; },
set: function (v) { this.dir = v; },
enumerable: true,
configurable: true
});
__decorate$2([
_angular_core.Input('dir'),
__metadata$2('design:type', String)
], Dir.prototype, "_dir", void 0);
__decorate$2([
_angular_core.Output(),
__metadata$2('design:type', Object)
], Dir.prototype, "dirChange", void 0);
__decorate$2([
_angular_core.HostBinding('attr.dir'),
__metadata$2('design:type', String)
], Dir.prototype, "dir", null);
Dir = __decorate$2([
_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'
}),
__metadata$2('design:paramtypes', [])
], Dir);
return Dir;
}());
var RtlModule = (function () {
function RtlModule() {
}
RtlModule.forRoot = function () {
return {
ngModule: RtlModule,
providers: []
};
};
RtlModule = __decorate$2([
_angular_core.NgModule({
exports: [Dir],
declarations: [Dir]
}),
__metadata$2('design:paramtypes', [])
], RtlModule);
return RtlModule;
}());
/** TODO: internal */
var ForegroundRippleState;
(function (ForegroundRippleState) {
ForegroundRippleState[ForegroundRippleState["NEW"] = 0] = "NEW";
ForegroundRippleState[ForegroundRippleState["EXPANDING"] = 1] = "EXPANDING";
ForegroundRippleState[ForegroundRippleState["FADING_OUT"] = 2] = "FADING_OUT";
})(ForegroundRippleState || (ForegroundRippleState = {}));
/**
* Wrapper for a foreground ripple DOM element and its animation state.
* TODO: internal
*/
var ForegroundRipple = (function () {
function ForegroundRipple(rippleElement) {
this.rippleElement = rippleElement;
this.state = ForegroundRippleState.NEW;
}
return ForegroundRipple;
}());
var RIPPLE_SPEED_PX_PER_SECOND = 1000;
var MIN_RIPPLE_FILL_TIME_SECONDS = 0.1;
var MAX_RIPPLE_FILL_TIME_SECONDS = 0.3;
/**
* Returns the distance from the point (x, y) to the furthest corner of a rectangle.
*/
var distanceToFurthestCorner = function (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);
};
/**
* 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.
* TODO: internal
*/
var RippleRenderer = (function () {
function RippleRenderer(_elementRef, _eventHandlers) {
this._eventHandlers = _eventHandlers;
this._rippleElement = _elementRef.nativeElement;
// It might be nice to delay creating the background until it's needed, but doing this in
// fadeInRippleBackground causes the first click event to not be handled reliably.
this._backgroundDiv = document.createElement('div');
this._backgroundDiv.classList.add('md-ripple-background');
this._rippleElement.appendChild(this._backgroundDiv);
}
/**
* Installs event handlers on the given trigger element, and removes event handlers from the
* previous trigger if needed.
*/
RippleRenderer.prototype.setTriggerElement = function (newTrigger) {
var _this = this;
if (this._triggerElement !== newTrigger) {
if (this._triggerElement) {
this._eventHandlers.forEach(function (eventHandler, eventName) {
_this._triggerElement.removeEventListener(eventName, eventHandler);
});
}
this._triggerElement = newTrigger;
if (this._triggerElement) {
this._eventHandlers.forEach(function (eventHandler, eventName) {
_this._triggerElement.addEventListener(eventName, eventHandler);
});
}
}
};
/**
* Installs event handlers on the host element of the md-ripple directive.
*/
RippleRenderer.prototype.setTriggerElementToHost = function () {
this.setTriggerElement(this._rippleElement);
};
/**
* Removes event handlers from the current trigger element if needed.
*/
RippleRenderer.prototype.clearTriggerElement = function () {
this.setTriggerElement(null);
};
/**
* Creates a foreground ripple and sets its animation to expand and fade in from the position
* given by rippleOriginLeft and rippleOriginTop (or from the center of the <md-ripple>
* bounding rect if centered is true).
*/
RippleRenderer.prototype.createForegroundRipple = function (rippleOriginLeft, rippleOriginTop, color, centered, radius, speedFactor, transitionEndCallback) {
var parentRect = this._rippleElement.getBoundingClientRect();
// Create a foreground ripple div with the size and position of the fully expanded ripple.
// When the div is created, it's given a transform style that causes the ripple to be displayed
// small and centered on the event location (or the center of the bounding rect if the centered
// argument is true). Removing that transform causes the ripple to animate to its natural size.
var startX = centered ? (parentRect.left + parentRect.width / 2) : rippleOriginLeft;
var startY = centered ? (parentRect.top + parentRect.height / 2) : rippleOriginTop;
var offsetX = startX - parentRect.left;
var offsetY = startY - parentRect.top;
var maxRadius = radius > 0 ? radius : distanceToFurthestCorner(startX, startY, parentRect);
var rippleDiv = document.createElement('div');
this._rippleElement.appendChild(rippleDiv);
rippleDiv.classList.add('md-ripple-foreground');
rippleDiv.style.left = (offsetX - maxRadius) + "px";
rippleDiv.style.top = (offsetY - maxRadius) + "px";
rippleDiv.style.width = 2 * maxRadius + "px";
rippleDiv.style.height = rippleDiv.style.width;
// If color input is not set, this will default to the background color defined in CSS.
rippleDiv.style.backgroundColor = color;
// Start the ripple tiny.
rippleDiv.style.transform = "scale(0.001)";
var fadeInSeconds = (1 / (speedFactor || 1)) * Math.max(MIN_RIPPLE_FILL_TIME_SECONDS, Math.min(MAX_RIPPLE_FILL_TIME_SECONDS, maxRadius / RIPPLE_SPEED_PX_PER_SECOND));
rippleDiv.style.transitionDuration = fadeInSeconds + "s";
// https://timtaubert.de/blog/2012/09/css-transitions-for-dynamically-created-dom-elements/
window.getComputedStyle(rippleDiv).opacity;
rippleDiv.classList.add('md-ripple-fade-in');
// Clearing the transform property causes the ripple to animate to its full size.
rippleDiv.style.transform = '';
var ripple = new ForegroundRipple(rippleDiv);
ripple.state = ForegroundRippleState.EXPANDING;
rippleDiv.addEventListener('transitionend', function (event) { return transitionEndCallback(ripple, event); });
};
/**
* Fades out a foreground ripple after it has fully expanded and faded in.
*/
RippleRenderer.prototype.fadeOutForegroundRipple = function (ripple) {
ripple.classList.remove('md-ripple-fade-in');
ripple.classList.add('md-ripple-fade-out');
};
/**
* Removes a foreground ripple from the DOM after it has faded out.
*/
RippleRenderer.prototype.removeRippleFromDom = function (ripple) {
ripple.parentElement.removeChild(ripple);
};
/**
* Fades in the ripple background.
*/
RippleRenderer.prototype.fadeInRippleBackground = function (color) {
this._backgroundDiv.classList.add('md-ripple-active');
// If color is not set, this will default to the background color defined in CSS.
this._backgroundDiv.style.backgroundColor = color;
};
/**
* Fades out the ripple background.
*/
RippleRenderer.prototype.fadeOutRippleBackground = function () {
if (this._backgroundDiv) {
this._backgroundDiv.classList.remove('md-ripple-active');
}
};
return RippleRenderer;
}());
var __decorate$3 = (window && window.__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 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var MdRipple = (function () {
function MdRipple(_elementRef) {
var _this = this;
/**
* 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.maxRadius = 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.
*/
this.speedFactor = 1;
// These event handlers are attached to the element that triggers the ripple animations.
var eventHandlers = new Map();
eventHandlers.set('mousedown', function (event) { return _this._mouseDown(event); });
eventHandlers.set('click', function (event) { return _this._click(event); });
eventHandlers.set('mouseleave', function (event) { return _this._mouseLeave(event); });
this._rippleRenderer = new RippleRenderer(_elementRef, eventHandlers);
}
/** TODO: internal */
MdRipple.prototype.ngOnInit = function () {
// If no trigger element was explicity set, use the host element
if (!this.trigger) {
this._rippleRenderer.setTriggerElementToHost();
}
};
/** TODO: internal */
MdRipple.prototype.ngOnDestroy = function () {
// Remove event listeners on the trigger element.
this._rippleRenderer.clearTriggerElement();
};
/** TODO: internal */
MdRipple.prototype.ngOnChanges = function (changes) {
// If the trigger element changed (or is being initially set), add event listeners to it.
var changedInputs = Object.keys(changes);
if (changedInputs.indexOf('trigger') !== -1) {
this._rippleRenderer.setTriggerElement(this.trigger);
}
};
/**
* Responds to the start of a ripple animation trigger by fading the background in.
*/
MdRipple.prototype.start = function () {
this._rippleRenderer.fadeInRippleBackground(this.backgroundColor);
};
/**
* Responds to the end of a ripple animation trigger by fading the background out, and creating a
* foreground ripple that expands from the event location (or from the center of the element if
* the "centered" property is set or forceCenter is true).
*/
MdRipple.prototype.end = function (left, top, forceCenter) {
var _this = this;
if (forceCenter === void 0) { forceCenter = true; }
this._rippleRenderer.createForegroundRipple(left, top, this.color, this.centered || forceCenter, this.maxRadius, this.speedFactor, function (ripple, e) { return _this._rippleTransitionEnded(ripple, e); });
this._rippleRenderer.fadeOutRippleBackground();
};
MdRipple.prototype._rippleTransitionEnded = function (ripple, event) {
if (event.propertyName === 'opacity') {
// If the ripple finished expanding, start fading it out. If it finished fading out,
// remove it from the DOM.
switch (ripple.state) {
case ForegroundRippleState.EXPANDING:
this._rippleRenderer.fadeOutForegroundRipple(ripple.rippleElement);
ripple.state = ForegroundRippleState.FADING_OUT;
break;
case ForegroundRippleState.FADING_OUT:
this._rippleRenderer.removeRippleFromDom(ripple.rippleElement);
break;
}
}
};
/**
* Called when the trigger element receives a mousedown event. Starts the ripple animation by
* fading in the background.
*/
MdRipple.prototype._mouseDown = function (event) {
if (!this.disabled && event.button === 0) {
this.start();
}
};
/**
* Called when the trigger element receives a click event. Creates a foreground ripple and
* runs its animation.
*/
MdRipple.prototype._click = function (event) {
if (!this.disabled && event.button === 0) {
// If screen and page positions are all 0, this was probably triggered by a keypress.
// In that case, use the center of the bounding rect as the ripple origin.
// FIXME: This fails on IE11, which still sets pageX/Y and screenX/Y on keyboard clicks.
var isKeyEvent = (event.screenX === 0 && event.screenY === 0 && event.pageX === 0 && event.pageY === 0);
this.end(event.pageX, event.pageY, isKeyEvent);
}
};
/**
* Called when the trigger element receives a mouseleave event. Fades out the background.
*/
MdRipple.prototype._mouseLeave = function (event) {
// We can always fade out the background here; It's a no-op if it was already inactive.
this._rippleRenderer.fadeOutRippleBackground();
};
__decorate$3([
_angular_core.Input('md-ripple-trigger'),
__metadata$3('design:type', Object)
], MdRipple.prototype, "trigger", void 0);
__decorate$3([
_angular_core.Input('md-ripple-centered'),
__metadata$3('design:type', Boolean)
], MdRipple.prototype, "centered", void 0);
__decorate$3([
_angular_core.Input('md-ripple-disabled'),
__metadata$3('design:type', Boolean)
], MdRipple.prototype, "disabled", void 0);
__decorate$3([
_angular_core.Input('md-ripple-max-radius'),
__metadata$3('design:type', Number)
], MdRipple.prototype, "maxRadius", void 0);
__decorate$3([
_angular_core.Input('md-ripple-speed-factor'),
__metadata$3('design:type', Number)
], MdRipple.prototype, "speedFactor", void 0);
__decorate$3([
_angular_core.Input('md-ripple-color'),
__metadata$3('design:type', String)
], MdRipple.prototype, "color", void 0);
__decorate$3([
_angular_core.Input('md-ripple-background-color'),
__metadata$3('design:type', String)
], MdRipple.prototype, "backgroundColor", void 0);
__decorate$3([
_angular_core.HostBinding('class.md-ripple-focused'),
_angular_core.Input('md-ripple-focused'),
__metadata$3('design:type', Boolean)
], MdRipple.prototype, "focused", void 0);
__decorate$3([
_angular_core.HostBinding('class.md-ripple-unbounded'),
_angular_core.Input('md-ripple-unbounded'),
__metadata$3('design:type', Boolean)
], MdRipple.prototype, "unbounded", void 0);
MdRipple = __decorate$3([
_angular_core.Directive({
selector: '[md-ripple]',
}),
__metadata$3('design:paramtypes', [_angular_core.ElementRef])
], MdRipple);
return MdRipple;
}());
var MdRippleModule = (function () {
function MdRippleModule() {
}
MdRippleModule.forRoot = function () {
return {
ngModule: MdRippleModule,
providers: []
};
};
MdRippleModule = __decorate$3([
_angular_core.NgModule({
exports: [MdRipple],
declarations: [MdRipple],
}),
__metadata$3('design:paramtypes', [])
], MdRippleModule);
return MdRippleModule;
}());
// TODO(kara): Revisit why error messages are not being properly set.
var __extends$3 = (window && window.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/**
* Wrapper around Error that sets the error message.
*/
var MdError = (function (_super) {
__extends$3(MdError, _super);
function MdError(value) {
_super.call(this);
this.message = value;
}
return MdError;
}(Error));
var __extends$2 = (window && window.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/** Exception thrown when a ComponentPortal is attached to a DomPortalHost without an origin. */
var MdComponentPortalAttachedToDomWithoutOriginError = (function (_super) {
__extends$2(MdComponentPortalAttachedToDomWithoutOriginError, _super);
function MdComponentPortalAttachedToDomWithoutOriginError() {
_super.call(this, 'A ComponentPortal must have an origin set when attached to a DomPortalHost ' +
'because the DOM element is not part of the Angular application context.');
}
return MdComponentPortalAttachedToDomWithoutOriginError;
}(MdError));
/** Exception thrown when attempting to attach a null portal to a host. */
var MdNullPortalError = (function (_super) {
__extends$2(MdNullPortalError, _super);
function MdNullPortalError() {
_super.call(this, 'Must provide a portal to attach');
}
return MdNullPortalError;
}(MdError));
/** Exception thrown when attempting to attach a portal to a host that is already attached. */
var MdPortalAlreadyAttachedError = (function (_super) {
__extends$2(MdPortalAlreadyAttachedError, _super);
function MdPortalAlreadyAttachedError() {
_super.call(this, 'Host already has a portal attached');
}
return MdPortalAlreadyAttachedError;
}(MdError));
/** Exception thrown when attempting to attach a portal to an already-disposed host. */
var MdPortalHostAlreadyDisposedError = (function (_super) {
__extends$2(MdPortalHostAlreadyDisposedError, _super);
function MdPortalHostAlreadyDisposedError() {
_super.call(this, 'This PortalHost has already been disposed');
}
return MdPortalHostAlreadyDisposedError;
}(MdError));
/** Exception thrown when attempting to attach an unknown portal type. */
var MdUnknownPortalTypeError = (function (_super) {
__extends$2(MdUnknownPortalTypeError, _super);
function MdUnknownPortalTypeError() {
_super.call(this, 'Attempting to attach an unknown Portal type. ' +
'BasePortalHost accepts either a ComponentPortal or a TemplatePortal.');
}
return MdUnknownPortalTypeError;
}(MdError));
/** Exception thrown when attempting to attach a portal to a null host. */
var MdNullPortalHostError = (function (_super) {
__extends$2(MdNullPortalHostError, _super);
function MdNullPortalHostError() {
_super.call(this, 'Attempting to attach a portal to a null PortalHost');
}
return MdNullPortalHostError;
}(MdError));
/** Exception thrown when attempting to detach a portal that is not attached. */
var MdNoPortalAttachedError = (function (_super) {
__extends$2(MdNoPortalAttachedError, _super);
function MdNoPortalAttachedError() {
_super.call(this, 'Attempting to detach a portal that is not attached to a host');
}
return MdNoPortalAttachedError;
}(MdError));
var __extends$1 = (window && window.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/**
* A `Portal` is something that you want to render somewhere else.
* It can be attach to / detached from a `PortalHost`.
*/
var Portal = (function () {
function Portal() {
}
/** Attach this portal to a host. */
Portal.prototype.attach = function (host) {
if (host == null) {
throw new MdNullPortalHostError();
}
if (host.hasAttached()) {
throw new MdPortalAlreadyAttachedError();
}
this._attachedHost = host;
return host.attach(this);
};
/** Detach this portal from its host */
Portal.prototype.detach = function () {
var host = this._attachedHost;
if (host == null) {
throw new MdNoPortalAttachedError();
}
this._attachedHost = null;
return host.detach();
};
Object.defineProperty(Portal.prototype, "isAttached", {
/** Whether this portal is attached to a host. */
get: function () {
return this._attachedHost != null;
},
enumerable: true,
configurable: true
});
/**
* Sets the PortalHost reference without performing `attach()`. This is used directly by
* the PortalHost when it is performing an `attach()` or `detatch()`.
*/
Portal.prototype.setAttachedHost = function (host) {
this._attachedHost = host;
};
return Portal;
}());
/**
* A `ComponentPortal` is a portal that instantiates some Component upon attachment.
*/
var ComponentPortal = (function (_super) {
__extends$1(ComponentPortal, _super);
function ComponentPortal(component, viewContainerRef, injector) {
if (viewContainerRef === void 0) { viewContainerRef = null; }
if (injector === void 0) { injector = null; }
_super.call(this);
this.component = component;
this.viewContainerRef = viewContainerRef;
this.injector = injector;
}
return ComponentPortal;
}(Portal));
/**
* A `TemplatePortal` is a portal that represents some embedded template (TemplateRef).
*/
var TemplatePortal = (function (_super) {
__extends$1(TemplatePortal, _super);
function TemplatePortal(template, viewContainerRef) {
_super.call(this);
/**
* Additional locals for the instantiated embedded view.
* These locals can be seen as "exports" for the template, such as how ngFor has
* index / event / odd.
* See https://angular.io/docs/ts/latest/api/core/EmbeddedViewRef-class.html
*/
this.locals = new Map();
this.templateRef = template;
this.viewContainerRef = viewContainerRef;
}
Object.defineProperty(TemplatePortal.prototype, "origin", {
get: function () {
return this.templateRef.elementRef;
},
enumerable: true,
configurable: true
});
TemplatePortal.prototype.attach = function (host, locals) {
this.locals = locals == null ? new Map() : locals;
return _super.prototype.attach.call(this, host);
};
TemplatePortal.prototype.detach = function () {
this.locals = new Map();
return _super.prototype.detach.call(this);
};
return TemplatePortal;
}(Portal));
/**
* Partial implementation of PortalHost that only deals with attaching either a
* ComponentPortal or a TemplatePortal.
*/
var BasePortalHost = (function () {
function BasePortalHost() {
/** Whether this host has already been permanently disposed. */
this._isDisposed = false;
}
/** Whether this host has an attached portal. */
BasePortalHost.prototype.hasAttached = function () {
return this._attachedPortal != null;
};
BasePortalHost.prototype.attach = function (portal) {
if (portal == null) {
throw new MdNullPortalError();
}
if (this.hasAttached()) {
throw new MdPortalAlreadyAttachedError();
}
if (this._isDisposed) {
throw new MdPortalHostAlreadyDisposedError();
}
if (portal instanceof ComponentPortal) {
this._attachedPortal = portal;
return this.attachComponentPortal(portal);
}
else if (portal instanceof TemplatePortal) {
this._attachedPortal = portal;
return this.attachTemplatePortal(portal);
}
throw new MdUnknownPortalTypeError();
};
BasePortalHost.prototype.detach = function () {
if (this._attachedPortal) {
this._attachedPortal.setAttachedHost(null);
}
this._attachedPortal = null;
if (this._disposeFn != null) {
this._disposeFn();
this._disposeFn = null;
}
};
BasePortalHost.prototype.dispose = function () {
if (this.hasAttached()) {
this.detach();
}
this._isDisposed = true;
};
BasePortalHost.prototype.setDisposeFn = function (fn) {
this._disposeFn = fn;
};
return BasePortalHost;
}());
var __extends = (window && window.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var __decorate$4 = (window && window.__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 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/**
* Directive version of a `TemplatePortal`. Because the directive *is* a TemplatePortal,
* the directive instance itself can be attached to a host, enabling declarative use of portals.
*
* Usage:
* <template portal #greeting>
* <p> Hello {{name}} </p>
* </template>
*/
var TemplatePortalDirective = (function (_super) {
__extends(TemplatePortalDirective, _super);
function TemplatePortalDirective(templateRef, viewContainerRef) {
_super.call(this, templateRef, viewContainerRef);
}
TemplatePortalDirective = __decorate$4([
_angular_core.Directive({
selector: '[portal]',
exportAs: 'portal',
}),
__metadata$4('design:paramtypes', [_angular_core.TemplateRef, _angular_core.ViewContainerRef])
], TemplatePortalDirective);
return TemplatePortalDirective;
}(TemplatePortal));
/**
* Directive version of a PortalHost. Because the directive *is* a PortalHost, portals can be
* directly attached to it, enabling declarative use.
*
* Usage:
* <template [portalHost]="greeting"></template>
*/
var PortalHostDirective = (function (_super) {
__extends(PortalHostDirective, _super);
function PortalHostDirective(_componentFactoryResolver, _viewContainerRef) {
_super.call(this);
this._componentFactoryResolver = _componentFactoryResolver;
this._viewContainerRef = _viewContainerRef;
}
Object.defineProperty(PortalHostDirective.prototype, "portal", {
get: function () {
return this._portal;
},
set: function (p) {
this._replaceAttachedPortal(p);
},
enumerable: true,
configurable: true
});
/** Attach the given ComponentPortal to this PortlHost using the ComponentFactoryResolver. */
PortalHostDirective.prototype.attachComponentPortal = function (portal) {
portal.setAttachedHost(this);
// If the portal specifies an origin, use that as the logical location of the component
// in the application tree. Otherwise use the location of this PortalHost.
var viewContainerRef = portal.viewContainerRef != null ?
portal.viewContainerRef :
this._viewContainerRef;
var componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component);
var ref = viewContainerRef.createComponent(componentFactory, viewContainerRef.length, portal.injector || viewContainerRef.parentInjector);
this.setDisposeFn(function () { return ref.destroy(); });
return ref;
};
/** Attach the given TemplatePortal to this PortlHost as an embedded View. */
PortalHostDirective.prototype.attachTemplatePortal = function (portal) {
var _this = this;
portal.setAttachedHost(this);
this._viewContainerRef.createEmbeddedView(portal.templateRef);
this.setDisposeFn(function () { return _this._viewContainerRef.clear(); });
// TODO(jelbourn): return locals from view
return new Map();
};
/** Detatches the currently attached Portal (if there is one) and attaches the given Portal. */
PortalHostDirective.prototype._replaceAttachedPortal = function (p) {
if (this.hasAttached()) {
this.detach();
}
if (p) {
this.attach(p);
this._portal = p;
}
};
PortalHostDirective = __decorate$4([
_angular_core.Directive({
selector: '[portalHost]',
inputs: ['portal: portalHost']
}),
__metadata$4('design:paramtypes', [_angular_core.ComponentFactoryResolver, _angular_core.ViewContainerRef])
], PortalHostDirective);
return PortalHostDirective;
}(BasePortalHost));
var PortalModule = (function () {
function PortalModule() {
}
PortalModule.forRoot = function () {
return {
ngModule: PortalModule,
providers: []
};
};
PortalModule = __decorate$4([
_angular_core.NgModule({
exports: [TemplatePortalDirective, PortalHostDirective],
declarations: [TemplatePortalDirective, PortalHostDirective],
}),
__metadata$4('design:paramtypes', [])
], PortalModule);
return PortalModule;
}());
/**
* OverlayState is a bag of values for either the initial configuration or current state of an
* overlay.
*/
var OverlayState = (function () {
function OverlayState() {
}
return OverlayState;
}());
var __extends$4 = (window && window.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
/**
* A PortalHost for attaching portals to an arbitrary DOM element outside of the Angular
* application context.
*
* This is the only part of the portal core that directly touches the DOM.
*/
var DomPortalHost = (function (_super) {
__extends$4(DomPortalHost, _super);
function DomPortalHost(_hostDomElement, _componentFactoryResolver) {
_super.call(this);
this._hostDomElement = _hostDomElement;
this._componentFactoryResolver = _componentFactoryResolver;
}
/** Attach the given ComponentPortal to DOM element using the ComponentFactoryResolver. */
DomPortalHost.prototype.attachComponentPortal = function (portal) {
if (portal.viewContainerRef == null) {
throw new MdComponentPortalAttachedToDomWithoutOriginError();
}
var componentFactory = this._componentFactoryResolver.resolveComponentFactory(portal.component);
var ref = portal.viewContainerRef.createComponent(componentFactory, portal.viewContainerRef.length, portal.injector || portal.viewContainerRef.parentInjector);
var hostView = ref.hostView;
this._hostDomElement.appendChild(hostView.rootNodes[0]);
this.setDisposeFn(function () { return ref.destroy(); });
return ref;
};
DomPortalHost.prototype.attachTemplatePortal = function (portal) {
var _this = this;
var viewContainer = portal.viewContainerRef;
var viewRef = viewContainer.createEmbeddedView(portal.templateRef);
viewRef.rootNodes.forEach(function (rootNode) { return _this._hostDomElement.appendChild(rootNode); });
this.setDisposeFn((function () {
var index = viewContainer.indexOf(viewRef);
if (index != -1) {
viewContainer.remove(index);
}
}));
// TODO(jelbourn): Return locals from view.
return new Map();
};
DomPortalHost.prototype.dispose = function () {
_super.prototype.dispose.call(this);
if (this._hostDomElement.parentNode != null) {
this._hostDomElement.parentNode.removeChild(this._hostDomElement);
}
};
return DomPortalHost;
}(BasePortalHost));
/**
* Reference to an overlay that has been created with the Overlay service.
* Used to manipulate or dispose of said overlay.
*/
var OverlayRef = (function () {
function OverlayRef(_portalHost, _pane, _state) {
this._portalHost = _portalHost;
this._pane = _pane;
this._state = _state;
}
OverlayRef.prototype.attach = function (portal) {
var attachResult = this._portalHost.attach(portal);
this.updatePosition();
return attachResult;
};
OverlayRef.prototype.detach = function () {
return this._portalHost.detach();
};
OverlayRef.prototype.dispose = function () {
this._portalHost.dispose();
};
OverlayRef.prototype.hasAttached = function () {
return this._portalHost.hasAttached();
};
/** Gets the current state config of the overlay. */
OverlayRef.prototype.getState = function () {
return this._state;
};
/** Updates the position of the overlay based on the position strategy. */
OverlayRef.prototype.updatePosition = function () {
if (this._state.positionStrategy) {
this._state.positionStrategy.apply(this._pane);
}
};
return OverlayRef;
}());
var __decorate$8 = (window && window.__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$8 = (window && window.__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.
* TODO: internal
*/
var ViewportRuler = (function () {
function ViewportRuler() {
}
// TODO(jelbourn): cache the document's bounding rect and only update it when the window
// is resized (debounced).
/** Gets a ClientRect for the viewport's bounds. */
ViewportRuler.prototype.getViewportRect = function () {
// 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 documentRect = document.documentElement.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 = document.documentElement.getBoundingClientRect(); }
// 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 < 0 && document.body.scrollTop == 0 ?
-documentRect.top :
document.body.scrollTop;
var left = documentRect.left < 0 && document.body.scrollLeft == 0 ?
-documentRect.left :
document.body.scrollLeft;
return { top: top, left: left };
};
ViewportRuler = __decorate$8([
_angular_core.Injectable(),
__metadata$8('design:paramtypes', [])
], ViewportRuler);
return ViewportRuler;
}());
/** The points of the origin element and the overlay element to connect. */
var ConnectionPositionPair = (function () {
function ConnectionPositionPair(origin, overlay) {
this.originX = origin.originX;
this.originY = origin.originY;
this.overlayX = overlay.overlayX;
this.overlayY = overlay.overlayY;
}
return ConnectionPositionPair;
}());
/**
* A strategy for positioning overlays. Using this strategy, an overlay is given an
* implict position relative some origin element. The relative position is defined in terms of
* a point on the origin element that is connected to a point on the overlay element. For example,
* a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner
* of the overlay.
*/
var ConnectedPositionStrategy = (function () {
function ConnectedPositionStrategy(_connectedTo, _originPos, _overlayPos, _viewportRuler) {
this._connectedTo = _connectedTo;
this._originPos = _originPos;
this._overlayPos = _overlayPos;
this._viewportRuler = _viewportRuler;
// TODO(jelbourn): set RTL to the actual value from the app.
/** Whether the we're dealing with an RTL context */
this._isRtl = false;
/** Ordered list of preferred positions, from most to least desirable. */
this._preferredPositions = [];
this._origin = this._connectedTo.nativeElement;
this.withFallbackPosition(_originPos, _overlayPos);
}
Object.defineProperty(ConnectedPositionStrategy.prototype, "positions", {
get: function () {
return this._preferredPositions;
},
enumerable: true,
configurable: true
});
/**
* Updates the position of the overlay element, using whichever preferred position relative
* to the origin fits on-screen.
* TODO: internal
*/
ConnectedPositionStrategy.prototype.apply = function (element) {
// We need the bounding rects for the origin and the overlay to determine how to position
// the overlay relative to the origin.
var originRect = this._origin.getBoundingClientRect();
var overlayRect = element.getBoundingClientRect();
// We use the viewport rect to determine whether a position would go off-screen.
var viewportRect = this._viewportRuler.getViewportRect();
var firstOverlayPoint = null;
// We want to place the overlay in the first of the preferred positions such that the
// overlay fits on-screen.
for (var _i = 0, _a = this._preferredPositions; _i < _a.length; _i++) {
var pos = _a[_i];
// Get the (x, y) point of connection on the origin, and then use that to get the
// (top, left) coordinate for the overlay at `pos`.
var originPoint = this._getOriginConnectionPoint(originRect, pos);
var overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos);
firstOverlayPoint = firstOverlayPoint || overlayPoint;
// If the overlay in the calculated position fits on-screen, put it there and we're done.
if (this._willOverlayFitWithinViewport(overlayPoint, overlayRect, viewportRect)) {
this._setElementPosition(element, overlayPoint);
return Promise.resolve(null);
}
}
// TODO(jelbourn): fallback behavior for when none of the preferred positions fit on-screen.
// For now, just stick it in the first position and let it go off-screen.
this._setElementPosition(element, firstOverlayPoint);
return Promise.resolve(null);
};
ConnectedPositionStrategy.prototype.withFallbackPosition = function (originPos, overlayPos) {
this._preferredPositions.push(new ConnectionPositionPair(originPos, overlayPos));
return this;
};
/**
* Gets the horizontal (x) "start" dimension based on whether the overlay is in an RTL context.
* @param rect
*/
ConnectedPositionStrategy.prototype._getStartX = function (rect) {
return this._isRtl ? rect.right : rect.left;
};
/**
* Gets the horizontal (x) "end" dimension based on whether the overlay is in an RTL context.
* @param rect
*/
ConnectedPositionStrategy.prototype._getEndX = function (rect) {
return this._isRtl ? rect.left : rect.right;
};
/**
* Gets the (x, y) coordinate of a connection point on the origin based on a relative position.
* @param originRect
* @param pos
*/
ConnectedPositionStrategy.prototype._getOriginConnectionPoint = function (originRect, pos) {
var originStartX = this._getStartX(originRect);
var originEndX = this._getEndX(originRect);
var x;
if (pos.originX == 'center') {
x = originStartX + (originRect.width / 2);
}
else {
x = pos.originX == 'start' ? originStartX : originEndX;
}
var y;
if (pos.originY == 'center') {
y = originRect.top + (originRect.height / 2);
}
else {
y = pos.originY == 'top' ? originRect.top : originRect.bottom;
}
return { x: x, y: y };
};
/**
* Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and
* origin point to which the overlay should be connected.
* @param originPoint
* @param overlayRect
* @param pos
*/
ConnectedPositionStrategy.prototype._getOverlayPoint = function (originPoint, overlayRect, pos) {
// Calculate the (overlayStartX, overlayStartY), the start of the potential overlay position
// relative to the origin point.
var overlayStartX;
if (pos.overlayX == 'center') {
overlayStartX = -overlayRect.width / 2;
}
else {
overlayStartX = pos.overlayX == 'start' ? 0 : -overlayRect.width;
}
var overlayStartY;
if (pos.overlayY == 'center') {
overlayStartY = -overlayRect.height / 2;
}
else {
overlayStartY = pos.overlayY == 'top' ? 0 : -overlayRect.height;
}
return {
x: originPoint.x + overlayStartX,
y: originPoint.y + overlayStartY
};
};
/**
* Gets whether the overlay positioned at the given point will fit on-screen.
* @param overlayPoint The top-left coordinate of the overlay.
* @param overlayRect Bounding rect of the overlay, used to get its size.
* @param viewportRect The bounding viewport.
*/
ConnectedPositionStrategy.prototype._willOverlayFitWithinViewport = function (overlayPoint, overlayRect, viewportRect) {
// TODO(jelbourn): probably also want some space between overlay edge and viewport edge.
return overlayPoint.x >= viewportRect.left &&
overlayPoint.x + overlayRect.width <= viewportRect.right &&
overlayPoint.y >= viewportRect.top &&
overlayPoint.y + overlayRect.height <= viewportRect.bottom;
};
/**
* Physically positions the overlay element to the given coordinate.
* @param element
* @param overlayPoint
*/
ConnectedPositionStrategy.prototype._setElementPosition = function (element, overlayPoint) {
var scrollPos = this._viewportRuler.getViewportScrollPosition();
var x = overlayPoint.x + scrollPos.left;
var y = overlayPoint.y + scrollPos.top;
// TODO(jelbourn): we don't want to always overwrite the transform property here,
// because it will need to be used for animations.
_angular2Material_core.applyCssTransform(element, "translateX(" + x + "px) translateY(" + y + "px)");
};
return ConnectedPositionStrategy;
}());
/**
* A strategy for positioning overlays. Using this strategy, an overlay is given an
* explicit position relative to the browser's viewport.
*/
var GlobalPositionStrategy = (function () {
function GlobalPositionStrategy() {
this._cssPosition = 'absolute';
this._top = '';
this._bottom = '';
this._left = '';
this._right = '';
/** Array of individual applications of translateX(). Currently only for centering. */
this._translateX = [];
/** Array of individual applications of translateY(). Currently only for centering. */
this._translateY = [];
}
/** Sets the element to usee CSS position: fixed */
GlobalPositionStrategy.prototype.fixed = function () {
this._cssPosition = 'fixed';
return this;
};
/** Sets the element to usee CSS position: absolute. This is the default. */
GlobalPositionStrategy.prototype.absolute = function () {
this._cssPosition = 'absolute';
return this;
};
/** Sets the top position of the overlay. Clears any previously set vertical position. */
GlobalPositionStrategy.prototype.top = function (value) {
this._bottom = '';
this._translateY = [];
this._top = value;
return this;
};
/** Sets the left position of the overlay. Clears any previously set horizontal position. */
GlobalPositionStrategy.prototype.left = function (value) {
this._right = '';
this._translateX = [];
this._left = value;
return this;
};
/** Sets the bottom position of the overlay. Clears any previously set vertical position. */
GlobalPositionStrategy.prototype.bottom = function (value) {
this._top = '';
this._translateY = [];
this._bottom = value;
return this;
};
/** Sets the right position of the overlay. Clears any previously set horizontal position. */
GlobalPositionStrategy.prototype.right = function (value) {
this._left = '';
this._translateX = [];
this._right = value;
return this;
};
/**
* Centers the overlay horizontally with an optional offset.
* Clears any previously set horizontal position.
*/
GlobalPositionStrategy.prototype.centerHorizontally = function (offset) {
if (offset === void 0) { offset = '0px'; }
this._left = '50%';
this._right = '';
this._translateX = ['-50%', offset];
return this;
};
/**
* Centers the overlay vertically with an optional offset.
* Clears any previously set vertical position.
*/
GlobalPositionStrategy.prototype.centerVertically = function (offset) {
if (offset === void 0) { offset = '0px'; }
this._top = '50%';
this._bottom = '';
this._translateY = ['-50%', offset];
return this;
};
/**
* Apply the position to the element.
* TODO: internal
*/
GlobalPositionStrategy.prototype.apply = function (element) {
element.style.position = this._cssPosition;
element.style.top = this._top;
element.style.left = this._left;
element.style.bottom = this._bottom;
element.style.right = this._right;
// TODO(jelbourn): we don't want to always overwrite the transform property here,
// because it will need to be used for animations.
var tranlateX = this._reduceTranslateValues('translateX', this._translateX);
var translateY = this._reduceTranslateValues('translateY', this._translateY);
_angular2Material_core.applyCssTransform(element, tranlateX + " " + translateY);
return Promise.resolve(null);
};
/** Reduce a list of translate values to a string that can be used in the transform property */
GlobalPositionStrategy.prototype._reduceTranslateValues = function (translateFn, values) {
return values.map(function (t) { return (translateFn + "(" + t + ")"); }).join(' ');
};
return GlobalPositionStrategy;
}());
var __decorate$7 = (window && window.__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$7 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/** Builder for overlay position strategy. */
var OverlayPositionBuilder = (function () {
function OverlayPositionBuilder(_viewportRuler) {
this._viewportRuler = _viewportRuler;
}
/** Creates a global position strategy. */
OverlayPositionBuilder.prototype.global = function () {
return new GlobalPositionStrategy();
};
/** Creates a relative position strategy. */
OverlayPositionBuilder.prototype.connectedTo = function (elementRef, originPos, overlayPos) {
return new ConnectedPositionStrategy(elementRef, originPos, overlayPos, this._viewportRuler);
};
OverlayPositionBuilder = __decorate$7([
_angular_core.Injectable(),
__metadata$7('design:paramtypes', [ViewportRuler])
], OverlayPositionBuilder);
return OverlayPositionBuilder;
}());
/**
* The OverlayContainer is the container in which all overlays will load.
* It should be provided in the root component to ensure it is properly shared.
*/
var OverlayContainer = (function () {
function OverlayContainer() {
}
/**
* This method returns the overlay container element. It will lazily
* create the element the first time it is called to facilitate using
* the container in non-browser environments.
* @returns {HTMLElement} the container element
*/
OverlayContainer.prototype.getContainerElement = function () {
if (!this._containerElement) {
this._createContainer();
}
return this._containerElement;
};
/**
* Create the overlay container element, which is simply a div
* with the 'md-overlay-container' class on the document body.
*/
OverlayContainer.prototype._createContainer = function () {
var container = document.createElement('div');
container.classList.add('md-overlay-container');
document.body.appendChild(container);
this._containerElement = container;
};
return OverlayContainer;
}());
var __decorate$6 = (window && window.__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 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/** Next overlay unique ID. */
var nextUniqueId = 0;
/** The default state for newly created overlays. */
var defaultState = new OverlayState();
/**
* Service to create Overlays. Overlays are dynamically added pieces of floating UI, meant to be
* used as a low-level building building block for other components. Dialogs, tooltips, menus,
* selects, etc. can all be built using overlays. The service should primarily be used by authors
* of re-usable components rather than developers building end-user applications.
*
* An overlay *is* a PortalHost, so any kind of Portal can be loaded into one.
*/
var Overlay = (function () {
function Overlay(_overlayContainer, _componentFactoryResolver, _positionBuilder) {
this._overlayContainer = _overlayContainer;
this._componentFactoryResolver = _componentFactoryResolver;
this._positionBuilder = _positionBuilder;
}
/**
* Creates an overlay.
* @param state State to apply to the overlay.
* @returns A reference to the created overlay.
*/
Overlay.prototype.create = function (state) {
if (state === void 0) { state = defaultState; }
return this._createOverlayRef(this._createPaneElement(), state);
};
/**
* Returns a position builder that can be used, via fluent API,
* to construct and configure a position strategy.
*/
Overlay.prototype.position = function () {
return this._positionBuilder;
};
/**
* Creates the DOM element for an overlay and appends it to the overlay container.
* @returns Promise resolving to the created element.
*/
Overlay.prototype._createPaneElement = function () {
var pane = document.createElement('div');
pane.id = "md-overlay-" + nextUniqueId++;
pane.classList.add('md-overlay-pane');
this._overlayContainer.getContainerElement().appendChild(pane);
return pane;
};
/**
* Create a DomPortalHost into which the overlay content can be loaded.
* @param pane The DOM element to turn into a portal host.
* @returns A portal host for the given DOM element.
*/
Overlay.prototype._createPortalHost = function (pane) {
return new DomPortalHost(pane, this._componentFactoryResolver);
};
/**
* Creates an OverlayRef for an overlay in the given DOM element.
* @param pane DOM element for the overlay
* @param state
* @returns {OverlayRef}
*/
Overlay.prototype._createOverlayRef = function (pane, state) {
return new OverlayRef(this._createPortalHost(pane), pane, state);
};
Overlay = __decorate$6([
_angular_core.Injectable(),
__metadata$6('design:paramtypes', [OverlayContainer, _angular_core.ComponentFactoryResolver, OverlayPositionBuilder])
], Overlay);
return Overlay;
}());
/** Providers for Overlay and its related injectables. */
var OVERLAY_PROVIDERS = [
ViewportRuler,
OverlayPositionBuilder,
Overlay,
OverlayContainer,
];
var __decorate$5 = (window && window.__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 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/** Default set of positions for the overlay. Follows the behavior of a dropdown. */
var defaultPositionList = [
new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' }),
new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' }),
];
/**
* Directive applied to an element to make it usable as an origin for an Overlay using a
* ConnectedPositionStrategy.
*/
var OverlayOrigin = (function () {
function OverlayOrigin(_elementRef) {
this._elementRef = _elementRef;
}
Object.defineProperty(OverlayOrigin.prototype, "elementRef", {
get: function () {
return this._elementRef;
},
enumerable: true,
configurable: true
});
OverlayOrigin = __decorate$5([
_angular_core.Directive({
selector: '[overlay-origin]',
exportAs: 'overlayOrigin',
}),
__metadata$5('design:paramtypes', [_angular_core.ElementRef])
], OverlayOrigin);
return OverlayOrigin;
}());
/**
* Directive to facilitate declarative creation of an Overlay using a ConnectedPositionStrategy.
*/
var ConnectedOverlayDirective = (function () {
// TODO(jelbourn): inputs for size, scroll behavior, animation, etc.
function ConnectedOverlayDirective(_overlay, templateRef, viewContainerRef) {
this._overlay = _overlay;
this._templatePortal = new TemplatePortal(templateRef, viewContainerRef);
}
Object.defineProperty(ConnectedOverlayDirective.prototype, "overlayRef", {
get: function () {
return this._overlayRef;
},
enumerable: true,
configurable: true
});
/** TODO: internal */
ConnectedOverlayDirective.prototype.ngOnInit = function () {
this._createOverlay();
};
/** TODO: internal */
ConnectedOverlayDirective.prototype.ngOnDestroy = function () {
this._destroyOverlay();
};
/** Creates an overlay and attaches this directive's template to it. */
ConnectedOverlayDirective.prototype._createOverlay = function () {
if (!this.positions || !this.positions.length) {
this.positions = defaultPositionList;
}
var overlayConfig = new OverlayState();
overlayConfig.positionStrategy =
this._overlay.position().connectedTo(this.origin.elementRef, { originX: this.positions[0].overlayX, originY: this.positions[0].originY }, { overlayX: this.positions[0].overlayX, overlayY: this.positions[0].overlayY });
this._overlayRef = this._overlay.create(overlayConfig);
this._overlayRef.attach(this._templatePortal);
};
/** Destroys the overlay created by this directive. */
ConnectedOverlayDirective.prototype._destroyOverlay = function () {
this._overlayRef.dispose();
};
__decorate$5([
_angular_core.Input(),
__metadata$5('design:type', OverlayOrigin)
], ConnectedOverlayDirective.prototype, "origin", void 0);
__decorate$5([
_angular_core.Input(),
__metadata$5('design:type', Array)
], ConnectedOverlayDirective.prototype, "positions", void 0);
ConnectedOverlayDirective = __decorate$5([
_angular_core.Directive({
selector: '[connected-overlay]'
}),
__metadata$5('design:paramtypes', [Overlay, _angular_core.TemplateRef, _angular_core.ViewContainerRef])
], ConnectedOverlayDirective);
return ConnectedOverlayDirective;
}());
var OverlayModule = (function () {
function OverlayModule() {
}
OverlayModule.forRoot = function () {
return {
ngModule: OverlayModule,
providers: OVERLAY_PROVIDERS,
};
};
OverlayModule = __decorate$5([
_angular_core.NgModule({
imports: [PortalModule],
exports: [ConnectedOverlayDirective, OverlayOrigin],
declarations: [ConnectedOverlayDirective, OverlayOrigin],
}),
__metadata$5('design:paramtypes', [])
], OverlayModule);
return OverlayModule;
}());
var __decorate$9 = (window && window.__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$9 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (window && window.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
var LIVE_ANNOUNCER_ELEMENT_TOKEN = new _angular_core.OpaqueToken('mdLiveAnnouncerElement');
var MdLiveAnnouncer = (function () {
function MdLiveAnnouncer(elementToken) {
// We inject the live element as `any` because the constructor signature cannot reference
// browser globals (HTMLElement) on non-browser environments, since having a class decorator
// causes TypeScript to preserve the constructor signature types.
this._liveElement = elementToken || this._createLiveElement();
}
/**
* @param message Message to be announced to the screenreader
* @param politeness The politeness of the announcer element.
*/
MdLiveAnnouncer.prototype.announce = function (message, politeness) {
var _this = this;
if (politeness === void 0) { politeness = 'polite'; }
this._liveElement.textContent = '';
// TODO: ensure changing the politeness works on all environments we support.
this._liveElement.setAttribute('aria-live', politeness);
// This 100ms timeout is necessary for some browser + screen-reader combinations:
// - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout.
// - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a
// second time without clearing and then using a non-zero delay.
// (using JAWS 17 at time of this writing).
setTimeout(function () { return _this._liveElement.textContent = message; }, 100);
};
MdLiveAnnouncer.prototype._createLiveElement = function () {
var liveEl = document.createElement('div');
liveEl.classList.add('md-live-announcer');
liveEl.setAttribute('aria-atomic', 'true');
liveEl.setAttribute('aria-live', 'polite');
document.body.appendChild(liveEl);
return liveEl;
};
MdLiveAnnouncer = __decorate$9([
_angular_core.Injectable(),
__param(0, _angular_core.Optional()),
__param(0, _angular_core.Inject(LIVE_ANNOUNCER_ELEMENT_TOKEN)),
__metadata$9('design:paramtypes', [Object])
], MdLiveAnnouncer);
return MdLiveAnnouncer;
}());
var __extends$5 = (window && window.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var __decorate$10 = (window && window.__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$10 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/* Adjusts configuration of our gesture library, Hammer. */
var MdGestureConfig = (function (_super) {
__extends$5(MdGestureConfig, _super);
function MdGestureConfig() {
_super.apply(this, arguments);
/* List of new event names to add to the gesture support list */
this.events = [
'drag',
'dragstart',
'dragend',
'dragright',
'dragleft',
'longpress',
'slide',
'slidestart',
'slideend',
'slideright',
'slideleft'
];
}
/*
* Builds Hammer instance manually to add custom recognizers that match the Material Design spec.
*
* Our gesture names come from the Material Design gestures spec:
* https://www.google.com/design/spec/patterns/gestures.html#gestures-touch-mechanics
*
* More information on default recognizers can be found in Hammer docs:
* http://hammerjs.github.io/recognizer-pan/
* http://hammerjs.github.io/recognizer-press/
*
* TODO: Confirm threshold numbers with Material Design UX Team
* */
MdGestureConfig.prototype.buildHammer = function (element) {
var mc = new Hammer(element);
// Default Hammer Recognizers.
var pan = new Hammer.Pan();
var swipe = new Hammer.Swipe();
var press = new Hammer.Press();
// Notice that a HammerJS recognizer can only depend on one other recognizer once.
// Otherwise the previous `recognizeWith` will be dropped.
var slide = this._createRecognizer(pan, { event: 'slide', threshold: 0 }, swipe);
var drag = this._createRecognizer(slide, { event: 'drag', threshold: 6 }, swipe);
var longpress = this._createRecognizer(press, { event: 'longpress', time: 500 });
// Overwrite the default `pan` event to use the swipe event.
pan.recognizeWith(swipe);
// Add customized gestures to Hammer manager
mc.add([swipe, press, pan, drag, slide, longpress]);
return mc;
};
/** Creates a new recognizer, without affecting the default recognizers of HammerJS */
MdGestureConfig.prototype._createRecognizer = function (base, options) {
var inheritances = [];
for (var _i = 2; _i < arguments.length; _i++) {
inheritances[_i - 2] = arguments[_i];
}
var recognizer = new base.constructor(options);
inheritances.push(base);
inheritances.forEach(function (item) { return recognizer.recognizeWith(item); });
return recognizer;
};
MdGestureConfig = __decorate$10([
_angular_core.Injectable(),
__metadata$10('design:paramtypes', [])
], MdGestureConfig);
return MdGestureConfig;
}(_angular_platformBrowser.HammerGestureConfig));
var __decorate$11 = (window && window.__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$11 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/**
* Class to coordinate unique selection based on name.
* Intended to be consumed as an Angular service.
* This service is needed because native radio change events are only fired on the item currently
* being selected, and we still need to uncheck the previous selection.
*
* This service does not *store* any IDs and names because they may change at any time, so it is
* less error-prone if they are simply passed through when the events occur.
*/
var MdUniqueSelectionDispatcher = (function () {
function MdUniqueSelectionDispatcher() {
this._listeners = [];
}
/** Notify other items that selection for the given name has been set. */
MdUniqueSelectionDispatcher.prototype.notify = function (id, name) {
for (var _i = 0, _a = this._listeners; _i < _a.length; _i++) {
var listener = _a[_i];
listener(id, name);
}
};
/** Listen for future changes to item selection. */
MdUniqueSelectionDispatcher.prototype.listen = function (listener) {
this._listeners.push(listener);
};
MdUniqueSelectionDispatcher = __decorate$11([
_angular_core.Injectable(),
__metadata$11('design:paramtypes', [])
], MdUniqueSelectionDispatcher);
return MdUniqueSelectionDispatcher;
}());
/**
* Applies a CSS transform to an element, including browser-prefixed properties.
* @param element
* @param transformValue
*/
function applyCssTransform$1(element, transformValue) {
// It's important to trim the result, because the browser will ignore the set operation
// if the string contains only whitespace.
var value = transformValue.trim();
element.style.transform = value;
element.style.webkitTransform = value;
}
/**
* Annotation Factory that allows HTML style boolean attributes. For example,
* a field declared like this:
* @Directive({ selector: 'component' }) class MyComponent {
* @Input() @BooleanFieldValueFactory() myField: boolean;
* }
*
* You could set it up this way:
* <component myField>
* or:
* <component myField="">
* @deprecated
*/
function booleanFieldValueFactory() {
return function booleanFieldValueMetadata(target, key) {
var defaultValue = target[key];
var localKey = "__md_private_symbol_" + key;
target[localKey] = defaultValue;
Object.defineProperty(target, key, {
get: function () { return this[localKey]; },
set: function (value) {
this[localKey] = value != null && "" + value !== 'false';
}
});
};
}
// Due to a bug in the ChromeDriver, Angular 2 keyboard events are not triggered by `sendKeys`
// during E2E tests when using dot notation such as `(keydown.rightArrow)`. To get around this,
// we are temporarily using a single (keydown) handler.
// See: https://github.com/angular/angular/issues/9419
var UP_ARROW = 38;
var DOWN_ARROW = 40;
var RIGHT_ARROW = 39;
var LEFT_ARROW = 37;
var ENTER = 13;
var TAB = 9;
var __decorate = (window && window.__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 = (window && window.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var MdCoreModule = (function () {
function MdCoreModule() {
}
MdCoreModule.forRoot = function () {
return {
ngModule: MdCoreModule,
providers: [MdLiveAnnouncer]
};
};
MdCoreModule = __decorate([
_angular_core.NgModule({
imports: [MdLineModule, RtlModule, MdRippleModule, PortalModule, OverlayModule],
exports: [MdLineModule, RtlModule, MdRippleModule, PortalModule, OverlayModule],
}),
__metadata('design:paramtypes', [])
], MdCoreModule);
return MdCoreModule;
}());
exports.MdCoreModule = MdCoreModule;
exports.Dir = Dir;
exports.RtlModule = RtlModule;
exports.Portal = Portal;
exports.BasePortalHost = BasePortalHost;
exports.ComponentPortal = ComponentPortal;
exports.TemplatePortal = TemplatePortal;
exports.PortalHostDirective = PortalHostDirective;
exports.TemplatePortalDirective = TemplatePortalDirective;
exports.PortalModule = PortalModule;
exports.DomPortalHost = DomPortalHost;
exports.Overlay = Overlay;
exports.OVERLAY_PROVIDERS = OVERLAY_PROVIDERS;
exports.OverlayContainer = OverlayContainer;
exports.OverlayRef = OverlayRef;
exports.OverlayState = OverlayState;
exports.ConnectedOverlayDirective = ConnectedOverlayDirective;
exports.OverlayOrigin = OverlayOrigin;
exports.OverlayModule = OverlayModule;
exports.MdGestureConfig = MdGestureConfig;
exports.MdRipple = MdRipple;
exports.MdRippleModule = MdRippleModule;
exports.MdLiveAnnouncer = MdLiveAnnouncer;
exports.LIVE_ANNOUNCER_ELEMENT_TOKEN = LIVE_ANNOUNCER_ELEMENT_TOKEN;
exports.MdUniqueSelectionDispatcher = MdUniqueSelectionDispatcher;
exports.MdLineModule = MdLineModule;
exports.MdLine = MdLine;
exports.MdLineSetter = MdLineSetter;
exports.applyCssTransform = applyCssTransform$1;
exports.MdError = MdError;
exports.BooleanFieldValue = booleanFieldValueFactory;
exports.ConnectedPositionStrategy = ConnectedPositionStrategy;
exports.ConnectionPositionPair = ConnectionPositionPair;
exports.UP_ARROW = UP_ARROW;
exports.DOWN_ARROW = DOWN_ARROW;
exports.RIGHT_ARROW = RIGHT_ARROW;
exports.LEFT_ARROW = LEFT_ARROW;
exports.ENTER = ENTER;
exports.TAB = TAB;
Object.defineProperty(exports, '__esModule', { value: true });
})));