Path: blob/trunk/third_party/closure/goog/positioning/anchoredviewportposition.js
2868 views
// Copyright 2006 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Anchored viewport positioning class.16*17* @author [email protected] (Emil A Eklund)18*/1920goog.provide('goog.positioning.AnchoredViewportPosition');2122goog.require('goog.positioning');23goog.require('goog.positioning.AnchoredPosition');24goog.require('goog.positioning.Overflow');25goog.require('goog.positioning.OverflowStatus');26272829/**30* Encapsulates a popup position where the popup is anchored at a corner of31* an element. The corners are swapped if dictated by the viewport. For instance32* if a popup is anchored with its top left corner to the bottom left corner of33* the anchor the popup is either displayed below the anchor (as specified) or34* above it if there's not enough room to display it below.35*36* When using this positioning object it's recommended that the movable element37* be absolutely positioned.38*39* @param {Element} anchorElement Element the movable element should be40* anchored against.41* @param {goog.positioning.Corner} corner Corner of anchored element the42* movable element should be positioned at.43* @param {boolean=} opt_adjust Whether the positioning should be adjusted until44* the element fits inside the viewport even if that means that the anchored45* corners are ignored.46* @param {goog.math.Box=} opt_overflowConstraint Box object describing the47* dimensions in which the movable element could be shown.48* @constructor49* @extends {goog.positioning.AnchoredPosition}50*/51goog.positioning.AnchoredViewportPosition = function(52anchorElement, corner, opt_adjust, opt_overflowConstraint) {53goog.positioning.AnchoredPosition.call(this, anchorElement, corner);5455/**56* The last resort algorithm to use if the algorithm can't fit inside57* the viewport.58*59* IGNORE = do nothing, just display at the preferred position.60*61* ADJUST_X | ADJUST_Y = Adjust until the element fits, even if that means62* that the anchored corners are ignored.63*64* @type {number}65* @private66*/67this.lastResortOverflow_ = opt_adjust ? (goog.positioning.Overflow.ADJUST_X |68goog.positioning.Overflow.ADJUST_Y) :69goog.positioning.Overflow.IGNORE;7071/**72* The dimensions in which the movable element could be shown.73* @type {goog.math.Box|undefined}74* @private75*/76this.overflowConstraint_ = opt_overflowConstraint || undefined;77};78goog.inherits(79goog.positioning.AnchoredViewportPosition,80goog.positioning.AnchoredPosition);818283/**84* @return {goog.math.Box|undefined} The box object describing the85* dimensions in which the movable element will be shown.86*/87goog.positioning.AnchoredViewportPosition.prototype.getOverflowConstraint =88function() {89return this.overflowConstraint_;90};919293/**94* @param {goog.math.Box|undefined} overflowConstraint Box object describing the95* dimensions in which the movable element could be shown.96*/97goog.positioning.AnchoredViewportPosition.prototype.setOverflowConstraint =98function(overflowConstraint) {99this.overflowConstraint_ = overflowConstraint;100};101102103/**104* @return {number} A bitmask for the "last resort" overflow.105*/106goog.positioning.AnchoredViewportPosition.prototype.getLastResortOverflow =107function() {108return this.lastResortOverflow_;109};110111112/**113* @param {number} lastResortOverflow A bitmask for the "last resort" overflow,114* if we fail to fit the element on-screen.115*/116goog.positioning.AnchoredViewportPosition.prototype.setLastResortOverflow =117function(lastResortOverflow) {118this.lastResortOverflow_ = lastResortOverflow;119};120121122/**123* Repositions the movable element.124*125* @param {Element} movableElement Element to position.126* @param {goog.positioning.Corner} movableCorner Corner of the movable element127* that should be positioned adjacent to the anchored element.128* @param {goog.math.Box=} opt_margin A margin specified in pixels.129* @param {goog.math.Size=} opt_preferredSize The preferred size of the130* movableElement.131* @override132*/133goog.positioning.AnchoredViewportPosition.prototype.reposition = function(134movableElement, movableCorner, opt_margin, opt_preferredSize) {135var status = goog.positioning.positionAtAnchor(136this.element, this.corner, movableElement, movableCorner, null,137opt_margin,138goog.positioning.Overflow.FAIL_X | goog.positioning.Overflow.FAIL_Y,139opt_preferredSize, this.overflowConstraint_);140141// If the desired position is outside the viewport try mirroring the corners142// horizontally or vertically.143if (status & goog.positioning.OverflowStatus.FAILED) {144var cornerFallback = this.adjustCorner(status, this.corner);145var movableCornerFallback = this.adjustCorner(status, movableCorner);146147status = goog.positioning.positionAtAnchor(148this.element, cornerFallback, movableElement, movableCornerFallback,149null, opt_margin,150goog.positioning.Overflow.FAIL_X | goog.positioning.Overflow.FAIL_Y,151opt_preferredSize, this.overflowConstraint_);152153if (status & goog.positioning.OverflowStatus.FAILED) {154// If that also fails, pick the best corner from the two tries,155// and adjust the position until it fits.156cornerFallback = this.adjustCorner(status, cornerFallback);157movableCornerFallback = this.adjustCorner(status, movableCornerFallback);158159goog.positioning.positionAtAnchor(160this.element, cornerFallback, movableElement, movableCornerFallback,161null, opt_margin, this.getLastResortOverflow(), opt_preferredSize,162this.overflowConstraint_);163}164}165};166167168/**169* Adjusts the corner if X or Y positioning failed.170* @param {number} status The status of the last positionAtAnchor call.171* @param {goog.positioning.Corner} corner The corner to adjust.172* @return {goog.positioning.Corner} The adjusted corner.173* @protected174*/175goog.positioning.AnchoredViewportPosition.prototype.adjustCorner = function(176status, corner) {177if (status & goog.positioning.OverflowStatus.FAILED_HORIZONTAL) {178corner = goog.positioning.flipCornerHorizontal(corner);179}180181if (status & goog.positioning.OverflowStatus.FAILED_VERTICAL) {182corner = goog.positioning.flipCornerVertical(corner);183}184185return corner;186};187188189