Ext.ux.Accordion extension class code:
1 // vim: ts=2:sw=2:nu:fdc=2:nospell
2
3 // Create user extensions namespace (Ext.ux)
4 Ext.namespace('Ext.ux');
5
6 /**
7 * Ext.ux.Accordion Extension Class
8 *
9 * @author Ing. Jozef Sakalos
10 * @version $Id: Ext.ux.Accordion.js 18 2007-06-13 17:55:16Z jozo $
11 *
12 * @class Ext.ux.Accordion
13 * @extends Ext.ContentPanel
14 * @constructor
15 * @param {String/HTMLElement/Element} el The container element for this panel
16 * @param {String/Object} config A string to set only the title or a config object
17 * @cfg {Boolean} animate global animation flag for all panels. (defaults to true)
18 * @cfg {Boolean} boxWrap set to true to wrap wrapEl the body is child of (defaults to false)
19 * @cfg {Boolean} draggable set to false to disallow panels dragging (defaults to true)
20 * @cfg {Boolean} fitHeight set to true if you use fixed height dock
21 * @cfg {Boolean} independent true to make panels independent (defaults to false)
22 * @cfg {Integer} initialHeight Initial height to set box to (defaults to 0)
23 * @cfg {Boolean} monitorWindowResize if true panels are moved to
24 * viewport if window is small (defaults to true)
25 * @cfg {Boolean} resizable global resizable flag for all panels (defaults to true)
26 * @cfg {Boolean} undockable true to allow undocking of panels (defaults to true)
27 * @cfg {Boolean} useShadow global useShadow flag for all panels. (defaults to true)
28 * @cfg {Element/HTMLElement/String} wrapEl Element to wrap with nice surrounding
29 */
30 Ext.ux.Accordion = function(el, config) {
31
32 // call parent constructor
33 Ext.ux.Accordion.superclass.constructor.call(this, el, config);
34
35 // create collection for panels
36 this.items = new Ext.util.MixedCollection();
37
38 // assume no panel is expanded
39 this.expanded = null;
40
41 // {{{
42 // install event handlers
43 this.on({
44
45 // {{{
46 // runs before expansion. Triggered by panel's beforeexpand event
47 beforeexpand: {
48 scope: this
49 , fn: function(panel) {
50 // raise panel above others
51 if(!panel.docked) {
52 this.raise(panel);
53 }
54
55 // set fixed height
56 var panelBodyHeight;
57 if(this.fitHeight && panel.docked) {
58 panelBodyHeight = this.getPanelBodyHeight();
59 if(panelBodyHeight) {
60 panel.body.setHeight(panelBodyHeight);
61 }
62 }
63
64 if(panel.docked) {
65 this.expandCount++;
66 this.expanding = true;
67 // this.setDockScroll(false);
68 }
69
70 // don't collapse others if independent or not docked
71 if(this.independent || !panel.docked) {
72 return this;
73 }
74
75 // collapse expanded panel
76 if(this.expanded && this.expanded.docked) {
77 this.expanded.collapse();
78 }
79
80 // remember this panel as expanded
81 this.expanded = panel;
82 }}
83 // }}}
84 // {{{
85 // runs before panel collapses. Triggered by panel's beforecollapse event
86 , beforecollapse: {
87 scope: this
88 , fn: function(panel) {
89
90 // raise panel if not docked
91 if(!panel.docked) {
92 this.raise(panel);
93 }
94 return this;
95 }}
96 // }}}
97 // {{{
98 // runs on when panel expands (before animation). Triggered by panel's expand event
99 , expand: {
100 scope: this
101 , fn: function(panel) {
102 this.fireEvent('panelexpand', panel);
103 }}
104 // }}}
105 // {{{
106 // runs on when panel collapses (before animation). Triggered by panel's collapse event
107 , collapse: {
108 scope: this
109 , fn: function(panel) {
110 this.fireEvent('panelcollapse', panel);
111 }}
112 // }}}
113 // {{{
114 // runs on when animation is completed. Triggered by panel's animationcompleted event
115 , animationcompleted: {
116 scope: this
117 , fn: function(panel) {
118 var box = panel.el.getBox();
119 this.expandCount = (this.expandCount && this.expanding) ? --this.expandCount : 0;
120 if((0 === this.expandCount) && this.expanding) {
121 // this.setDockScroll(true);
122 this.expanding = false;
123 }
124 this.fireEvent('panelbox', panel, box);
125 }}
126 // }}}
127 // {{{
128 // runs when panel is pinned. Triggered by panel's pinned event
129 , pinned: {
130 scope: this
131 , fn: function(panel, pinned) {
132 if(!pinned) {
133 if(panel.collapseOnUnpin) {
134 panel.collapse();
135 }
136 else if(!this.independent) {
137 this.items.each(function(p) {
138 if(p !== panel && p.docked && !p.pinned) {
139 p.collapse();
140 }
141 });
142 this.expanded = panel;
143 }
144 }
145 this.fireEvent('panelpinned', panel, pinned);
146 }}
147 // }}}
148
149 , destroy: {
150 scope:this
151 , fn: function(panel) {
152 this.items.removeKey(panel.id);
153 this.updateOrder();
154 }}
155 });
156 // }}}
157 // {{{
158 // add events
159 this.addEvents({
160 /**
161 * Fires when a panel of the dock is collapsed
162 * @event panelcollapse
163 * @param {Ext.ux.InfoPanel} panel
164 */
165 panelcollapse: true
166
167 /**
168 * Fires when a panel of the dock is expanded
169 * @event panelexpand
170 * @param {Ext.ux.InfoPanel} panel
171 */
172 , panelexpand: true
173
174 /**
175 * Fires when a panel of the dock is pinned
176 * @event panelpinned
177 * @param {Ext.ux.InfoPanel} panel
178 * @param {Boolean} pinned true if panel was pinned false if unpinned
179 */
180 , panelpinned: true
181
182 /**
183 * Fires when the independent state of dock changes
184 * @event independent
185 * @param {Ext.ux.Accordion} this
186 * @param {Boolean} independent New independent state
187 */
188 , independent: true
189
190 /**
191 * Fires when the order of panel is changed
192 * @event orderchange
193 * @param {Ext.ux.Accordion} this
194 * @param {Array} order New order array
195 */
196 , orderchange: true
197
198 /**
199 * Fires when the undockable state of dock changes
200 * @event undockable
201 * @param {Ext.ux.Accordion} this
202 * @param {Array} undockable New undockable state
203 */
204 , undockable: true
205
206 /**
207 * Fires when a panel is undocked
208 * @event panelundock
209 * @param {Ext.ux.InfoPanel} panel
210 * @param {Object} box Position and size object
211 */
212 , panelundock: true
213
214 /**
215 * Fires when a panel is undocked
216 * @event paneldock
217 * @param {Ext.ux.InfoPanel} panel
218 */
219 , paneldock: true
220
221 /**
222 * Fires when a panel box is changed, e.g. after dragging
223 * @event panelbox
224 * @param {Ext.ux.InfoPanel} panel
225 * @param {Object} box Position and size object
226 */
227 , panelbox: true
228
229 /**
230 * Fires when useShadow status changes
231 * @event useshadow
232 * @param {Ext.ux.Accordion} this
233 * @param {Boolean} shadow Use shadow (for undocked panels) flag
234 */
235 , useshadow: true
236 });
237 // }}}
238
239 // setup body
240 this.body = Ext.get(this.body) || this.el;
241 this.resizeEl = this.body;
242 this.id = this.el.id;
243 this.body.addClass('x-dock-body');
244
245 // setup desktop
246 this.desktop = Ext.get(this.desktop || document.body);
247 //this.desktop = this.desktop.dom || this.desktop;
248
249 // setup fixed hight
250 this.wrapEl = Ext.get(this.wrapEl);
251 if(this.fitHeight) {
252 this.body.setStyle('overflow', 'hidden');
253 // this.bodyHeight = this.initialHeight || this.body.getHeight();
254 this.body.setHeight(this.initialHeight || this.body.getHeight());
255 if(this.boxWrap && this.wrapEl) {
256 this.wrapEl.boxWrap();
257 }
258 }
259
260 // watch window resize
261 if(this.monitorWindowResize) {
262 Ext.EventManager.onWindowResize(this.adjustViewport, this);
263 }
264
265 // create drop zone for panels
266 this.dd = new Ext.dd.DropZone(this.body.dom, {ddGroup:'dock-' + this.id });
267
268 }; // end of constructor
269
270 // extend
271 Ext.extend(Ext.ux.Accordion, Ext.ContentPanel, {
272
273 // {{{
274 // defaults
275 independent: false
276 , undockable: true
277 , useShadow: true
278 , boxWrap: false
279 , fitHeight: false
280 , initialHeight: 0
281 , animate: true // global animation flag
282 , zindex: 9999 // (private)
283 , zindexInc: 2 // (private) one for shadow
284 , expandCount: 0
285 , expanding: false
286 , monitorWindowResize: true
287 , resizable: true // global resizable flag
288 , draggable: true // global draggable flag
289 // }}}
290 // {{{
291 /**
292 * Adds the panel to Accordion
293 * @param {Ext.ux.InfoPanel} panel Panel to add
294 * @return {Ext.ux.InfoPanel} added panel
295 */
296 , add: function(panel) {
297
298
299 // append panel to body
300 this.body.appendChild(panel.el);
301
302 panel.docked = true;
303
304 // add docked class to panel body
305 // panel.body.addClass('x-dock-panel-body-docked');
306 // panel.body.removeClass('x-dock-panel-body-undocked');
307 panel.body.replaceClass('x-dock-panel-body-undocked', 'x-dock-panel-body-docked');
308
309 // add panel to items collection
310 this.items.add(panel.el.id, panel);
311
312 // relay these events from panel to dock
313 this.relayEvents(panel, [
314 'beforecollapse'
315 , 'collapse'
316 , 'beforeexpand'
317 , 'expand'
318 , 'animationcompleted'
319 , 'pinned'
320 , 'boxchange'
321 , 'destroy'
322 ]);
323
324 // panel dragging
325 if(this.draggable) {
326 panel.dd = new Ext.ux.Accordion.DDDock(panel, 'dock-' + this.id, this);
327 }
328
329 // panel resizing
330 panel.resizable = this.resizable;
331 // panel.setResizable(this.resizable);
332
333 // shadow and animate flags
334 panel.useShadow = this.useShadow;
335 panel.setShadow(this.useShadow);
336 if(panel.shadow) {
337 panel.shadow.hide();
338 }
339 panel.animate = undefined === panel.animate ? this.animate : panel.animate;
340
341 // z-index for panel
342 this.zindex += this.zindexInc;
343 panel.zindex = this.zindex;
344
345 // onclick handler for panel body (allows raising when panel body is clicked)
346 panel.body.on('click', this.onClickPanelBody.createDelegate(this, [panel]));
347
348 if(this.fitHeight) {
349 this.setPanelHeight(panel);
350 }
351
352 panel.dock = this;
353 panel.desktop = this.desktop;
354
355 return panel;
356
357 }
358 // }}}
359 // {{{
360 /**
361 * Called internally to raise panel above others
362 * Maintains z-index stack
363 * @param {Ext.ux.InfoPanel} panel Panel to raise
364 */
365 , raise: function(panel) {
366 this.items.each(function(p) {
367 if(p.zindex > panel.zindex) {
368 p.zindex -= this.zindexInc;
369 p.el.applyStyles({'z-index':p.zindex});
370 if(!p.docked) {
371 p.setShadow(true);
372 }
373 }
374 }, this);
375 panel.zindex = this.zindex;
376 panel.el.applyStyles({'z-index':panel.zindex});
377 if(this.desktop.lastChild !== panel.el.dom) {
378 this.desktop.appendChild(panel.el.dom);
379 }
380 if(!panel.docked) {
381 panel.setShadow(true);
382 }
383 }
384 // }}}
385 // {{{
386 /**
387 * Resets the order of panels within the dock
388 *
389 * @return {Ext.ux.Accordion} this
390 */
391 , resetOrder: function() {
392 this.items.each(function(panel) {
393 if(!panel.docked) {
394 return;
395 }
396 this.body.appendChild(panel.el);
397 }, this);
398 this.updateOrder();
399 return this;
400 }
401 // }}}
402 // {{{
403 /**
404 * Called internally to update the order variable after dragging
405 */
406 , updateOrder: function() {
407 var order = [];
408 var titles = this.body.select('.x-layout-panel-hd');
409 titles.each(function(titleEl){
410 order.push(titleEl.dom.parentNode.id);
411 });
412 this.order = order;
413 this.fireEvent('orderchange', this, order);
414 }
415 // }}}
416 // {{{
417 /**
418 * Returns array of panel ids in the current order
419 * @return {Array} order of panels
420 */
421 , getOrder: function() {
422 return this.order;
423 }
424 // }}}
425 // {{{
426 /**
427 * Set the order of panels
428 * @param {Array} order Array of ids of panels in required order.
429 * @return {Ext.ux.Accordion} this
430 */
431 , setOrder: function(order) {
432 if('object' !== typeof order || undefined === order.length) {
433 throw "setOrder: Argument is not array.";
434 }
435 var panelEl;
436 for(var i = 0; i < order.length; i++) {
437 panelEl = Ext.get(order[i]);
438 if(panelEl) {
439 this.body.appendChild(panelEl);
440 }
441 }
442 this.updateOrder();
443 return this;
444 }
445 // }}}
446 // {{{
447 /**
448 * Collapse all docked panels
449 * @param {Boolean} alsoPinned true to first unpin then collapse
450 * @param {Ext.ux.InfoPanel} except This panel will not be collapsed.
451 * @return {Ext.ux.Accordion} this
452 */
453 , collapseAll: function(alsoPinned, except) {
454 this.items.each(function(panel) {
455 if(panel.docked) {
456 panel.pinned = alsoPinned ? false : panel.pinned;
457 if(!except || panel !== except) {
458 panel.collapse();
459 }
460 }
461 }, this);
462 return this;
463 }
464 // }}}
465 // {{{
466 /**
467 * Expand all docked panels in independent mode
468 * @return {Ext.ux.Accordion} this
469 */
470 , expandAll: function() {
471 if(this.independent) {
472 this.items.each(function(panel) {
473 if(panel.docked && panel.collapsed) {
474 panel.expand();
475 }
476 }, this);
477 }
478 }
479 // }}}
480 // {{{
481 /**
482 * Called internally while dragging and by state manager
483 * @param {Ext.ux.InfoPanel/String} panel Panel object or id of the panel
484 * @box {Object} box coordinates with target position and size
485 * @return {Ext.ux.Accordion} this
486 */
487 , undock: function(panel, box) {
488
489 // get panel if necessary
490 panel = 'string' === typeof panel ? this.items.get(panel) : panel;
491
492 // proceed only if we have docked panel and in undockable mode
493 if(panel && panel.docked && this.undockable) {
494
495 // sanity check
496 if(box.x < 0 || box.y < 0) {
497 return this;
498 }
499
500 // move the panel in the dom (append to desktop)
501 this.desktop.appendChild(panel.el.dom);
502
503 // adjust panel visuals
504 panel.el.applyStyles({
505 position:'absolute'
506 , 'z-index': panel.zindex
507 });
508 panel.body.replaceClass('x-dock-panel-body-docked', 'x-dock-panel-body-undocked');
509
510 // position the panel
511 panel.setBox(box);
512
513 // reset docked flag
514 panel.docked = false;
515
516 // hide panel shadow (will be shown by raise)
517 if(panel.shadow) {
518 panel.shadow.hide();
519 }
520
521 // raise panel above others
522 this.raise(panel);
523
524 // set the height of a docked expanded panel
525 this.setPanelHeight(this.expanded);
526
527 // enable resizing and scrolling
528 panel.setResizable(!panel.collapsed);
529 if(panel.bodyScroll) {
530 panel.body.setStyle('overflow','auto');
531 }
532
533 // size the undocked panel
534 // todo: revise
535 panel.lastWidth = box.width;
536 panel.lastHeight = box.height;
537
538 // fire panelundock event
539 this.fireEvent('panelundock', panel, {x:box.x, y:box.y, width:box.width, height:box.height});
540 }
541
542 return this;
543 }
544 // }}}
545 // {{{
546 /**
547 * Called internally while dragging
548 * @param {Ext.ux.InfoPanel/String} panel Panel object or id of the panel
549 * @param {String} targetId id of panel after which this panel will be docked
550 * @return {Ext.ux.Accordion} this
551 */
552 , dock: function(panel, targetId) {
553
554 // get panel if necessary
555 panel = 'string' === typeof panel ? this.items.get(panel) : panel;
556
557 // proceed only if we have a docked panel
558 if(panel && !panel.docked) {
559
560 // remember width and height
561 if(!panel.collapsed) {
562 panel.lastWidth = panel.el.getWidth();
563 panel.lastHeight = panel.el.getHeight();
564 }
565
566 // move the panel element in the dom
567 if(targetId && (this.body.id !== targetId)) {
568 panel.el.insertBefore(Ext.fly(targetId));
569 }
570 else {
571 panel.el.appendTo(this.body);
572 }
573
574 // set docked flag
575 panel.docked = true;
576
577 // adjust panel visuals
578 panel.body.replaceClass('x-dock-panel-body-undocked', 'x-dock-panel-body-docked');
579 panel.el.applyStyles({
580 top:''
581 , left:''
582 , width:''
583 , height:''
584 , 'z-index':''
585 , position:'relative'
586 , visibility:''
587 });
588 panel.body.applyStyles({width:'',height:''});
589
590 // disable resizing and shadow
591 panel.setResizable(false);
592 if(panel.shadow) {
593 panel.shadow.hide();
594 }
595
596 // set panel height (only if this.fitHeight = true)
597 this.setPanelHeight(panel.collapsed ? this.expanded : panel);
598
599 // fire paneldock event
600 this.fireEvent('paneldock', panel);
601 }
602
603 return this;
604 }
605 // }}}
606 // {{{
607 /**
608 * Sets the independent mode
609 * @param {Boolean} independent set to false for normal mode
610 * @return {Ext.ux.Accordion} this
611 */
612 , setIndependent: function(independent) {
613 this.independent = independent ? true : false;
614 this.fireEvent('independent', this, independent);
615 return this;
616 }
617 // }}}
618 // {{{
619 /**
620 * Sets the undockable mode
621 * If undockable === true all undocked panels are docked and collapsed (except pinned)
622 * @param {Boolean} undockable set to true to not allow undocking
623 * @return {Ext.ux.Accordion} this
624 */
625 , setUndockable: function(undockable) {
626 this.items.each(function(panel) {
627
628 // dock and collapse (except pinned) all undocked panels if not undockable
629 if(!undockable && !panel.docked) {
630 this.dock(panel);
631 if(!this.independent && !panel.collapsed && !panel.pinned) {
632 panel.collapse();
633 }
634 }
635
636 // refresh dragging constraints
637 if(panel.docked && panel.draggable) {
638 panel.dd.constrainTo(this.body, 0, false);
639 panel.dd.clearConstraints();
640 if(undockable) {
641 panel.constrainToDesktop();
642 }
643 else {
644 panel.dd.setXConstraint(0,0);
645 }
646 }
647 }, this);
648
649 // set the flag and fire event
650 this.undockable = undockable;
651 this.fireEvent('undockable', this, undockable);
652 return this;
653 }
654 // }}}
655 // {{{
656 /**
657 * Restores state of dock and panels
658 * @param {Ext.state.Provider} provider (optional) An alternate state provider
659 */
660 , restoreState: function(provider) {
661 if(!provider) {
662 provider = Ext.state.Manager;
663 }
664 var sm = new Ext.ux.AccordionStateManager();
665 sm.init(this, provider);
666
667 }
668 // }}}
669 // {{{
670 /**
671 * Sets the shadows for all panels
672 * @param {Boolean} shadow set to false to disable shadows
673 * @return {Ext.ux.Accordion} this
674 */
675 , setShadow: function(shadow) {
676 this.items.each(function(panel) {
677 panel.useShadow = shadow;
678 panel.setShadow(false);
679 if(!panel.docked) {
680 panel.setShadow(shadow);
681 }
682 });
683 this.useShadow = shadow;
684 this.fireEvent('useshadow', this, shadow);
685 return this;
686 }
687 // }}}
688 // {{{
689 /**
690 * Called when user clicks the panel body
691 * @param {Ext.ux.InfoPanel} panel
692 */
693 , onClickPanelBody: function(panel) {
694 if(!panel.docked) {
695 this.raise(panel);
696 }
697 }
698 // }}}
699 // {{{
700 /**
701 * Called internally for fixed height docks to get current height of panel(s)
702 */
703 , getPanelBodyHeight: function() {
704 var titleHeight = 0;
705 this.items.each(function(panel) {
706 titleHeight += panel.docked ? panel.titleEl.getHeight() : 0;
707 });
708 this.panelBodyHeight = this.body.getHeight() - titleHeight - this.body.getFrameWidth('tb') + 1;
709 // this.panelBodyHeight = this.body.getHeight() - titleHeight - this.body.getFrameWidth('tb');
710 return this.panelBodyHeight;
711 }
712 // }}}
713 // {{{
714 /**
715 * Sets the height of panel body
716 * Used with fixed height (fitHeight:true) docs
717 * @param {Ext.ux.InfoPanel} panel (defaults to this.expanded)
718 * @return {Ext.ux.Accordion} this
719 */
720 , setPanelHeight: function(panel) {
721 panel = panel || this.expanded;
722 if(this.fitHeight && panel && panel.docked) {
723 panel.body.setHeight(this.getPanelBodyHeight());
724 }
725 return this;
726 }
727 // }}}
728 // {{{
729 /**
730 * Constrains the dragging of panels do the desktop
731 * @return {Ext.ux.Accordion} this
732 */
733 , constrainToDesktop: function() {
734 this.items.each(function(panel) {
735 panel.constrainToDesktop();
736 }, this);
737 return this;
738 }
739 // }}}
740 // {{{
741 /**
742 * Clears dragging constraints of panels
743 * @return {Ext.ux.Accordion} this
744 */
745 , clearConstraints: function() {
746 this.items.each(function(panel) {
747 panel.dd.clearConstraints();
748 });
749 }
750 // }}}
751 // {{{
752 /**
753 * Shows all panels
754 * @param {Boolean} show (optional) if false hides the panels instead of showing
755 * @param {Boolean} alsoUndocked show also undocked panels (defaults to false)
756 * @return {Ext.ux.Accordion} this
757 */
758 , showAll: function(show, alsoUndocked) {
759 show = (false === show ? false : true);
760 this.items.each(function(panel) {
761 panel.show(show, alsoUndocked);
762 });
763 return this;
764 }
765 // }}}
766 // {{{
767 /**
768 * Hides all panels
769 * @param {Boolean} alsoUndocked hide also undocked panels (defaults to false)
770 * @return {Ext.ux.Accordion} this
771 */
772 , hideAll: function(alsoUndocked) {
773 return this.showAll(false, alsoUndocked);
774 }
775 // }}}
776 // {{{
777 /**
778 * Called internally to disable/enable scrolling of the dock while animating
779 * @param {Boolean} enable true to enable, false to disable
780 * @return {void}
781 * @todo not used at present - revise
782 */
783 , setDockScroll: function(enable) {
784 if(enable && !this.fitHeight) {
785 this.body.setStyle('overflow','auto');
786 }
787 else {
788 this.body.setStyle('overflow','hidden');
789 }
790 }
791 // }}}
792 // {{{
793 /**
794 * Set Accordion size
795 * Overrides ContentPanel.setSize
796 *
797 * @param {Integer} w width
798 * @param {Integer} h height
799 * @return {Ext.ux.Accordion} this
800 */
801 , setSize: function(w, h) {
802 // call parent's setSize
803 Ext.ux.Accordion.superclass.setSize.call(this, w, h);
804 // this.body.setHeight(h);
805 this.setPanelHeight();
806
807 return this;
808 }
809 // }}}
810 // {{{
811 /**
812 * Called as windowResize event handler
813 *
814 * @todo: review
815 */
816 , adjustViewport: function() {
817 var viewport = this.desktop.dom === document.body ? {} : Ext.get(this.desktop).getBox();
818
819 viewport.height =
820 this.desktop === document.body
821 ? window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
822 : viewport.height
823 ;
824
825 viewport.width =
826 this.desktop === document.body
827 ? window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
828 : viewport.width
829 ;
830
831 viewport.x = this.desktop === document.body ? 0 : viewport.x;
832 viewport.y = this.desktop === document.body ? 0 : viewport.y;
833
834 this.items.each(function(panel) {
835 if(!panel.docked) {
836 panel.moveToViewport(viewport);
837 }
838 });
839
840 }
841 // }}}
842
843 }); // end of extend
844
845 // {{{
846 // {{{
847 /**
848 * @class Ext.ux.Accordion.DDDock
849 * @constructor
850 * @extends Ext.dd.DDProxy
851 * @param {Ext.ux.InfoPanel} panel Panel the dragging object is created for
852 * @param {String} group Only elements of same group interact
853 * @param {Ext.ux.Accordion} dock Place where panels are docked/undocked
854 */
855 Ext.ux.Accordion.DDDock = function(panel, group, dock) {
856
857 // call parent constructor
858 Ext.ux.Accordion.DDDock.superclass.constructor.call(this, panel.el.dom, group);
859
860 // save panel and dock references for use in methods
861 this.panel = panel;
862 this.dock = dock;
863
864 // drag by grabbing the title only
865 this.setHandleElId(panel.titleEl.id);
866
867 // move only in the dock if undockable
868 if(false === dock.undockable) {
869 this.setXConstraint(0, 0);
870 }
871
872 // init internal variables
873 this.lastY = 0;
874
875 //this.DDM.mode = Ext.dd.DDM.INTERSECT;
876 this.DDM.mode = Ext.dd.DDM.POINT;
877
878 }; // end of constructor
879 // }}}
880
881 // extend
882 Ext.extend(Ext.ux.Accordion.DDDock, Ext.dd.DDProxy, {
883
884 // {{{
885 /**
886 * Default DDProxy startDrag override
887 * Saves some variable for use by other methods
888 * and creates nice dragging proxy (ghost)
889 *
890 * Passed x, y arguments are not used
891 */
892 startDrag: function(x, y) {
893
894 this.lastMoveTarget = null;
895
896 // create nice dragging ghost
897 this.createGhost();
898
899 // get srcEl (the original) and dragEl (the ghost)
900 var srcEl = Ext.get(this.getEl());
901 var dragEl = Ext.get(this.getDragEl());
902
903 // refresh constraints
904 this.panel.constrainToDesktop();
905 var dragHeight, rightC, bottomC;
906 if(this.dock.undockable) {
907 if(this.panel.collapsed) {
908 dragHeight = this.panel.titleEl.getHeight();
909 }
910 else {
911 dragHeight = dragEl.getHeight();
912 dragHeight = dragHeight <= this.panel.titleEl.getHeight() ? srcEl.getHeight() : dragHeight;
913 }
914
915 rightC = this.rightConstraint + srcEl.getWidth() - dragEl.getWidth();
916 bottomC = this.bottomConstraint + srcEl.getHeight() - dragHeight;
917 this.setXConstraint(this.leftConstraint, rightC);
918 this.setYConstraint(this.topConstraint, bottomC);
919 }
920 else {
921 if(this.panel.docked) {
922 this.setXConstraint(0, 0);
923 }
924 }
925
926 // hide dragEl (will be shown by onDrag)
927 dragEl.hide();
928
929 // raise panel's "window" above others
930 if(!this.panel.docked) {
931 this.dock.raise(this.panel);
932 }
933
934 // hide panel's shadow if any
935 this.panel.setShadow(false);
936
937 // clear visibility of panel's body (was setup by animations)
938 this.panel.body.dom.style.visibility = '';
939
940 // hide source panel if undocked
941 if(!this.panel.docked) {
942 srcEl.hide();
943 dragEl.show();
944 }
945
946 } // end of function startDrag
947 // }}}
948 // {{{
949 /**
950 * Called internally to create nice dragging proxy (ghost)
951 */
952 , createGhost: function() {
953
954 // get variables
955 var srcEl = Ext.get(this.getEl());
956 var dragEl = Ext.get(this.getDragEl());
957 var dock = t