source: Dev/branches/rest-dojo-ui/client/dojox/layout/FloatingPane.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 11.4 KB
Line 
1define(["dojo/_base/kernel","dojo/_base/lang","dojo/_base/window","dojo/_base/declare",
2                "dojo/_base/fx","dojo/_base/connect","dojo/_base/array","dojo/_base/sniff",
3                "dojo/window","dojo/dom","dojo/dom-class","dojo/dom-geometry","dojo/dom-construct",
4                "dijit/_TemplatedMixin","dijit/_Widget","dijit/BackgroundIframe","dojo/dnd/Moveable",
5                "./ContentPane","./ResizeHandle","dojo/text!./resources/FloatingPane.html"], function(
6        kernel, lang, winUtil, declare, baseFx, connectUtil, arrayUtil,
7        has, windowLib, dom, domClass, domGeom, domConstruct, TemplatedMixin, Widget, BackgroundIframe,
8        Moveable, ContentPane, ResizeHandle, template){
9
10/*=====
11var Widget = dijit._Widget;
12var TemplatedMixin = dijit._TemplatedMixin;
13var ContentPane = dojox.layout.ContentPane;
14=====*/
15kernel.experimental("dojox.layout.FloatingPane");
16var FloatingPane = declare("dojox.layout.FloatingPane", [ ContentPane, TemplatedMixin ],{
17        // summary:
18        //              A non-modal Floating window.
19        //
20        // description:
21        //              Makes a `dojox.layout.ContentPane` float and draggable by it's title [similar to TitlePane]
22        //              and over-rides onClick to onDblClick for wipeIn/Out of containerNode
23        //              provides minimize(dock) / show() and hide() methods, and resize [almost]
24        //
25        // closable: Boolean
26        //              Allow closure of this Node
27        closable: true,
28
29        // dockable: Boolean
30        //              Allow minimizing of pane if true
31        dockable: true,
32
33        // resizable: Boolean
34        //              Allow resizing of pane true if true
35        resizable: false,
36
37        // maxable: Boolean
38        //              Horrible param name for "Can you maximize this floating pane?"
39        maxable: false,
40
41        // resizeAxis: String
42        //              One of: x | xy | y to limit pane's sizing direction
43        resizeAxis: "xy",
44
45        // title: String
46        //              Title to use in the header
47        title: "",
48
49        // dockTo: DomNode?
50        //              if empty, will create private layout.Dock that scrolls with viewport
51        //              on bottom span of viewport.
52        dockTo: "",
53
54        // duration: Integer
55        //              Time is MS to spend toggling in/out node
56        duration: 400,
57
58        /*=====
59        // iconSrc: String
60        //              [not implemented yet] will be either icon in titlepane to left
61        //              of Title, and/or icon show when docked in a fisheye-like dock
62        //              or maybe dockIcon would be better?
63        iconSrc: null,
64        =====*/
65
66        // contentClass: String
67        //              The className to give to the inner node which has the content
68        contentClass: "dojoxFloatingPaneContent",
69
70        // animation holders for toggle
71        _showAnim: null,
72        _hideAnim: null,
73        // node in the dock (if docked)
74        _dockNode: null,
75
76        // privates:
77        _restoreState: {},
78        _allFPs: [],
79        _startZ: 100,
80
81        templateString: template,
82       
83        attributeMap: lang.delegate(Widget.prototype.attributeMap, {
84                title: { type:"innerHTML", node:"titleNode" }
85        }),
86       
87        postCreate: function(){
88                this.inherited(arguments);
89                new Moveable(this.domNode,{ handle: this.focusNode });
90                //this._listener = dojo.subscribe("/dnd/move/start",this,"bringToTop");
91
92                if(!this.dockable){ this.dockNode.style.display = "none"; }
93                if(!this.closable){ this.closeNode.style.display = "none"; }
94                if(!this.maxable){
95                        this.maxNode.style.display = "none";
96                        this.restoreNode.style.display = "none";
97                }
98                if(!this.resizable){
99                        this.resizeHandle.style.display = "none";
100                }else{
101                        this.domNode.style.width = domGeom.getMarginBox(this.domNode).w + "px";
102                }
103                this._allFPs.push(this);
104                this.domNode.style.position = "absolute";
105               
106                this.bgIframe = new BackgroundIframe(this.domNode);
107                this._naturalState = domGeom.position(this.domNode);
108        },
109       
110        startup: function(){
111                if(this._started){ return; }
112               
113                this.inherited(arguments);
114
115                if(this.resizable){
116                        if(has("ie")){
117                                this.canvas.style.overflow = "auto";
118                        }else{
119                                this.containerNode.style.overflow = "auto";
120                        }
121                       
122                        this._resizeHandle = new ResizeHandle({
123                                targetId: this.id,
124                                resizeAxis: this.resizeAxis
125                        },this.resizeHandle);
126
127                }
128
129                if(this.dockable){
130                        // FIXME: argh.
131                        var tmpName = this.dockTo;
132
133                        if(this.dockTo){
134                                this.dockTo = dijit.byId(this.dockTo);
135                        }else{
136                                this.dockTo = dijit.byId('dojoxGlobalFloatingDock');
137                        }
138
139                        if(!this.dockTo){
140                                var tmpId, tmpNode;
141                                // we need to make our dock node, and position it against
142                                // .dojoxDockDefault .. this is a lot. either dockto="node"
143                                // and fail if node doesn't exist or make the global one
144                                // once, and use it on empty OR invalid dockTo="" node?
145                                if(tmpName){
146                                        tmpId = tmpName;
147                                        tmpNode = dom.byId(tmpName);
148                                }else{
149                                        tmpNode = domConstruct.create('div', null, winUtil.body());
150                                        domClass.add(tmpNode,"dojoxFloatingDockDefault");
151                                        tmpId = 'dojoxGlobalFloatingDock';
152                                }
153                                this.dockTo = new Dock({ id: tmpId, autoPosition: "south" }, tmpNode);
154                                this.dockTo.startup();
155                        }
156                       
157                        if((this.domNode.style.display == "none")||(this.domNode.style.visibility == "hidden")){
158                                // If the FP is created dockable and non-visible, start up docked.
159                                this.minimize();
160                        }
161                }
162                this.connect(this.focusNode,"onmousedown","bringToTop");
163                this.connect(this.domNode,      "onmousedown","bringToTop");
164
165                // Initial resize to give child the opportunity to lay itself out
166                this.resize(domGeom.position(this.domNode));
167               
168                this._started = true;
169        },
170
171        setTitle: function(/* String */ title){
172                // summary: Update the Title bar with a new string
173                kernel.deprecated("pane.setTitle", "Use pane.set('title', someTitle)", "2.0");
174                this.set("title", title);
175        },
176               
177        close: function(){
178                // summary: Close and destroy this widget
179                if(!this.closable){ return; }
180                connectUtil.unsubscribe(this._listener);
181                this.hide(lang.hitch(this,function(){
182                        this.destroyRecursive();
183                }));
184        },
185
186        hide: function(/* Function? */ callback){
187                // summary: Close, but do not destroy this FloatingPane
188                baseFx.fadeOut({
189                        node:this.domNode,
190                        duration:this.duration,
191                        onEnd: lang.hitch(this,function() {
192                                this.domNode.style.display = "none";
193                                this.domNode.style.visibility = "hidden";
194                                if(this.dockTo && this.dockable){
195                                        this.dockTo._positionDock(null);
196                                }
197                                if(callback){
198                                        callback();
199                                }
200                        })
201                }).play();
202        },
203
204        show: function(/* Function? */callback){
205                // summary: Show the FloatingPane
206                var anim = baseFx.fadeIn({node:this.domNode, duration:this.duration,
207                        beforeBegin: lang.hitch(this,function(){
208                                this.domNode.style.display = "";
209                                this.domNode.style.visibility = "visible";
210                                if (this.dockTo && this.dockable) { this.dockTo._positionDock(null); }
211                                if (typeof callback == "function") { callback(); }
212                                this._isDocked = false;
213                                if (this._dockNode) {
214                                        this._dockNode.destroy();
215                                        this._dockNode = null;
216                                }
217                        })
218                }).play();
219                this.resize(domGeom.position(this.domNode));
220                this._onShow(); // lazy load trigger
221        },
222
223        minimize: function(){
224                // summary: Hide and dock the FloatingPane
225                if(!this._isDocked){ this.hide(lang.hitch(this,"_dock")); }
226        },
227
228        maximize: function(){
229                // summary: Make this FloatingPane full-screen (viewport)
230                if(this._maximized){ return; }
231                this._naturalState = domGeom.position(this.domNode);
232                if(this._isDocked){
233                        this.show();
234                        setTimeout(lang.hitch(this,"maximize"),this.duration);
235                }
236                domClass.add(this.focusNode,"floatingPaneMaximized");
237                this.resize(windowLib.getBox());
238                this._maximized = true;
239        },
240
241        _restore: function(){
242                if(this._maximized){
243                        this.resize(this._naturalState);
244                        domClass.remove(this.focusNode,"floatingPaneMaximized");
245                        this._maximized = false;
246                }
247        },
248
249        _dock: function(){
250                if(!this._isDocked && this.dockable){
251                        this._dockNode = this.dockTo.addNode(this);
252                        this._isDocked = true;
253                }
254        },
255       
256        resize: function(/* Object */dim){
257                // summary: Size the FloatingPane and place accordingly
258                dim = dim || this._naturalState;
259                this._currentState = dim;
260
261                // From the ResizeHandle we only get width and height information
262                var dns = this.domNode.style;
263                if("t" in dim){ dns.top = dim.t + "px"; }
264                else if("y" in dim){ dns.top = dim.y + "px"; }
265                if("l" in dim){ dns.left = dim.l + "px"; }
266                else if("x" in dim){ dns.left = dim.x + "px"; }
267                dns.width = dim.w + "px";
268                dns.height = dim.h + "px";
269
270                // Now resize canvas
271                var mbCanvas = { l: 0, t: 0, w: dim.w, h: (dim.h - this.focusNode.offsetHeight) };
272                domGeom.setMarginBox(this.canvas, mbCanvas);
273
274                // If the single child can resize, forward resize event to it so it can
275                // fit itself properly into the content area
276                this._checkIfSingleChild();
277                if(this._singleChild && this._singleChild.resize){
278                        this._singleChild.resize(mbCanvas);
279                }
280        },
281       
282        bringToTop: function(){
283                // summary: bring this FloatingPane above all other panes
284                var windows = arrayUtil.filter(
285                        this._allFPs,
286                        function(i){
287                                return i !== this;
288                        },
289                this);
290                windows.sort(function(a, b){
291                        return a.domNode.style.zIndex - b.domNode.style.zIndex;
292                });
293                windows.push(this);
294               
295                arrayUtil.forEach(windows, function(w, x){
296                        w.domNode.style.zIndex = this._startZ + (x * 2);
297                        domClass.remove(w.domNode, "dojoxFloatingPaneFg");
298                }, this);
299                domClass.add(this.domNode, "dojoxFloatingPaneFg");
300        },
301       
302        destroy: function(){
303                // summary: Destroy this FloatingPane completely
304                this._allFPs.splice(arrayUtil.indexOf(this._allFPs, this), 1);
305                if(this._resizeHandle){
306                        this._resizeHandle.destroy();
307                }
308                this.inherited(arguments);
309        }
310});
311
312var Dock = declare("dojox.layout.Dock",[Widget, TemplatedMixin],{
313        // summary:
314        //              A widget that attaches to a node and keeps track of incoming / outgoing FloatingPanes
315        //              and handles layout
316
317        templateString: '<div class="dojoxDock"><ul dojoAttachPoint="containerNode" class="dojoxDockList"></ul></div>',
318
319        // private _docked: array of panes currently in our dock
320        _docked: [],
321       
322        _inPositioning: false,
323       
324        autoPosition: false,
325       
326        addNode: function(refNode){
327                // summary: Instert a dockNode refernce into the dock
328               
329                var div = domConstruct.create('li', null, this.containerNode),
330                        node = new DockNode({
331                                title: refNode.title,
332                                paneRef: refNode
333                        }, div)
334                ;
335                node.startup();
336                return node;
337        },
338
339        startup: function(){
340                               
341                if (this.id == "dojoxGlobalFloatingDock" || this.isFixedDock) {
342                        // attach window.onScroll, and a position like in presentation/dialog
343                        this.connect(window, 'onresize', "_positionDock");
344                        this.connect(window, 'onscroll', "_positionDock");
345                        if(has("ie")){
346                                this.connect(this.domNode, "onresize", "_positionDock");
347                        }
348                }
349                this._positionDock(null);
350                this.inherited(arguments);
351
352        },
353       
354        _positionDock: function(/* Event? */e){
355                if(!this._inPositioning){
356                        if(this.autoPosition == "south"){
357                                // Give some time for scrollbars to appear/disappear
358                                setTimeout(lang.hitch(this, function() {
359                                        this._inPositiononing = true;
360                                        var viewport = windowLib.getBox();
361                                        var s = this.domNode.style;
362                                        s.left = viewport.l + "px";
363                                        s.width = (viewport.w-2) + "px";
364                                        s.top = (viewport.h + viewport.t) - this.domNode.offsetHeight + "px";
365                                        this._inPositioning = false;
366                                }), 125);
367                        }
368                }
369        }
370
371
372});
373
374var DockNode = declare("dojox.layout._DockNode",[Widget, TemplatedMixin],{
375        // summary:
376        //              dojox.layout._DockNode is a private widget used to keep track of
377        //              which pane is docked.
378        //
379        // title: String
380        //              Shown in dock icon. should read parent iconSrc?
381        title: "",
382
383        // paneRef: Widget
384        //              reference to the FloatingPane we reprasent in any given dock
385        paneRef: null,
386
387        templateString:
388                '<li dojoAttachEvent="onclick: restore" class="dojoxDockNode">'+
389                        '<span dojoAttachPoint="restoreNode" class="dojoxDockRestoreButton" dojoAttachEvent="onclick: restore"></span>'+
390                        '<span class="dojoxDockTitleNode" dojoAttachPoint="titleNode">${title}</span>'+
391                '</li>',
392
393        restore: function(){
394                // summary: remove this dock item from parent dock, and call show() on reffed floatingpane
395                this.paneRef.show();
396                this.paneRef.bringToTop();
397                this.destroy();
398        }
399});
400
401return FloatingPane;
402});
Note: See TracBrowser for help on using the repository browser.