| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- /**
- * @license
- * Copyright 2018 Google Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- import { __assign, __extends, __values } from "tslib";
- import { MDCFoundation } from '@material/base/foundation';
- import { Corner, CornerBit, cssClasses, numbers, strings } from './constants';
- /** MDC Menu Surface Foundation */
- var MDCMenuSurfaceFoundation = /** @class */ (function (_super) {
- __extends(MDCMenuSurfaceFoundation, _super);
- function MDCMenuSurfaceFoundation(adapter) {
- var _this = _super.call(this, __assign(__assign({}, MDCMenuSurfaceFoundation.defaultAdapter), adapter)) || this;
- _this.isSurfaceOpen = false;
- _this.isQuickOpen = false;
- _this.isHoistedElement = false;
- _this.isFixedPosition = false;
- _this.isHorizontallyCenteredOnViewport = false;
- _this.maxHeight = 0;
- _this.openBottomBias = 0;
- _this.openAnimationEndTimerId = 0;
- _this.closeAnimationEndTimerId = 0;
- _this.animationRequestId = 0;
- _this.anchorCorner = Corner.TOP_START;
- /**
- * Corner of the menu surface to which menu surface is attached to anchor.
- *
- * Anchor corner --->+----------+
- * | ANCHOR |
- * +----------+
- * Origin corner --->+--------------+
- * | |
- * | |
- * | MENU SURFACE |
- * | |
- * | |
- * +--------------+
- */
- _this.originCorner = Corner.TOP_START;
- _this.anchorMargin = { top: 0, right: 0, bottom: 0, left: 0 };
- _this.position = { x: 0, y: 0 };
- return _this;
- }
- Object.defineProperty(MDCMenuSurfaceFoundation, "cssClasses", {
- get: function () {
- return cssClasses;
- },
- enumerable: false,
- configurable: true
- });
- Object.defineProperty(MDCMenuSurfaceFoundation, "strings", {
- get: function () {
- return strings;
- },
- enumerable: false,
- configurable: true
- });
- Object.defineProperty(MDCMenuSurfaceFoundation, "numbers", {
- get: function () {
- return numbers;
- },
- enumerable: false,
- configurable: true
- });
- Object.defineProperty(MDCMenuSurfaceFoundation, "Corner", {
- get: function () {
- return Corner;
- },
- enumerable: false,
- configurable: true
- });
- Object.defineProperty(MDCMenuSurfaceFoundation, "defaultAdapter", {
- /**
- * @see {@link MDCMenuSurfaceAdapter} for typing information on parameters and return types.
- */
- get: function () {
- // tslint:disable:object-literal-sort-keys Methods should be in the same order as the adapter interface.
- return {
- addClass: function () { return undefined; },
- removeClass: function () { return undefined; },
- hasClass: function () { return false; },
- hasAnchor: function () { return false; },
- isElementInContainer: function () { return false; },
- isFocused: function () { return false; },
- isRtl: function () { return false; },
- getInnerDimensions: function () { return ({ height: 0, width: 0 }); },
- getAnchorDimensions: function () { return null; },
- getViewportDimensions: function () { return ({ height: 0, width: 0 }); },
- getBodyDimensions: function () { return ({ height: 0, width: 0 }); },
- getWindowScroll: function () { return ({ x: 0, y: 0 }); },
- setPosition: function () { return undefined; },
- setMaxHeight: function () { return undefined; },
- setTransformOrigin: function () { return undefined; },
- saveFocus: function () { return undefined; },
- restoreFocus: function () { return undefined; },
- notifyClose: function () { return undefined; },
- notifyClosing: function () { return undefined; },
- notifyOpen: function () { return undefined; },
- notifyOpening: function () { return undefined; },
- registerWindowEventHandler: function () { return undefined; },
- deregisterWindowEventHandler: function () { return undefined; },
- };
- // tslint:enable:object-literal-sort-keys
- },
- enumerable: false,
- configurable: true
- });
- MDCMenuSurfaceFoundation.prototype.init = function () {
- var _a = MDCMenuSurfaceFoundation.cssClasses, ROOT = _a.ROOT, OPEN = _a.OPEN;
- if (!this.adapter.hasClass(ROOT)) {
- throw new Error(ROOT + " class required in root element.");
- }
- if (this.adapter.hasClass(OPEN)) {
- this.isSurfaceOpen = true;
- }
- this.resizeListener = this.handleResize.bind(this);
- this.adapter.registerWindowEventHandler('resize', this.resizeListener);
- };
- MDCMenuSurfaceFoundation.prototype.destroy = function () {
- clearTimeout(this.openAnimationEndTimerId);
- clearTimeout(this.closeAnimationEndTimerId);
- // Cancel any currently running animations.
- cancelAnimationFrame(this.animationRequestId);
- this.adapter.deregisterWindowEventHandler('resize', this.resizeListener);
- };
- /**
- * @param corner Default anchor corner alignment of top-left menu surface
- * corner.
- */
- MDCMenuSurfaceFoundation.prototype.setAnchorCorner = function (corner) {
- this.anchorCorner = corner;
- };
- /**
- * Flip menu corner horizontally.
- */
- MDCMenuSurfaceFoundation.prototype.flipCornerHorizontally = function () {
- this.originCorner = this.originCorner ^ CornerBit.RIGHT;
- };
- /**
- * @param margin Set of margin values from anchor.
- */
- MDCMenuSurfaceFoundation.prototype.setAnchorMargin = function (margin) {
- this.anchorMargin.top = margin.top || 0;
- this.anchorMargin.right = margin.right || 0;
- this.anchorMargin.bottom = margin.bottom || 0;
- this.anchorMargin.left = margin.left || 0;
- };
- /** Used to indicate if the menu-surface is hoisted to the body. */
- MDCMenuSurfaceFoundation.prototype.setIsHoisted = function (isHoisted) {
- this.isHoistedElement = isHoisted;
- };
- /**
- * Used to set the menu-surface calculations based on a fixed position menu.
- */
- MDCMenuSurfaceFoundation.prototype.setFixedPosition = function (isFixedPosition) {
- this.isFixedPosition = isFixedPosition;
- };
- /**
- * @return Returns true if menu is in fixed (`position: fixed`) position.
- */
- MDCMenuSurfaceFoundation.prototype.isFixed = function () {
- return this.isFixedPosition;
- };
- /** Sets the menu-surface position on the page. */
- MDCMenuSurfaceFoundation.prototype.setAbsolutePosition = function (x, y) {
- this.position.x = this.isFinite(x) ? x : 0;
- this.position.y = this.isFinite(y) ? y : 0;
- };
- /** Sets whether menu-surface should be horizontally centered to viewport. */
- MDCMenuSurfaceFoundation.prototype.setIsHorizontallyCenteredOnViewport = function (isCentered) {
- this.isHorizontallyCenteredOnViewport = isCentered;
- };
- MDCMenuSurfaceFoundation.prototype.setQuickOpen = function (quickOpen) {
- this.isQuickOpen = quickOpen;
- };
- /**
- * Sets maximum menu-surface height on open.
- * @param maxHeight The desired max-height. Set to 0 (default) to
- * automatically calculate max height based on available viewport space.
- */
- MDCMenuSurfaceFoundation.prototype.setMaxHeight = function (maxHeight) {
- this.maxHeight = maxHeight;
- };
- /**
- * Set to a positive integer to influence the menu to preferentially open
- * below the anchor instead of above.
- * @param bias A value of `x` simulates an extra `x` pixels of available space
- * below the menu during positioning calculations.
- */
- MDCMenuSurfaceFoundation.prototype.setOpenBottomBias = function (bias) {
- this.openBottomBias = bias;
- };
- MDCMenuSurfaceFoundation.prototype.isOpen = function () {
- return this.isSurfaceOpen;
- };
- /**
- * Open the menu surface.
- */
- MDCMenuSurfaceFoundation.prototype.open = function () {
- var _this = this;
- if (this.isSurfaceOpen) {
- return;
- }
- this.adapter.notifyOpening();
- this.adapter.saveFocus();
- if (this.isQuickOpen) {
- this.isSurfaceOpen = true;
- this.adapter.addClass(MDCMenuSurfaceFoundation.cssClasses.OPEN);
- this.dimensions = this.adapter.getInnerDimensions();
- this.autoposition();
- this.adapter.notifyOpen();
- }
- else {
- this.adapter.addClass(MDCMenuSurfaceFoundation.cssClasses.ANIMATING_OPEN);
- this.animationRequestId = requestAnimationFrame(function () {
- _this.dimensions = _this.adapter.getInnerDimensions();
- _this.autoposition();
- _this.adapter.addClass(MDCMenuSurfaceFoundation.cssClasses.OPEN);
- _this.openAnimationEndTimerId = setTimeout(function () {
- _this.openAnimationEndTimerId = 0;
- _this.adapter.removeClass(MDCMenuSurfaceFoundation.cssClasses.ANIMATING_OPEN);
- _this.adapter.notifyOpen();
- }, numbers.TRANSITION_OPEN_DURATION);
- });
- this.isSurfaceOpen = true;
- }
- this.adapter.registerWindowEventHandler('resize', this.resizeListener);
- };
- /**
- * Closes the menu surface.
- */
- MDCMenuSurfaceFoundation.prototype.close = function (skipRestoreFocus) {
- var _this = this;
- if (skipRestoreFocus === void 0) { skipRestoreFocus = false; }
- if (!this.isSurfaceOpen) {
- return;
- }
- this.adapter.notifyClosing();
- this.adapter.deregisterWindowEventHandler('resize', this.resizeListener);
- if (this.isQuickOpen) {
- this.isSurfaceOpen = false;
- if (!skipRestoreFocus) {
- this.maybeRestoreFocus();
- }
- this.adapter.removeClass(MDCMenuSurfaceFoundation.cssClasses.OPEN);
- this.adapter.removeClass(MDCMenuSurfaceFoundation.cssClasses.IS_OPEN_BELOW);
- this.adapter.notifyClose();
- return;
- }
- this.adapter.addClass(MDCMenuSurfaceFoundation.cssClasses.ANIMATING_CLOSED);
- requestAnimationFrame(function () {
- _this.adapter.removeClass(MDCMenuSurfaceFoundation.cssClasses.OPEN);
- _this.adapter.removeClass(MDCMenuSurfaceFoundation.cssClasses.IS_OPEN_BELOW);
- _this.closeAnimationEndTimerId = setTimeout(function () {
- _this.closeAnimationEndTimerId = 0;
- _this.adapter.removeClass(MDCMenuSurfaceFoundation.cssClasses.ANIMATING_CLOSED);
- _this.adapter.notifyClose();
- }, numbers.TRANSITION_CLOSE_DURATION);
- });
- this.isSurfaceOpen = false;
- if (!skipRestoreFocus) {
- this.maybeRestoreFocus();
- }
- };
- /** Handle clicks and close if not within menu-surface element. */
- MDCMenuSurfaceFoundation.prototype.handleBodyClick = function (evt) {
- var el = evt.target;
- if (this.adapter.isElementInContainer(el)) {
- return;
- }
- this.close();
- };
- /** Handle keys that close the surface. */
- MDCMenuSurfaceFoundation.prototype.handleKeydown = function (evt) {
- var keyCode = evt.keyCode, key = evt.key;
- var isEscape = key === 'Escape' || keyCode === 27;
- if (isEscape) {
- this.close();
- }
- };
- /** Handles resize events on the window. */
- MDCMenuSurfaceFoundation.prototype.handleResize = function () {
- this.dimensions = this.adapter.getInnerDimensions();
- this.autoposition();
- };
- MDCMenuSurfaceFoundation.prototype.autoposition = function () {
- var _a;
- // Compute measurements for autoposition methods reuse.
- this.measurements = this.getAutoLayoutmeasurements();
- var corner = this.getoriginCorner();
- var maxMenuSurfaceHeight = this.getMenuSurfaceMaxHeight(corner);
- var verticalAlignment = this.hasBit(corner, CornerBit.BOTTOM) ? 'bottom' : 'top';
- var horizontalAlignment = this.hasBit(corner, CornerBit.RIGHT) ? 'right' : 'left';
- var horizontalOffset = this.getHorizontalOriginOffset(corner);
- var verticalOffset = this.getVerticalOriginOffset(corner);
- var _b = this.measurements, anchorSize = _b.anchorSize, surfaceSize = _b.surfaceSize;
- var position = (_a = {},
- _a[horizontalAlignment] = horizontalOffset,
- _a[verticalAlignment] = verticalOffset,
- _a);
- // Center align when anchor width is comparable or greater than menu
- // surface, otherwise keep corner.
- if (anchorSize.width / surfaceSize.width >
- numbers.ANCHOR_TO_MENU_SURFACE_WIDTH_RATIO) {
- horizontalAlignment = 'center';
- }
- // If the menu-surface has been hoisted to the body, it's no longer relative
- // to the anchor element
- if (this.isHoistedElement || this.isFixedPosition) {
- this.adjustPositionForHoistedElement(position);
- }
- this.adapter.setTransformOrigin(horizontalAlignment + " " + verticalAlignment);
- this.adapter.setPosition(position);
- this.adapter.setMaxHeight(maxMenuSurfaceHeight ? maxMenuSurfaceHeight + 'px' : '');
- // If it is opened from the top then add is-open-below class
- if (!this.hasBit(corner, CornerBit.BOTTOM)) {
- this.adapter.addClass(MDCMenuSurfaceFoundation.cssClasses.IS_OPEN_BELOW);
- }
- };
- /**
- * @return Measurements used to position menu surface popup.
- */
- MDCMenuSurfaceFoundation.prototype.getAutoLayoutmeasurements = function () {
- var anchorRect = this.adapter.getAnchorDimensions();
- var bodySize = this.adapter.getBodyDimensions();
- var viewportSize = this.adapter.getViewportDimensions();
- var windowScroll = this.adapter.getWindowScroll();
- if (!anchorRect) {
- // tslint:disable:object-literal-sort-keys Positional properties are more readable when they're grouped together
- anchorRect = {
- top: this.position.y,
- right: this.position.x,
- bottom: this.position.y,
- left: this.position.x,
- width: 0,
- height: 0,
- };
- // tslint:enable:object-literal-sort-keys
- }
- return {
- anchorSize: anchorRect,
- bodySize: bodySize,
- surfaceSize: this.dimensions,
- viewportDistance: {
- // tslint:disable:object-literal-sort-keys Positional properties are more readable when they're grouped together
- top: anchorRect.top,
- right: viewportSize.width - anchorRect.right,
- bottom: viewportSize.height - anchorRect.bottom,
- left: anchorRect.left,
- // tslint:enable:object-literal-sort-keys
- },
- viewportSize: viewportSize,
- windowScroll: windowScroll,
- };
- };
- /**
- * Computes the corner of the anchor from which to animate and position the
- * menu surface.
- *
- * Only LEFT or RIGHT bit is used to position the menu surface ignoring RTL
- * context. E.g., menu surface will be positioned from right side on TOP_END.
- */
- MDCMenuSurfaceFoundation.prototype.getoriginCorner = function () {
- var corner = this.originCorner;
- var _a = this.measurements, viewportDistance = _a.viewportDistance, anchorSize = _a.anchorSize, surfaceSize = _a.surfaceSize;
- var MARGIN_TO_EDGE = MDCMenuSurfaceFoundation.numbers.MARGIN_TO_EDGE;
- var isAnchoredToBottom = this.hasBit(this.anchorCorner, CornerBit.BOTTOM);
- var availableTop;
- var availableBottom;
- if (isAnchoredToBottom) {
- availableTop =
- viewportDistance.top - MARGIN_TO_EDGE + this.anchorMargin.bottom;
- availableBottom =
- viewportDistance.bottom - MARGIN_TO_EDGE - this.anchorMargin.bottom;
- }
- else {
- availableTop =
- viewportDistance.top - MARGIN_TO_EDGE + this.anchorMargin.top;
- availableBottom = viewportDistance.bottom - MARGIN_TO_EDGE +
- anchorSize.height - this.anchorMargin.top;
- }
- var isAvailableBottom = availableBottom - surfaceSize.height > 0;
- if (!isAvailableBottom &&
- availableTop > availableBottom + this.openBottomBias) {
- // Attach bottom side of surface to the anchor.
- corner = this.setBit(corner, CornerBit.BOTTOM);
- }
- var isRtl = this.adapter.isRtl();
- var isFlipRtl = this.hasBit(this.anchorCorner, CornerBit.FLIP_RTL);
- var hasRightBit = this.hasBit(this.anchorCorner, CornerBit.RIGHT) ||
- this.hasBit(corner, CornerBit.RIGHT);
- // Whether surface attached to right side of anchor element.
- var isAnchoredToRight = false;
- // Anchored to start
- if (isRtl && isFlipRtl) {
- isAnchoredToRight = !hasRightBit;
- }
- else {
- // Anchored to right
- isAnchoredToRight = hasRightBit;
- }
- var availableLeft;
- var availableRight;
- if (isAnchoredToRight) {
- availableLeft =
- viewportDistance.left + anchorSize.width + this.anchorMargin.left;
- availableRight = viewportDistance.right - this.anchorMargin.left;
- }
- else {
- availableLeft = viewportDistance.left + this.anchorMargin.left;
- availableRight =
- viewportDistance.right + anchorSize.width - this.anchorMargin.left;
- }
- var isAvailableLeft = availableLeft - surfaceSize.width > 0;
- var isAvailableRight = availableRight - surfaceSize.width > 0;
- var isOriginCornerAlignedToEnd = this.hasBit(corner, CornerBit.FLIP_RTL) &&
- this.hasBit(corner, CornerBit.RIGHT);
- if (isAvailableRight && isOriginCornerAlignedToEnd && isRtl ||
- !isAvailableLeft && isOriginCornerAlignedToEnd) {
- // Attach left side of surface to the anchor.
- corner = this.unsetBit(corner, CornerBit.RIGHT);
- }
- else if (isAvailableLeft && isAnchoredToRight && isRtl ||
- (isAvailableLeft && !isAnchoredToRight && hasRightBit) ||
- (!isAvailableRight && availableLeft >= availableRight)) {
- // Attach right side of surface to the anchor.
- corner = this.setBit(corner, CornerBit.RIGHT);
- }
- return corner;
- };
- /**
- * @param corner Origin corner of the menu surface.
- * @return Maximum height of the menu surface, based on available space. 0
- * indicates should not be set.
- */
- MDCMenuSurfaceFoundation.prototype.getMenuSurfaceMaxHeight = function (corner) {
- if (this.maxHeight > 0) {
- return this.maxHeight;
- }
- var viewportDistance = this.measurements.viewportDistance;
- var maxHeight = 0;
- var isBottomAligned = this.hasBit(corner, CornerBit.BOTTOM);
- var isBottomAnchored = this.hasBit(this.anchorCorner, CornerBit.BOTTOM);
- var MARGIN_TO_EDGE = MDCMenuSurfaceFoundation.numbers.MARGIN_TO_EDGE;
- // When maximum height is not specified, it is handled from CSS.
- if (isBottomAligned) {
- maxHeight = viewportDistance.top + this.anchorMargin.top - MARGIN_TO_EDGE;
- if (!isBottomAnchored) {
- maxHeight += this.measurements.anchorSize.height;
- }
- }
- else {
- maxHeight = viewportDistance.bottom - this.anchorMargin.bottom +
- this.measurements.anchorSize.height - MARGIN_TO_EDGE;
- if (isBottomAnchored) {
- maxHeight -= this.measurements.anchorSize.height;
- }
- }
- return maxHeight;
- };
- /**
- * @param corner Origin corner of the menu surface.
- * @return Horizontal offset of menu surface origin corner from corresponding
- * anchor corner.
- */
- MDCMenuSurfaceFoundation.prototype.getHorizontalOriginOffset = function (corner) {
- var anchorSize = this.measurements.anchorSize;
- // isRightAligned corresponds to using the 'right' property on the surface.
- var isRightAligned = this.hasBit(corner, CornerBit.RIGHT);
- var avoidHorizontalOverlap = this.hasBit(this.anchorCorner, CornerBit.RIGHT);
- if (isRightAligned) {
- var rightOffset = avoidHorizontalOverlap ?
- anchorSize.width - this.anchorMargin.left :
- this.anchorMargin.right;
- // For hoisted or fixed elements, adjust the offset by the difference
- // between viewport width and body width so when we calculate the right
- // value (`adjustPositionForHoistedElement`) based on the element
- // position, the right property is correct.
- if (this.isHoistedElement || this.isFixedPosition) {
- return rightOffset -
- (this.measurements.viewportSize.width -
- this.measurements.bodySize.width);
- }
- return rightOffset;
- }
- return avoidHorizontalOverlap ? anchorSize.width - this.anchorMargin.right :
- this.anchorMargin.left;
- };
- /**
- * @param corner Origin corner of the menu surface.
- * @return Vertical offset of menu surface origin corner from corresponding
- * anchor corner.
- */
- MDCMenuSurfaceFoundation.prototype.getVerticalOriginOffset = function (corner) {
- var anchorSize = this.measurements.anchorSize;
- var isBottomAligned = this.hasBit(corner, CornerBit.BOTTOM);
- var avoidVerticalOverlap = this.hasBit(this.anchorCorner, CornerBit.BOTTOM);
- var y = 0;
- if (isBottomAligned) {
- y = avoidVerticalOverlap ? anchorSize.height - this.anchorMargin.top :
- -this.anchorMargin.bottom;
- }
- else {
- y = avoidVerticalOverlap ?
- (anchorSize.height + this.anchorMargin.bottom) :
- this.anchorMargin.top;
- }
- return y;
- };
- /**
- * Calculates the offsets for positioning the menu-surface when the
- * menu-surface has been hoisted to the body.
- */
- MDCMenuSurfaceFoundation.prototype.adjustPositionForHoistedElement = function (position) {
- var e_1, _a;
- var _b = this.measurements, windowScroll = _b.windowScroll, viewportDistance = _b.viewportDistance, surfaceSize = _b.surfaceSize, viewportSize = _b.viewportSize;
- var props = Object.keys(position);
- try {
- for (var props_1 = __values(props), props_1_1 = props_1.next(); !props_1_1.done; props_1_1 = props_1.next()) {
- var prop = props_1_1.value;
- var value = position[prop] || 0;
- if (this.isHorizontallyCenteredOnViewport &&
- (prop === 'left' || prop === 'right')) {
- position[prop] = (viewportSize.width - surfaceSize.width) / 2;
- continue;
- }
- // Hoisted surfaces need to have the anchor elements location on the page
- // added to the position properties for proper alignment on the body.
- value += viewportDistance[prop];
- // Surfaces that are absolutely positioned need to have additional
- // calculations for scroll and bottom positioning.
- if (!this.isFixedPosition) {
- if (prop === 'top') {
- value += windowScroll.y;
- }
- else if (prop === 'bottom') {
- value -= windowScroll.y;
- }
- else if (prop === 'left') {
- value += windowScroll.x;
- }
- else { // prop === 'right'
- value -= windowScroll.x;
- }
- }
- position[prop] = value;
- }
- }
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
- finally {
- try {
- if (props_1_1 && !props_1_1.done && (_a = props_1.return)) _a.call(props_1);
- }
- finally { if (e_1) throw e_1.error; }
- }
- };
- /**
- * The last focused element when the menu surface was opened should regain
- * focus, if the user is focused on or within the menu surface when it is
- * closed.
- */
- MDCMenuSurfaceFoundation.prototype.maybeRestoreFocus = function () {
- var _this = this;
- var isRootFocused = this.adapter.isFocused();
- var ownerDocument = this.adapter.getOwnerDocument ?
- this.adapter.getOwnerDocument() :
- document;
- var childHasFocus = ownerDocument.activeElement &&
- this.adapter.isElementInContainer(ownerDocument.activeElement);
- if (isRootFocused || childHasFocus) {
- // Wait before restoring focus when closing the menu surface. This is
- // important because if a touch event triggered the menu close, and the
- // subsequent mouse event occurs after focus is restored, then the
- // restored focus would be lost.
- setTimeout(function () {
- _this.adapter.restoreFocus();
- }, numbers.TOUCH_EVENT_WAIT_MS);
- }
- };
- MDCMenuSurfaceFoundation.prototype.hasBit = function (corner, bit) {
- return Boolean(corner & bit); // tslint:disable-line:no-bitwise
- };
- MDCMenuSurfaceFoundation.prototype.setBit = function (corner, bit) {
- return corner | bit; // tslint:disable-line:no-bitwise
- };
- MDCMenuSurfaceFoundation.prototype.unsetBit = function (corner, bit) {
- return corner ^ bit;
- };
- /**
- * isFinite that doesn't force conversion to number type.
- * Equivalent to Number.isFinite in ES2015, which is not supported in IE.
- */
- MDCMenuSurfaceFoundation.prototype.isFinite = function (num) {
- return typeof num === 'number' && isFinite(num);
- };
- return MDCMenuSurfaceFoundation;
- }(MDCFoundation));
- export { MDCMenuSurfaceFoundation };
- // tslint:disable-next-line:no-default-export Needed for backward compatibility with MDC Web v0.44.0 and earlier.
- export default MDCMenuSurfaceFoundation;
- //# sourceMappingURL=foundation.js.map
|