2 * Copyright 2010-2013 Ben Birch
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this software except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 var ui = app.ns("ui");
20 ui.AbstractPanel = ui.AbstractWidget.extend({
22 body: null, // initial content of the body
23 modal: true, // create a modal panel - creates a div that blocks interaction with page
24 height: 'auto', // panel height
25 width: 400, // panel width (in pixels)
26 open: false, // show the panel when it is created
27 parent: 'BODY', // node that panel is attached to
28 autoRemove: false // remove the panel from the dom and destroy it when the widget is closed
30 shared: { // shared data for all instances of ui.Panel and decendants
31 stack: [], // array of all open panels
32 modal: $( { tag: "DIV", id: "uiModal", css: { opacity: 0.2, position: "absolute", top: "0px", left: "0px" } } )
37 open: function( ev ) {
39 .css( { visibility: "hidden" } )
40 .appendTo( this.config.parent )
41 .css( this._getPosition( ev ) )
42 .css( { zIndex: (this.shared.stack.length ? (+this.shared.stack[this.shared.stack.length - 1].el.css("zIndex") + 10) : 100) } )
43 .css( { visibility: "visible", display: "block" } );
44 this.shared.stack.remove(this);
45 this.shared.stack.push(this);
47 $(document).bind("keyup", this._close_handler );
48 this.fire("open", { source: this, event: ev } );
52 var index = this.shared.stack.indexOf(this);
54 this.shared.stack.splice(index, 1);
55 this.el.css( { left: "-2999px" } ); // move the dialog to the left rather than hiding to prevent ie6 rendering artifacts
57 this.fire("close", this );
58 if(this.config.autoRemove) {
64 // close the panel and remove it from the dom, destroying it (you can not reuse the panel after calling remove)
67 $(document).unbind("keyup", this._close_handler );
70 // starting at the top of the stack, find the first panel that wants a modal and put it just underneath, otherwise remove the modal
71 _setModal: function() {
72 for(var stackPtr = this.shared.stack.length - 1; stackPtr >= 0; stackPtr--) {
73 if(this.shared.stack[stackPtr].config.modal) {
75 .appendTo( document.body )
76 .css( { zIndex: this.shared.stack[stackPtr].el.css("zIndex") - 5 } )
77 .css( $(document).vSize().asSize() );
81 this.shared.modal.remove(); // no panels that want a modal were found
83 _getPosition: function() {
84 return $(window).vSize() // get the current viewport size
85 .sub(this.el.vSize()) // subtract the size of the panel
86 .mod(function(s) { return s / 2; }) // divide by 2 (to center it)
87 .add($(document).vScroll()) // add the current scroll offset
88 .mod(function(s) { return Math.max(5, s); }) // make sure the panel is not off the edge of the window
89 .asOffset(); // and return it as a {top, left} object
91 _close_handler: function( ev ) {
92 if( ev.type === "keyup" && ev.keyCode !== 27) { return; } // press esc key to close
93 $(document).unbind("keyup", this._close_handler);
98 })( this.jQuery, this.app );