// ======================================================================== // SproutCore // copyright 2006-2008 Sprout Systems, Inc. // ======================================================================== require('views/view') ; require('views/container') ; /** @class Manages the panels on a page. To make a view into a panel, just set the isPanel property on it. To customize how panels are shown in your application, override the showPanel() and hidePanel() methods. @extends SC.View */ SC.PanelView = SC.View.extend( /** @scope SC.PanelView.prototype */ { emptyElement: '
', // Override this property to incldue an example view all panels // will be wrapped in. The view must have a 'content' property that will // be set to the view to show. wrapperView: SC.ContainerView.extend({ emptyElement: '
', outlets: ['rootView'], rootView: SC.View.outletFor('.root?') }), // this is filled with instances of the the wrapperView so we don't have // to recreate them all the time. _wrapperPool: null, // this is used to get a new wrapper. _getWrapperView: function() { var ret = this._wrapperPool.pop() ; if (ret) return ret ; ret = this.wrapperView.viewFor() ; if (ret.visibleAnimation) { var va = Object.clone(ret.visibleAnimation) ; va.onComplete = this.hidePanelDidComplete.bind(this) ; ret.visibleAnimation = va ; } return ret ; }, // ................................... // SHOWING AND HIDING VIEWS // locationFor: function(view,evt) { return { top: '50px', left: 'auto' } ; }, // this is the method called by the view to show itself as a popup. showPanel: function(view,evt) { var wrapperView = this._getWrapperView() ; // setup popupView. wrapperView.set('animateVisible',false) ; wrapperView.set('isVisible',false) ; wrapperView.set('content',view) ; // set the popup view. wrapperView.setClassName('standard-panel', !(view.get('hasCustomPanelWrapper') || false)); view._wrapperView = wrapperView ; // The dimensions of the panel cannot be computed until it is actually // added to the document. Turn off animation and add view with visiblity // set to hidden so we can get dimensions. this.nowShowing.push(view) ; this.appendChild(wrapperView) ; this.set('isVisible',true) ; // show panels wrapperView.setStyle({ visibility: 'hidden' }) ; wrapperView.set('isVisible',true) ; // show the panel var dim = Element.getDimensions(view.rootElement) ; wrapperView.setStyle(this.locationFor(view,evt)) ; wrapperView.set('isVisible',false) ; wrapperView.setStyle({ width: dim.width+'px', visibility: 'visible' }); wrapperView.set('animateVisible',true); wrapperView.set('isVisible',true) ; }, hidePanel: function(view) { var didHideWrapperView = null ; // clear view if (view._wrapperView) { if (view._wrapperView.visibleAnimation) { } else { didHideWrapperView = view._wrapperView ; } view._wrapperView.set('isVisible',false) ; view._wrapperView = null ; } // now remove from list of popups and hide pane (maybe) this.nowShowing = this.nowShowing.without(view) ; if (didHideWrapperView) this.hidePanelDidComplete(didHideWrapperView) ; }, hidePanelDidComplete: function(wrapperView) { if (wrapperView.get('isVisible') != false) return ; if (wrapperView) { wrapperView.set('content',null) ; this._wrapperPool.push(wrapperView) ; } if (this.nowShowing.length <= 0) this.set('isVisible',false); }, init: function() { arguments.callee.base.call(this) ; this.nowShowing = [] ; this._wrapperPool = [] ; }, // ................................... // SHOWING AND HIDING THE POPUP PANEL // panelStyle: { zIndex: '10000', visibility: 'visible', position: 'absolute', top: '0', left: '0', width: '100%', height: '100%', overflow: 'hidden' }, showView: function() { // add panel to body node if it has not been added already. var bodyNode = $tag('body'); if (this.rootElement.parentNode != bodyNode) bodyNode.appendChild(this.rootElement) ; this.setStyle(this.panelStyle) ; if (!SC.isIE7() && bodyNode) Element.addClassName(bodyNode, 'under-panel') ; }, hideView: function() { var bodyNode = $tag('body'); this.setStyle({ zIndex: '-10000', visibility: 'hidden' }) ; if (!SC.isIE7() && bodyNode) Element.removeClassName(bodyNode, 'under-panel') ; }, // if the user clicks outside the top popup, then dismiss the popup unless // it is modal. didClick: function(ev) { if (this.nowShowing.length == 0) return ; // nothing to do. // find the top-most popup var topPanel = this.nowShowing[this.nowShowing.length-1] ; var tgt = Event.element(ev) ; var tgtView = $view(tgt) ; var view = topPanel._wrapperView ; while(tgt && (tgt != this.rootElement) && (tgtView != view)) { tgt = tgt.parentNode ; tgtView = (tgt) ? $view(tgt) : null ; } // may dismiss if clicked outside of topPopup and isModal == false if ((tgtView != view) && (!topPanel.get('isModal'))) { topPanel.set('isVisible',false) ; } } }) ; SC.callOnLoad(function() { if (!SC.page) SC.page = SC.Page.create() ; SC.page.panels = SC.PanelView.outletFor(null); }) ;