// Name: AjaxControlToolkit.PopupExtender.PopupBehavior.debug.js // Assembly: AjaxControlToolkit // Version: 3.0.30930.28736 // FileVersion: 3.0.30930.0 // (c) Copyright Microsoft Corporation. // This source is subject to the Microsoft Public License. // See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL. // All other rights reserved. /// /// /// /// /// /// /// /// Type.registerNamespace('AjaxControlToolkit'); AjaxControlToolkit.PopupBehavior = function(element) { /// /// The PopupBehavior is used to show/hide an element at a position /// relative to another element /// /// /// The DOM element the behavior is associated with /// AjaxControlToolkit.PopupBehavior.initializeBase(this, [element]); this._x = 0; this._y = 0; this._positioningMode = AjaxControlToolkit.PositioningMode.Absolute; this._parentElement = null; this._parentElementID = null; this._moveHandler = null; this._firstPopup = true; this._originalParent = null; this._visible = false; this._onParentRepositionHandler = null; this._elementsWithAttachedRepositionHandlers = null; // Generic animation behaviors that automatically build animations // from JSON descriptions this._onShow = null; this._onShowEndedHandler = null; this._onHide = null; this._onHideEndedHandler = null; } AjaxControlToolkit.PopupBehavior.prototype = { initialize: function() { /// /// Initialize the PopupBehavior /// AjaxControlToolkit.PopupBehavior.callBaseMethod(this, 'initialize'); this._hidePopup(); this._prepareElement(); // Create handlers for the animation ended events this._onShowEndedHandler = Function.createDelegate(this, this._onShowEnded); this._onHideEndedHandler = Function.createDelegate(this, this._onHideEnded); }, dispose: function() { /// /// Dispose the PopupBehavior /// var element = this.get_element(); if (element) { if (this._visible) { this.hide(); } if (this._originalParent) { element.parentNode.removeChild(element); this._originalParent.appendChild(element); this._originalParent = null; } // Remove expando properties element._hideWindowedElementsIFrame = null; } this._parentElement = null; // Remove the animation ended events and wipe the animations // (we don't need to dispose them because that will happen // automatically in our base dispose) if (this._onShow && this._onShow.get_animation() && this._onShowEndedHandler) { this._onShow.get_animation().remove_ended(this._onShowEndedHandler); } this._onShowEndedHandler = null; this._onShow = null; if (this._onHide && this._onHide.get_animation() && this._onHideEndedHandler) { this._onHide.get_animation().remove_ended(this._onHideEndedHandler); } this._onHideEndedHandler = null; this._onHide = null; if (this._onParentRepositionHandler != null) { $removeHandler(window, 'resize', this._onParentRepositionHandler); } if (this._elementsWithAttachedRepositionHandlers != null) { for (var i = 0; i < this._elementsWithAttachedRepositionHandlers.length; i++) { $removeHandler(this._elementsWithAttachedRepositionHandlers[i], 'resize', this._onParentRepositionHandler); $removeHandler(this._elementsWithAttachedRepositionHandlers[i], 'scroll', this._onParentRepositionHandler); } this._elementsWithAttachedRepositionHandlers = null; } this._onParentRepositionHandler = null; AjaxControlToolkit.PopupBehavior.callBaseMethod(this, 'dispose'); }, _prepareElement: function() { /// /// Makes the element a child of the body element /// and attaches onscroll event handlers to synchronize the position /// of the popup with the position of the element /// var element = this.get_element(); this._onParentRepositionHandler = Function.createDelegate(this, this._reposition); this._elementsWithAttachedRepositionHandlers = new Array(); var parent = element.parentNode; while (parent) { if (parent == document.body) { break; } $addHandler(parent, 'scroll', this._onParentRepositionHandler); $addHandler(parent, 'resize', this._onParentRepositionHandler); this._elementsWithAttachedRepositionHandlers.push(parent); parent = parent.parentNode; } $addHandler(window, 'resize', this._onParentRepositionHandler); element.style.position = 'absolute'; $common.appendElementToFormOrBody(element); }, _reposition: function() { if (!this._visible) { return; } this.setupPopup(); }, show: function() { /// /// Show the popup /// // Ignore requests to hide multiple times if (this._visible) { return; } var eventArgs = new Sys.CancelEventArgs(); this.raiseShowing(eventArgs); if (eventArgs.get_cancel()) { return; } // Either show the popup or play an animation that does // (note: even if we're animating, we still show and position // the popup before hiding it again and playing the animation // which makes the animation much simpler) this._visible = true; var element = this.get_element(); $common.setVisible(element, true); this.setupPopup(); if (this._onShow) { $common.setVisible(element, false); this.onShow(); } else { this.raiseShown(Sys.EventArgs.Empty); } }, hide: function() { /// /// Hide the popup /// // Ignore requests to hide multiple times if (!this._visible) { return; } var eventArgs = new Sys.CancelEventArgs(); this.raiseHiding(eventArgs); if (eventArgs.get_cancel()) { return; } // Either hide the popup or play an animation that does this._visible = false; if (this._onHide) { this.onHide(); } else { this._hidePopup(); this._hideCleanup(); } }, getBounds: function() { /// /// Get the expected bounds of the popup relative to its parent /// /// /// Bounds of the popup relative to its parent /// /// /// The actual final position can only be calculated after it is /// initially set and we can verify it doesn't bleed off the edge /// of the screen. /// var element = this.get_element(); // offsetParent (doc element if absolutely positioned or no offsetparent available) var offsetParent = element.offsetParent || document.documentElement; // diff = difference in position between element's offsetParent and the element we will attach popup to. // this is basically so we can position the popup in the right spot even though it may not be absolutely positioned var diff; var parentBounds; if (this._parentElement) { // we will be positioning the element against the assigned parent parentBounds = $common.getBounds(this._parentElement); var offsetParentLocation = $common.getLocation(offsetParent); diff = { x: parentBounds.x - offsetParentLocation.x, y: parentBounds.y - offsetParentLocation.y }; } else { // we will be positioning the element against the offset parent by default, since no parent element given parentBounds = $common.getBounds(offsetParent); diff = { x: 0, y: 0 }; } // width/height of the element, needed for calculations that involve width like centering var width = element.offsetWidth - (element.clientLeft ? element.clientLeft * 2 : 0); var height = element.offsetHeight - (element.clientTop ? element.clientTop * 2 : 0); // Setting the width causes the element to grow by border+passing every // time. But not setting it causes strange behavior in safari. Just set it once. if (this._firstpopup) { element.style.width = width + "px"; this._firstpopup = false; } var position, pos; switch (this._positioningMode) { case AjaxControlToolkit.PositioningMode.Center: pos = { x: Math.round(parentBounds.width / 2 - width / 2), y: Math.round(parentBounds.height / 2 - height / 2), altX: Math.round(parentBounds.width / 2 - width / 2), altY: Math.round(parentBounds.height / 2 - height / 2) }; break; case AjaxControlToolkit.PositioningMode.BottomLeft: pos = { x: 0, y: parentBounds.height, altX: parentBounds.width - width, altY: 0 - height } break; case AjaxControlToolkit.PositioningMode.BottomRight: pos = { x: parentBounds.width - width, y: parentBounds.height, altX: 0, altY: 0 - height } break; case AjaxControlToolkit.PositioningMode.TopLeft: pos = { x: 0, y: -element.offsetHeight, altX: parentBounds.width - width, altY: parentBounds.height } break; case AjaxControlToolkit.PositioningMode.TopRight: pos = { x: parentBounds.width - width, y: -element.offsetHeight, altX: 0, altY: parentBounds.height } break; case AjaxControlToolkit.PositioningMode.Right: pos = { x: parentBounds.width, y: 0, altX: -element.offsetWidth, altY: parentBounds.height - height } break; case AjaxControlToolkit.PositioningMode.Left: pos = { x: -element.offsetWidth, y: 0, altX: parentBounds.width, altY: parentBounds.height - height } break; default: pos = { x: 0, y: 0, altX: 0, altY: 0 }; } pos.x += this._x + diff.x; pos.altX += this._x + diff.x; pos.y += this._y + diff.y; pos.altY += this._y + diff.y; position = this._verifyPosition(pos, width, height, parentBounds); return new Sys.UI.Bounds(position.x, position.y, width, height); }, _verifyPosition: function(pos, elementWidth, elementHeight, parentBounds) { /// /// Checks whether the popup is entirely visible and attempts to change its position to make it entirely visihle. /// var newX = 0, newY = 0; var windowBounds = this._getWindowBounds(); // Check horizontal positioning if (!((pos.x + elementWidth > windowBounds.x + windowBounds.width) || (pos.x < windowBounds.x))) { newX = pos.x; } else { newX = pos.altX; if (pos.altX < windowBounds.x) { if (pos.x > pos.altX) { newX = pos.x; } } else if (windowBounds.width + windowBounds.x - pos.altX < elementWidth) { var xDiff = pos.x > pos.altX ? Math.abs(windowBounds.x - pos.x) : (windowBounds.x - pos.x); if (xDiff < elementWidth - windowBounds.width - windowBounds.x + pos.altX) { newX = pos.x; } } } // Check vertical positioning if (!((pos.y + elementHeight > windowBounds.y + windowBounds.height) || (pos.y < windowBounds.y))) { newY = pos.y; } else { newY = pos.altY; if (pos.altY < windowBounds.y) { if (windowBounds.y - pos.altY > elementHeight - windowBounds.height - windowBounds.y + pos.y) { newY = pos.y; } } else if (windowBounds.height + windowBounds.y - pos.altY < elementHeight) { if (windowBounds.y - pos.y < elementHeight - windowBounds.height - windowBounds.y + pos.altY) { newY = pos.y; } } } return { x: newX, y: newY }; }, _getWindowBounds: function() { var bounds = { x: this._getWindowScrollLeft(), y: this._getWindowScrollTop(), width: this._getWindowWidth(), height: this._getWindowHeight() }; return bounds; }, _getWindowHeight: function() { var windowHeight = 0; if (document.documentElement && document.documentElement.clientHeight) { windowHeight = document.documentElement.clientHeight; } else if (document.body && document.body.clientHeight) { windowHeight = document.body.clientHeight; } return windowHeight; }, _getWindowWidth: function() { var windowWidth = 0; if (document.documentElement && document.documentElement.clientWidth) { windowWidth = document.documentElement.clientWidth; } else if (document.body && document.body.clientWidth) { windowWidth = document.body.clientWidth; } return windowWidth; }, _getWindowScrollTop: function() { var scrollTop = 0; if (typeof (window.pageYOffset) == 'number') { scrollTop = window.pageYOffset; } if (document.body && document.body.scrollTop) { scrollTop = document.body.scrollTop; } else if (document.documentElement && document.documentElement.scrollTop) { scrollTop = document.documentElement.scrollTop; } return scrollTop; }, _getWindowScrollLeft: function() { var scrollLeft = 0; if (typeof (window.pageXOffset) == 'number') { scrollLeft = window.pageXOffset; } else if (document.body && document.body.scrollLeft) { scrollLeft = document.body.scrollLeft; } else if (document.documentElement && document.documentElement.scrollLeft) { scrollLeft = document.documentElement.scrollLeft; } return scrollLeft; }, adjustPopupPosition: function(bounds) { /// /// Adjust the position of the popup after it's originally bet set /// to make sure that it's visible on the page. /// /// /// Original bounds of the parent element /// var element = this.get_element(); if (!bounds) { bounds = this.getBounds(); } // Get the new bounds now that we've shown the popup var newPosition = $common.getBounds(element); var updateNeeded = false; if (newPosition.x < 0) { bounds.x -= newPosition.x; updateNeeded = true; } if (newPosition.y < 0) { bounds.y -= newPosition.y; updateNeeded = true; } // If the popup was off the screen, reposition it if (updateNeeded) { $common.setLocation(element, bounds); } }, addBackgroundIFrame: function() { /// /// Add an empty IFRAME behind the popup (for IE6 only) so that SELECT, etc., won't /// show through the popup. /// // Get the child frame var element = this.get_element(); if ((Sys.Browser.agent === Sys.Browser.InternetExplorer) && (Sys.Browser.version < 7)) { var childFrame = element._hideWindowedElementsIFrame; // Create the child frame if it wasn't found if (!childFrame) { childFrame = document.createElement("iframe"); childFrame.src = "javascript:'';"; childFrame.style.position = "absolute"; childFrame.style.display = "none"; childFrame.scrolling = "no"; childFrame.frameBorder = "0"; childFrame.tabIndex = "-1"; childFrame.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"; element.parentNode.insertBefore(childFrame, element); element._hideWindowedElementsIFrame = childFrame; this._moveHandler = Function.createDelegate(this, this._onMove); Sys.UI.DomEvent.addHandler(element, "move", this._moveHandler); } // Position the frame exactly behind the element $common.setBounds(childFrame, $common.getBounds(element)); childFrame.style.left = element.style.left; childFrame.style.top = element.style.top; childFrame.style.display = element.style.display; if (element.currentStyle && element.currentStyle.zIndex) { childFrame.style.zIndex = element.currentStyle.zIndex; } else if (element.style.zIndex) { childFrame.style.zIndex = element.style.zIndex; } } }, setupPopup: function() { /// /// Position the popup relative to its parent /// var element = this.get_element(); var bounds = this.getBounds(); $common.setLocation(element, bounds); // Tweak the position, set the zIndex, and add the background iframe in IE6 this.adjustPopupPosition(bounds); element.style.zIndex = 1000; this.addBackgroundIFrame(); }, _hidePopup: function() { /// /// Internal hide implementation /// var element = this.get_element(); $common.setVisible(element, false); if (element.originalWidth) { element.style.width = element.originalWidth + "px"; element.originalWidth = null; } }, _hideCleanup: function() { /// /// Perform cleanup after hiding the element /// var element = this.get_element(); // Remove the tracking handler if (this._moveHandler) { Sys.UI.DomEvent.removeHandler(element, "move", this._moveHandler); this._moveHandler = null; } // Hide the child frame if (Sys.Browser.agent === Sys.Browser.InternetExplorer) { var childFrame = element._hideWindowedElementsIFrame; if (childFrame) { childFrame.style.display = "none"; } } this.raiseHidden(Sys.EventArgs.Empty); }, _onMove: function() { /// /// Track the popup's movements so the hidden IFrame (IE6 only) can /// be moved along with it /// var element = this.get_element(); if (element._hideWindowedElementsIFrame) { element.parentNode.insertBefore(element._hideWindowedElementsIFrame, element); element._hideWindowedElementsIFrame.style.top = element.style.top; element._hideWindowedElementsIFrame.style.left = element.style.left; } }, get_onShow: function() { /// /// Generic OnShow Animation's JSON definition /// return this._onShow ? this._onShow.get_json() : null; }, set_onShow: function(value) { if (!this._onShow) { this._onShow = new AjaxControlToolkit.Animation.GenericAnimationBehavior(this.get_element()); this._onShow.initialize(); } this._onShow.set_json(value); var animation = this._onShow.get_animation(); if (animation) { animation.add_ended(this._onShowEndedHandler); } this.raisePropertyChanged('onShow'); }, get_onShowBehavior: function() { /// /// Generic OnShow Animation's behavior /// return this._onShow; }, onShow: function() { /// /// Play the OnShow animation /// /// if (this._onShow) { if (this._onHide) { this._onHide.quit(); } this._onShow.play(); } }, _onShowEnded: function() { /// /// Handler for the OnShow Animation's Ended event /// // Make sure the popup is where it belongs this.adjustPopupPosition(); this.addBackgroundIFrame(); this.raiseShown(Sys.EventArgs.Empty); }, get_onHide: function() { /// /// Generic OnHide Animation's JSON definition /// return this._onHide ? this._onHide.get_json() : null; }, set_onHide: function(value) { if (!this._onHide) { this._onHide = new AjaxControlToolkit.Animation.GenericAnimationBehavior(this.get_element()); this._onHide.initialize(); } this._onHide.set_json(value); var animation = this._onHide.get_animation(); if (animation) { animation.add_ended(this._onHideEndedHandler); } this.raisePropertyChanged('onHide'); }, get_onHideBehavior: function() { /// /// Generic OnHide Animation's behavior /// return this._onHide; }, onHide: function() { /// /// Play the OnHide animation /// /// if (this._onHide) { if (this._onShow) { this._onShow.quit(); } this._onHide.play(); } }, _onHideEnded: function() { /// /// Handler for the OnHide Animation's Ended event /// this._hideCleanup(); }, get_parentElement: function() { /// /// Parent dom element. /// if (!this._parentElement && this._parentElementID) { this.set_parentElement($get(this._parentElementID)); Sys.Debug.assert(this._parentElement != null, String.format(AjaxControlToolkit.Resources.PopupExtender_NoParentElement, this._parentElementID)); } return this._parentElement; }, set_parentElement: function(element) { this._parentElement = element; this.raisePropertyChanged('parentElement'); }, get_parentElementID: function() { /// /// Parent dom element. /// if (this._parentElement) { return this._parentElement.id } return this._parentElementID; }, set_parentElementID: function(elementID) { this._parentElementID = elementID; if (this.get_isInitialized()) { this.set_parentElement($get(elementID)); } }, get_positioningMode: function() { /// /// Positioning mode. /// return this._positioningMode; }, set_positioningMode: function(mode) { this._positioningMode = mode; this.raisePropertyChanged('positioningMode'); }, get_x: function() { /// /// X coordinate. /// return this._x; }, set_x: function(value) { if (value != this._x) { this._x = value; // Reposition the popup if it's already showing if (this._visible) { this.setupPopup(); } this.raisePropertyChanged('x'); } }, get_y: function() { /// /// Y coordinate. /// return this._y; }, set_y: function(value) { if (value != this._y) { this._y = value; // Reposition the popup if it's already showing if (this._visible) { this.setupPopup(); } this.raisePropertyChanged('y'); } }, get_visible: function() { /// /// Whether or not the popup is currently visible /// return this._visible; }, add_showing: function(handler) { /// /// Add an event handler for the showing event /// /// /// Event handler /// /// this.get_events().addHandler('showing', handler); }, remove_showing: function(handler) { /// /// Remove an event handler from the showing event /// /// /// Event handler /// /// this.get_events().removeHandler('showing', handler); }, raiseShowing: function(eventArgs) { /// /// Raise the showing event /// /// /// Event arguments for the showing event /// /// var handler = this.get_events().getHandler('showing'); if (handler) { handler(this, eventArgs); } }, add_shown: function(handler) { /// /// Add an event handler for the shown event /// /// /// Event handler /// /// this.get_events().addHandler('shown', handler); }, remove_shown: function(handler) { /// /// Remove an event handler from the shown event /// /// /// Event handler /// /// this.get_events().removeHandler('shown', handler); }, raiseShown: function(eventArgs) { /// /// Raise the shown event /// /// /// Event arguments for the shown event /// /// var handler = this.get_events().getHandler('shown'); if (handler) { handler(this, eventArgs); } }, add_hiding: function(handler) { /// /// Add an event handler for the hiding event /// /// /// Event handler /// /// this.get_events().addHandler('hiding', handler); }, remove_hiding: function(handler) { /// /// Remove an event handler from the hiding event /// /// /// Event handler /// /// this.get_events().removeHandler('hiding', handler); }, raiseHiding: function(eventArgs) { /// /// Raise the hiding event /// /// /// Event arguments for the hiding event /// /// var handler = this.get_events().getHandler('hiding'); if (handler) { handler(this, eventArgs); } }, add_hidden: function(handler) { /// /// Add an event handler for the hidden event /// /// /// Event handler /// /// this.get_events().addHandler('hidden', handler); }, remove_hidden: function(handler) { /// /// Remove an event handler from the hidden event /// /// /// Event handler /// /// this.get_events().removeHandler('hidden', handler); }, raiseHidden: function(eventArgs) { /// /// Raise the hidden event /// /// /// Event arguments for the hidden event /// /// var handler = this.get_events().getHandler('hidden'); if (handler) { handler(this, eventArgs); } } } AjaxControlToolkit.PopupBehavior.registerClass('AjaxControlToolkit.PopupBehavior', AjaxControlToolkit.BehaviorBase); //AjaxControlToolkit.PopupBehavior.descriptor = { // properties: [ {name: 'parentElement', attributes: [ Sys.Attributes.Element, true ] }, // {name: 'positioningMode', type: AjaxControlToolkit.PositioningMode}, // {name: 'x', type: Number}, // {name: 'y', type: Number} ], // events: [ {name: 'show'}, // {name: 'hide'} ] //} AjaxControlToolkit.PositioningMode = function() { /// /// Positioning mode describing how the popup should be positioned /// relative to its specified parent /// /// /// /// /// /// /// /// /// throw Error.invalidOperation(); } AjaxControlToolkit.PositioningMode.prototype = { Absolute: 0, Center: 1, BottomLeft: 2, BottomRight: 3, TopLeft: 4, TopRight: 5, Right: 6, Left: 7 } AjaxControlToolkit.PositioningMode.registerEnum('AjaxControlToolkit.PositioningMode');