Path: blob/trunk/third_party/closure/goog/positioning/anchoredviewportposition.js
4206 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview Anchored viewport positioning class.8*/910goog.provide('goog.positioning.AnchoredViewportPosition');1112goog.require('goog.positioning');13goog.require('goog.positioning.AnchoredPosition');14goog.require('goog.positioning.Overflow');15goog.require('goog.positioning.OverflowStatus');16goog.requireType('goog.math.Box');17goog.requireType('goog.math.Size');18192021/**22* Encapsulates a popup position where the popup is anchored at a corner of23* an element. The corners are swapped if dictated by the viewport. For instance24* if a popup is anchored with its top left corner to the bottom left corner of25* the anchor the popup is either displayed below the anchor (as specified) or26* above it if there's not enough room to display it below.27*28* When using this positioning object it's recommended that the movable element29* be absolutely positioned.30*31* @param {Element} anchorElement Element the movable element should be32* anchored against.33* @param {goog.positioning.Corner} corner Corner of anchored element the34* movable element should be positioned at.35* @param {boolean=} opt_adjust Whether the positioning should be adjusted until36* the element fits inside the viewport even if that means that the anchored37* corners are ignored.38* @param {goog.math.Box=} opt_overflowConstraint Box object describing the39* dimensions in which the movable element could be shown.40* @constructor41* @extends {goog.positioning.AnchoredPosition}42*/43goog.positioning.AnchoredViewportPosition = function(44anchorElement, corner, opt_adjust, opt_overflowConstraint) {45'use strict';46goog.positioning.AnchoredPosition.call(this, anchorElement, corner);4748/**49* The last resort algorithm to use if the algorithm can't fit inside50* the viewport.51*52* IGNORE = do nothing, just display at the preferred position.53*54* ADJUST_X | ADJUST_Y = Adjust until the element fits, even if that means55* that the anchored corners are ignored.56*57* @type {number}58* @private59*/60this.lastResortOverflow_ = opt_adjust ? (goog.positioning.Overflow.ADJUST_X |61goog.positioning.Overflow.ADJUST_Y) :62goog.positioning.Overflow.IGNORE;6364/**65* The dimensions in which the movable element could be shown.66* @type {goog.math.Box|undefined}67* @private68*/69this.overflowConstraint_ = opt_overflowConstraint || undefined;70};71goog.inherits(72goog.positioning.AnchoredViewportPosition,73goog.positioning.AnchoredPosition);747576/**77* @return {goog.math.Box|undefined} The box object describing the78* dimensions in which the movable element will be shown.79*/80goog.positioning.AnchoredViewportPosition.prototype.getOverflowConstraint =81function() {82'use strict';83return this.overflowConstraint_;84};858687/**88* @param {goog.math.Box|undefined} overflowConstraint Box object describing the89* dimensions in which the movable element could be shown.90*/91goog.positioning.AnchoredViewportPosition.prototype.setOverflowConstraint =92function(overflowConstraint) {93'use strict';94this.overflowConstraint_ = overflowConstraint;95};969798/**99* @return {number} A bitmask for the "last resort" overflow.100*/101goog.positioning.AnchoredViewportPosition.prototype.getLastResortOverflow =102function() {103'use strict';104return this.lastResortOverflow_;105};106107108/**109* @param {number} lastResortOverflow A bitmask for the "last resort" overflow,110* if we fail to fit the element on-screen.111*/112goog.positioning.AnchoredViewportPosition.prototype.setLastResortOverflow =113function(lastResortOverflow) {114'use strict';115this.lastResortOverflow_ = lastResortOverflow;116};117118119/**120* Repositions the movable element.121*122* @param {Element} movableElement Element to position.123* @param {goog.positioning.Corner} movableCorner Corner of the movable element124* that should be positioned adjacent to the anchored element.125* @param {goog.math.Box=} opt_margin A margin specified in pixels.126* @param {goog.math.Size=} opt_preferredSize The preferred size of the127* movableElement.128* @override129*/130goog.positioning.AnchoredViewportPosition.prototype.reposition = function(131movableElement, movableCorner, opt_margin, opt_preferredSize) {132'use strict';133var status = goog.positioning.positionAtAnchor(134this.element, this.corner, movableElement, movableCorner, null,135opt_margin,136goog.positioning.Overflow.FAIL_X | goog.positioning.Overflow.FAIL_Y,137opt_preferredSize, this.overflowConstraint_);138139// If the desired position is outside the viewport try mirroring the corners140// horizontally or vertically.141if (status & goog.positioning.OverflowStatus.FAILED) {142var cornerFallback = this.adjustCorner(status, this.corner);143var movableCornerFallback = this.adjustCorner(status, movableCorner);144145status = goog.positioning.positionAtAnchor(146this.element, cornerFallback, movableElement, movableCornerFallback,147null, opt_margin,148goog.positioning.Overflow.FAIL_X | goog.positioning.Overflow.FAIL_Y,149opt_preferredSize, this.overflowConstraint_);150151if (status & goog.positioning.OverflowStatus.FAILED) {152// If that also fails, pick the best corner from the two tries,153// and adjust the position until it fits.154cornerFallback = this.adjustCorner(status, cornerFallback);155movableCornerFallback = this.adjustCorner(status, movableCornerFallback);156157goog.positioning.positionAtAnchor(158this.element, cornerFallback, movableElement, movableCornerFallback,159null, opt_margin, this.getLastResortOverflow(), opt_preferredSize,160this.overflowConstraint_);161}162}163};164165166/**167* Adjusts the corner if X or Y positioning failed.168* @param {number} status The status of the last positionAtAnchor call.169* @param {goog.positioning.Corner} corner The corner to adjust.170* @return {goog.positioning.Corner} The adjusted corner.171* @protected172*/173goog.positioning.AnchoredViewportPosition.prototype.adjustCorner = function(174status, corner) {175'use strict';176if (status & goog.positioning.OverflowStatus.FAILED_HORIZONTAL) {177corner = goog.positioning.flipCornerHorizontal(corner);178}179180if (status & goog.positioning.OverflowStatus.FAILED_VERTICAL) {181corner = goog.positioning.flipCornerVertical(corner);182}183184return corner;185};186187188