UNPKG

md2

Version:

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

169 lines 8.49 kB
import { RippleRef, RippleState } from './ripple-ref'; /** Fade-in duration for the ripples. Can be modified with the speedFactor option. */ export var RIPPLE_FADE_IN_DURATION = 450; /** Fade-out duration for the ripples in milliseconds. This can't be modified by the speedFactor. */ export 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 = 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 = 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 = RippleState.FADING_OUT; // Once the ripple faded out, the ripple can be safely removed from the DOM. this.runTimeoutOutsideZone(function () { rippleRef.state = 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 === 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; }()); export { 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); } //# sourceMappingURL=ripple-renderer.js.map