PDA

View Full Version : [9/12/08] [Alpha 1] Ext.Window Drawers



jay@moduscreate.com
9 Aug 2008, 10:46 AM
Click here to download: winDrawers.alpha1.tgz (http://tdg-i.com/js/examples/ext/winDrawers/winDrawers.alpha1.tgz)


Inspired by Sean McDaniel (http://www.mcdconsultingllc.com/blinds)

jay@moduscreate.com
9 Aug 2008, 10:52 AM
For those who don't venture out of windows and have not seen this before:

Click the image below to see a window drawer work in OS X
http://tdg-i.com/img/screencasts/2008-08-09_1452.png (http://tdg-i.com/img/screencasts/2008-08-09_1449.swf)

Yoris
9 Aug 2008, 3:15 PM
Unbelievable!!!!!!!!!!! it is A REALLY GREAT CONTRIBUTION to the ext-user community!!! y personally thank you for posting this.
Thanks a LOT.

mjlecomte
9 Aug 2008, 7:29 PM
configurable fx. Cool. I just commented on something about that in another thread.


animCollapse (http://extjs.com/deploy/dev/docs/?class=Ext.Panel&member=animCollapse) : Boolean
True to animate the transition when the panel is collapsed, false to skip the animation (defaults to true if the Ext.Fx class is available, otherwise false).

Not sure why that isn't:

animCollapse (http://extjs.com/deploy/dev/docs/?class=Ext.Panel&member=animCollapse) : BooleanMixed
False (default) to skip the animation, otherwise specify a valid Ext.fx method: 'blind' (the current effect), 'fadeIn', 'fadeOut', ...etc).

mjlecomte
9 Aug 2008, 7:33 PM
By the way, I understand better why the size is constrained to the base panel, but still, if you make your grid example real short, what happens...does it add vertical scroll bars? Your other screenshot, the panels start to stretch out with empty space. Just seems like there should be a config for the height in those situations which might be for 'fit' or maxHeight or whatever.
Just thoughts....

sean
10 Aug 2008, 1:14 PM
Sickness Jay! My original approach at a drawer component this was not nearly as nice. This will be a nice extension for those working on webtop style apps.

jay@moduscreate.com
10 Aug 2008, 1:26 PM
Sickness Jay! My original approach at a drawer component this was not nearly as nice. This will be a nice extension for those working on webtop style apps.

Thanks for the feedback dude. Still some work to do, but it's a start. :)

I'm hoping to add your window blind to an example to show how loaded a window can be :D

jay@moduscreate.com
10 Aug 2008, 1:29 PM
By the way, I understand better why the size is constrained to the base panel, but still, if you make your grid example real short, what happens...does it add vertical scroll bars? Your other screenshot, the panels start to stretch out with empty space. Just seems like there should be a config for the height in those situations which might be for 'fit' or maxHeight or whatever.
Just thoughts....


Ideally, you should configure the parent window (which the drawers resize themselves to) to min dimensions.

The drawers are extensions of Ext.Window, which extend Panel - so you have all of the resizing functionality. I'm going to leave it up to the developer ( like Ext does ) to manage sizing. Ideally, you never want your drawer to get too small - otherwise having one (like in the grid example) makes no sense ;)

Thanks for your feedback dude. It's always valuable.

sean
11 Aug 2008, 7:18 AM
I think the users's should be able to resize the drawer, ie pull it in or out using a drag handle. Also I think that you will need to ensure that the drawer gets masked when the parent window is masked, if you haven't done so already.

brian.moeskau
11 Aug 2008, 8:40 AM
Very nice. Need to sync the drawers when the main window is resized.

Hooray for more Mac fx :D

jay@moduscreate.com
11 Aug 2008, 9:37 AM
I think the users's should be able to resize the drawer, ie pull it in or out using a drag handle. Also I think that you will need to ensure that the drawer gets masked when the parent window is masked, if you haven't done so already.

Thanks dude.
Resize is on the to do list. Didn't think about the loading mask, I'll have to give that some thought. :D

jay@moduscreate.com
11 Aug 2008, 9:58 AM
Very nice. Need to sync the drawers when the main window is resized.


Thanks for the heads up. I must have pushed an Older copy of the drawers. Please see the site now.http://tdg-i.com/js/examples/ext/winDrawers/

Thanks. :)

sean
11 Aug 2008, 10:38 AM
I think the issue is that the width or height (depending on orientation of the drawer) needs to resize with its parent window while it is visible. The behavior of example doesn't demonstrate this behavior. Steps: show all then resize the parent window. In addition it doesn't appear that the drawer stays aligned like it does during a drag/drop sequence.

Sean

jay@moduscreate.com
11 Aug 2008, 10:46 AM
I think the issue is that the width or height (depending on orientation of the drawer) needs to resize with its parent window while it is visible. The behavior of example doesn't demonstrate this behavior. Steps: show all then resize the parent window. In addition it doesn't appear that the drawer stays aligned like it does during a drag/drop sequence.

Sean


Please purge your cache and try again. :)

sean
11 Aug 2008, 10:55 AM
that was it. sorry! It would be sexy to keep the drawers shown during the resize.

jay@moduscreate.com
11 Aug 2008, 11:00 AM
that was it. sorry! It would be sexy to keep the drawers shown during the resize.

I could work on that ;).

Ytorres
12 Aug 2008, 1:33 PM
just to say.... very great job ^^

ajaxvador
12 Aug 2008, 2:09 PM
great job, =D>

blancomario
13 Aug 2008, 11:39 AM
This is excellent work! Is it possible to have multiple drawers that come from the same side? So if I have 2 buttons in a toolbar each button will open a different drawer, but both drawers will appear at the bottom?

jay@moduscreate.com
13 Aug 2008, 12:08 PM
Thanks for the feedback guys.


blancomario,

General UI convention is one drawer per window per side.

http://homepage.mac.com/simx/.Pictures/transmit_drawers.png

Stripeman
18 Aug 2008, 4:30 AM
Wholly crap.. this is just beautimus.

Any know issues with 2.2 ?
also.. (am running 2.2) I actually had to comment out the line resizable: false line otherwise i kept getting the error "this.win.resizer is null or not an object." from drawer.js

Then when i tried to use this in a Panel instead of the window i get the very same error no matter how i set that line (or comment it out) idears?

Terry

jay@moduscreate.com
18 Aug 2008, 4:33 AM
Wholly crap.. this is just beutimus.

Any know issues with 2.2 ?
also.. (am running 2.2) I actually had to comment out the line resizable: false line otherwise i kept getting the error "this.win.resizer is null or not an object." from drawer.js

Then when i tried to use this in a Panel instead of the window i get the very same error no matter how i set that line (or comment it out) idears?

Terry


Thanks. My Demo uses Ext 2.2. Window drawers are meant to use in Windows, not anything else. For panels, use Border Layout ;)

hendricd
18 Aug 2008, 7:01 AM
Sweetness, dude!

ux.MediaFlash players can now have playlist drawers.

jay@moduscreate.com
18 Aug 2008, 7:03 AM
Sweetness, dude!

ux.MediaFlash players can now have playlist drawers.

Yes sir :)

I'm hoping to do a composite example using your ux in the very near future. I might bug you for help - is that OK?

hendricd
18 Aug 2008, 7:06 AM
Yes sir :)

I'm hoping to do a composite example using your ux in the very near future. I might bug you for help - is that OK?

You bet. 1.0 should be released today. Solves all that:
- Flash re-init crap
- mediaMask
- fscommand
- better ExternalInterface support.

should make for a nice demo.

Stripeman
18 Aug 2008, 7:36 AM
Thanks for the reply..
Ok.. got ya.. makes sense.. (hence the name LOL of your ext.)

I cant wait till i get to a point where i can write extensions like this...!!

Terry

jay@moduscreate.com
18 Aug 2008, 8:29 AM
I cant wait till i get to a point where i can write extensions like this...!!


In due time :). This is my first 'plugin' ;)

learningExt
21 Aug 2008, 10:36 AM
Excellent plugin, but has anyone played around with this plugin in the Desktop example? The z-index seems to be off... See attached pic.

jay@moduscreate.com
21 Aug 2008, 10:57 AM
Excellent plugin, but has anyone played around with this plugin in the Desktop example? The z-index seems to be off... See attached pic.

I honestly have not done that yet. I'm thinking the windowManager is playing games that i don't like :(.

I'm hoping to work more on it this weekend. :)

ajaxvador
21 Aug 2008, 2:42 PM
possible to attach this plugin to panel ?

very nice plugin ... =D>

iamleppert
26 Aug 2008, 11:41 AM
is it possible to use these on a standard panel?

jay@moduscreate.com
26 Aug 2008, 11:57 AM
is it possible to use these on a standard panel?

Drawers are meant for windows. It's like asking to use a sound card as a display device.


For Panels, May I suggest Sean McDaniel's window blinds (http://www.mcdconsultingllc.com/blinds)?

iamleppert
27 Aug 2008, 8:21 AM
Drawers are meant for windows. It's like asking to use a sound card as a display device.


For Panels, May I suggest Sean McDaniel's window blinds (http://www.mcdconsultingllc.com/blinds)?

Well, in my case I'm using a portal with panels and have a grid in a panel and would like to display a chart of the grid data in a fold-out "drawer" if the user wants. The window blinds aren't really what I want because they will cover up the data.

I don't think using my existing architecture I am able to use windows instead of panels.

Any suggestions/ideas?

jay@moduscreate.com
27 Aug 2008, 8:25 AM
The BorderLayout would be perfect for that. :)

iamleppert
27 Aug 2008, 8:32 AM
you mean a border layout inside the panel? interesting...

thanks for the suggestion

johnathan

jay@moduscreate.com
27 Aug 2008, 8:49 AM
yes sir :).

One of the first 'complex layout' examples show the properties grid,etc. I realize that drawers would seem slicker, but they would hide existing content if they were attached to a panel. :(

vtswingkid
27 Aug 2008, 11:03 AM
Drawers are meant for windows. It's like asking to use a sound card as a display device.

Wow you guys are old school! Still using your eyes as eyes and ears as ears huh? Speaking of school I think it was teachers who first broke through and figured out how to see from the back of their head.

Nice drawers! And I do mean the code.

xantus
30 Aug 2008, 7:54 AM
Best ext user extension, ever

Thanks!

jay@moduscreate.com
1 Sep 2008, 5:47 PM
Thanks for the feedback everyone.

I've updated the code.

Please look at the following link, which has grid dnd. Fx only right now please ;).
http://tdg-i.com/js/examples/ext/winDrawers/complex_with_dnd.html

jay@moduscreate.com
12 Sep 2008, 9:42 AM
Ping for the update:

Changes [9/12/08]:

Ext Window Drawers Alpha 1 is released today with two new examples; the drag and drop (http://tdg-i.com/js/examples/ext/winDrawers/complex_with_dnd.html) and basic grid window in the desktop (http://tdg-i.com/js/examples/ext/winDrawers/desktop/desktop.html).


The following features were added:

IE6 and IE7 Certification
Fx3 Certification
Titles
Support for [ X ] close button in titles
Resize finished
Window.el.move intercepted
animate : true || false honored Examples to date:

Four Drawer basic (http://tdg-i.com/js/examples/ext/winDrawers/)
Grid and Form (http://tdg-i.com/js/examples/ext/winDrawers/complex_with_dnd.html)
Grid to grid DnD (http://tdg-i.com/js/examples/ext/winDrawers/complex_with_dnd.html)(new)
Web Desktop (http://tdg-i.com/js/examples/ext/winDrawers/desktop/desktop.html) (new - not complete) http://tdg-i.com/img/screencasts/2008-09-12_1327.png
(drag and drop example)
http://tdg-i.com/img/screencasts/2008-09-12_1336.png
(grid in desktop window example)
Known issues:

IE6/7 - Issues with z-ordering (desktop only thus far)
Desktop window maximize to normal size not hooked properly

medley
22 Sep 2008, 7:44 AM
Hello,

I am using the plug-in drawer.
I wanted to declare the window modal :



var rightDrawer = new drawer({
size : 250,
resizable : true,
side : 'e', // Can be n e s w (North, East, South, West)
animate : true,
plain : true,
layout : 'fit',
closable : true,
title : '',
items : TOP.tree.verifier
});


TOP.window = new Ext.Window({
layout : 'border',
width : 400,
height : 400,
modal : true,
closeAction :'hide',
plain : true,
closable : false,
constrain : true,
resizable : false, // Required for now
title : windowTitle,
buttonAlign : 'center',
items : items,
tbar : [],
plugins : [rightDrawer]
});


But the east panel (TOP.tree.verifier) appears disabled.

Thanks for help.
Medley

jay@moduscreate.com
22 Sep 2008, 7:52 AM
Ah, never did modal testing.

Can you replace drawer.js with the following code and let me know if it works (seems to work for me). I have not tested in IEx yet.


/*
Author : Jay Garcia
Site : http://tdg-i.com
Contact Info : jgarcia@tdg-i.com
Purpose : Window Drawers for Ext 2.x Ext.Window class, which emulates OS X behaviors
Warranty : none
Price : free
Version : 1 Alpha 2
Date : 09/22/08

*/
/*
Need to override the Window DnD to allow events to fire.

*/
Ext.override(Ext.Window.DD, {
// private - used for dragging
startDrag : function(){
var w = this.win;
w.fireEvent('ghost', []);
this.proxy = w.ghost();
if(w.constrain !== false){
var so = w.el.shadowOffset;
this.constrainTo(w.container, {right: so, left: so, bottom: so});
}else if(w.constrainHeader !== false){
var s = this.proxy.getSize();
this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
}
}
});

/*
Need to override the Window class to allow events to fire for front and back movement.

*/
Ext.override(Ext.Window, {
setZIndex : function(index){

var newZIndex = ++index;


if(this.modal){
this.mask.setStyle("z-index", index);
}

this.el.setZIndex(newZIndex);
index += 1;

if(this.resizer){
this.resizer.proxy.setStyle("z-index", ++index);
}
if (newZIndex > this.lastZIndex) {
this.fireEvent('tofront', this);
}
else {
this.fireEvent('toback', this);
}
this.lastZIndex = index;
}
});


/*
Drawer Base Class
*/
var drawer = Ext.extend( Ext.Window, {
resizable : false,
closable : false,
init : function(parent) {
this.win = parent;

parent.drawers = parent.drawers || {};


this.resizeHandles = this.side;
parent.drawers[this.side] = this;


this.el.on("mousedown", this.win.toFront, this.win);

this.win.on('tofront', this.onBeforeShow, this);

this.win.on('toback', this.onBeforeShow, this);

this.win.on('ghost', this.onBeforeResize, this);

this.win.on('beforehide', function() {
this.hide(true);

}, this);


this.win.on('move', this.setAlignAndShow, this);

var drawerSetAlignAndShow = this.setAlignAndShow.createDelegate(this); // Needed for the anon function so we don't confuse scope.

(function() {
if (this.win.resizer) {
this.win.resizer.on('resize', this.setAlignAndShow.createDelegate(this));
}
this.win.el.win = this.win; //need this reference

/*
Hook after the window's element.moveTo method
*/
this.win.el.moveTo = this.win.el.moveTo.createSequence(function() {
drawerSetAlignAndShow();
},this.win.el);


}).defer(500, this);
//this.win.on('resize', this.setAlignAndShow.createDelegate(this), this);

if(this.resizable){
this.resizer = new Ext.Resizable(this.el, {
minWidth : this.minWidth,
minHeight : this.minHeight,
handles : this.resizeHandles || null,
pinned : true,
resizeElement : this.resizerAction
});
this.resizer.window = this;
this.resizer.on("beforeresize", this.beforeResize, this);
}

},

initComponent : function() {

Ext.apply(this, {
renderTo : Ext.getBody(),
frame : true,
closeAction : 'hide',
draggable : false,
//title : '',
alignToParams : {}
});
this.on('beforeshow', this.onBeforeShow, this);

if (this.size) {
if (this.side == 'e' || this.side == 'w') {
this.width = this.size;
}
else {
this.height = this.size;
}
}
drawer.superclass.initComponent.call(this, arguments);

},
setAlignAndShow : function() {
this.setAlignments();
if (! this.hidden) {
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY );

/*
Simple fix for IE, where the bwrap doesn't properly resize.
*/
if (Ext.isIE) {
this.bwrap.hide();
this.bwrap.show();
Ext.log('here');
}


}
else {
this.el.alignTo(document.body, 'tl', [-1, -1]);
}

if (this.showAgain) {
this.show(true);
}
this.showAgain = false;
},
onBeforeResize : function() {
if (! this.hidden) {
this.showAgain = true;
}

this.hide(true);
},
onBeforeShow : function() {
this.setAlignments();
this.setZIndexModified(this.win.el.getZIndex() - 2);
},
show : function(skipAnim){
if (! this.hidden) {
return;
}
skipAnim = skipAnim || false;

if(!this.rendered){
this.render(Ext.getBody());
}
if(this.fireEvent("beforeshow", this) === false){
return;
}

this.hidden = false;
this.beforeShow();
this.afterShow(skipAnim);

},
afterShow : function(skipAnim){
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY );

if (this.animate && ! skipAnim) {
this.el.slideIn(this.alignToParams.slideDirection, {
duration : this.animDuration || .25
});
}
else {
drawer.superclass.afterShow.call(this);
}
},
setAlignments: function() {
switch (this.side) {
case 'n' :
this.setWidth(this.win.el.getWidth() - 10);

this.alignToParams = Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [ 5, (this.el.getComputedHeight() * -1) + 5],
slideDirection : 'b'
});

break;

case 's' :
this.setWidth(this.win.el.getWidth() - 10);

this.alignToParams = Ext.apply(this.alignToParams, {
alignTo : 'bl',
alignToXY : [5, (Ext.isIE6) ? -2 : -7],
slideDirection : 't'
});

break;

case 'e' :
this.setHeight(this.win.el.getHeight() - 10);
this.alignToParams = Ext.apply(this.alignToParams, {
alignTo : 'tr',
alignToXY : [-5, 5],
slideDirection : 'l'
});

break;


case 'w' :
this.setHeight(this.win.el.getHeight() - 10);
this.alignToParams = Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [(this.el.getComputedWidth() * -1) + 5, 5],
slideDirection : 'r'
});

break;
}
},
beforeHide : function() {
//console.info('beforehide');

},
hide : function(skipAnim){
skipAnim = skipAnim || false;
if (this.hidden) {
return;
}

//this.hidden = true;
if(this.animate === true && skipAnim === false){
this.el.disableShadow(true);

this.el.slideOut(this.alignToParams.slideDirection, {
duration : this.animDuration || .25,
callback : function() {
drawer.superclass.hide.call(this);
},
scope : this
});
}
else {
drawer.superclass.hide.call(this);
}

},

// private
initEvents : function(){
Ext.Window.superclass.initEvents.call(this);
if(this.animateTarget){
this.setAnimateTarget(this.animateTarget);
}
if(this.draggable){
this.header.addClass("x-window-draggable");
}
this.initTools();

this.el.on("mousedown", this.toFront, this);
this.manager = this.manager || Ext.WindowMgr;
this.manager.register(this);
this.hidden = true;
if(this.maximized){
this.maximized = false;
this.maximize();
}
if(this.closable){
var km = this.getKeyMap();
km.on(27, this.onEsc, this);
km.disable();
}
},

toFront : Ext.emptyFn,
setZIndex : Ext.emptyFn,

setZIndexModified : function(index){
if(this.modal){
this.mask.setStyle("z-index", index);
}
this.el.setZIndex(++index);
index += 5;

if(this.resizer){
this.resizer.proxy.setStyle("z-index", ++index);
}

this.lastZIndex = index;
}

});

medley
23 Sep 2008, 12:26 AM
Thanks. It is working very well.

Medley

medley
23 Sep 2008, 1:33 AM
Hello,

I have a strange behaviour.
I have a leftDrawer with a formPanel.
When I close the window (winAmInfo) and I open it again and show the leftDrawer, the fields are duplicated in the form (see attachment)



var urlAMInfo = 'torisManagementAction.do?action='
+ TOP.struts.action.displayAMInfo + '&amdId='
+ record.data.amdId;

var AMInfoStore = fnGetAMInfoStore(urlAMInfo);

var AMInfoPanel = new Ext.form.FormPanel({
id : 'japan.panel.center',
labelWidth : 75,
title : TOP.displayAmDetails.title,
region : 'center',
frame : true,
width : 350,
margins : '0 0 0 0',
defaults : {
width : 230
},
defaultType : 'textfield',
items : fnGetAmendmentInfoItems(disabled)
});

//var reportInfoItems = ;

var reportInfoPanel = new Ext.form.FormPanel({
id : 'japan.panel.west',
title : TOP.displayReportDetails.title,
labelWidth : 85,
region : 'west',
frame : true,
width : 330,
margins : '0 0 0 0',
defaults : {
width : 215
},
items : fnGetReportInfoItems(disabled)
});

/* Get the signataires list */
var authorsList = fnGetSignataires(urlAMInfo);

AMInfoStore.load();
AMInfoStore.on('load', function() {
var record = AMInfoStore.getAt(0);
AMInfoPanel.getForm().loadRecord(record);
reportInfoPanel.getForm().loadRecord(record);
});

var bt = new Ext.Toolbar.Button({
id : 'japan.btn.reportInfo',
xtype : 'button',
tooltip : 'Click to display report info',
iconCls : 'icon-goto-left',
text : TOP.displayAmDetails.show.report,
handler : function() {
if(this.getText() == TOP.displayAmDetails.show.report)
{
winAmInfo.drawers.w.show();
this.setText(TOP.displayAmDetails.hide.report);
} else {
winAmInfo.drawers.w.hide();
this.setText(TOP.displayAmDetails.show.report);
}
}
});

var bt2 = new Ext.Toolbar.Button({
id : 'japan.btn.signataires',
menuAlign : 'right',
tooltip : 'Click to display authors list',
xtype : 'button',
iconCls : 'icon-goto-right',
text : TOP.displayAmDetails.show.signataires,
handler : function() {

if(this.getText() == TOP.displayAmDetails.show.signataires)
{
winAmInfo.drawers.e.show();
this.setText(TOP.displayAmDetails.hide.signataires);
} else {
winAmInfo.drawers.e.hide();
this.setText(TOP.displayAmDetails.show.signataires);
}
}
});

var rightDrawer = new drawer({
id : 'drawer.authors',
size : 350,
resizable : false,
side : 'e',
animate : true,
plain : true,
layout : 'fit',
title : '',
items : authorsList
});

var leftDrawer = new drawer({
id : 'drawer.report',
size : 350 ,
resizable : true,
side : 'w',
animate : true,
plain : true,
layout : 'fit',
title : '',
items : reportInfoPanel
});

var winAmInfo = new Ext.Window({
layout : 'border',
width : 400,
height : 400,
closeAction :'hide',
modal : true,
plain : true,
closable : false,
constrain : true,
resizable : false, // Required for now
title : windowTitle,
buttonAlign : 'center',
items : [AMInfoPanel],
tbar : [],
plugins : [leftDrawer, rightDrawer]
});

winAmInfo.id = 'borderWindow.AMInfo';
winAmInfo.getTopToolbar().push(bt);
winAmInfo.getTopToolbar().push('->');
winAmInfo.getTopToolbar().push(bt2);
winAmInfo.title = title;
winAmInfo.setSize(350, 510);

TOP.button.close = winAmInfo.addButton({
text : 'Close',
iconCls : 'icon-out',
handler : function() {
winAmInfo.close();
}
});

winAmInfo.show();

winAmInfo.on('close', function() {
delete winAmInfo;
});


Thanks for help
Medley

medley
23 Sep 2008, 3:42 AM
I did this and it works now :



leftDrawer.destroy();


I don't know if it is the best solution
Medley

jay@moduscreate.com
23 Sep 2008, 4:25 AM
You shouldn't have to destroy the drawers. It's hard duplicate your problem because of all of the stuff that you're doing.

medley
23 Sep 2008, 9:12 AM
I know that it is no clean to use destroy function.
I will look for the problem and let u know if I find something.

Medley

Saeven
15 Oct 2008, 10:19 PM
Very cool!

I've run into an incredibly strange problem though. If a drawer contains a treepanel, that contains a node whose width exceeds that of the drawer, the drawer's treepanel contents render elsewhere on the screen when the window is jiggled! Very strange!

Try this code to reproduce the problem:



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="../templates/advanced/ext2/resources/css/ext-all.css">
<script type="text/javascript" src="../templates/advanced/ext2/ext-base.js"></script>
<script type="text/javascript" src="../templates/advanced/ext2/ext.php"></script>

<!-- drawers -->
<script type="text/javascript" src="templates/stock/includes/ux/drawer/Ext.ux.Drawer.js"></script>

<!-- start test case -->
<script type="text/javascript">

Ext.onReady( function(){

var navPanel = new Ext.Window({
title: "Test Window",
width: 850,
height: 500,
shim:false,
animCollapse:false,
constrainHeader:true,
plugins : [
new drawer({
xtype : 'windowdrawer',
side : 'w',
animate : true,
resizable: false,
layout : 'fit',
width : 250,
items : [
{
xtype: 'treepanel',
id: 'ticket-category-queue',
title: "Select Visible Queues",
animate:true,
rootVisible: true,
enableDD:false,
root: new Ext.tree.TreeNode({
text: "default",
draggable:false,
id:'0'
}),
bodyStyle: 'padding:5px;',
autoScroll: true,
width: 250,
loadMask: true,
loader: new Ext.tree.TreeLoader()
}
]
})
],
tbar : [
{ text: 'show', handler: function(){ navPanel.drawers.w.show(); } },
{ text: 'hide', handler: function(){ navPanel.drawers.w.hide(); } }
]
});

navPanel.show();

var root = Ext.getCmp('ticket-category-queue').getRootNode();
root.appendChild(
new Ext.tree.TreeNode({
text: "This is a node with a very long title"
})
);

if( !root.childrenRendered )
root.renderChildren();

root.expand();

}); // Ext.onReady

</script>
<!-- end test case -->
</head>
<body>


</body>
</html>


Hope this picks your brain to a solution; if it does, let me know! ;)

Cheers!

jay@moduscreate.com
16 Oct 2008, 4:28 AM
OK, i see the problem.

To reproduce with your code, show the drawer, hide it, move the window.

Cool bug! :) Thanks for letting me know, i'll add it to the 'to do' list. ;)

jay@moduscreate.com
16 Oct 2008, 4:30 AM
I confirmed the bug in IE6 and Fx 3.

jay@moduscreate.com
16 Oct 2008, 4:33 AM
please replace drawer.js with the following code and let me know if it fixes your issue. I think i pinpointed and corrected the problem.


/*
Author : Jay Garcia
Site : http://tdg-i.com
Contact Info : jgarcia@tdg-i.com
Purpose : Window Drawers for Ext 2.x Ext.Window class, which emulates OS X behaviors
Warranty : none
Price : free
Version : 1 Alpha 1.1
Date : 10/16/08

*/
/*
Need to override the Window DnD to allow events to fire.

*/
Ext.override(Ext.Window.DD, {
// private - used for dragging
startDrag : function(){
var w = this.win;
w.fireEvent('ghost', []);
this.proxy = w.ghost();
if(w.constrain !== false){
var so = w.el.shadowOffset;
this.constrainTo(w.container, {right: so, left: so, bottom: so});
}else if(w.constrainHeader !== false){
var s = this.proxy.getSize();
this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
}
}
});

/*
Need to override the Window class to allow events to fire for front and back movement.

*/
Ext.override(Ext.Window, {
setZIndex : function(index){

var newZIndex = ++index;


if(this.modal){
this.mask.setStyle("z-index", index);
}

this.el.setZIndex(newZIndex);
index += 1;

if(this.resizer){
this.resizer.proxy.setStyle("z-index", ++index);
}
if (newZIndex > this.lastZIndex) {
this.fireEvent('tofront', this);
}
else {
this.fireEvent('toback', this);
}
this.lastZIndex = index;
}
});


/*
Drawer Base Class
*/
var drawer = Ext.extend( Ext.Window, {
resizable : false,
closable : false,
init : function(parent) {
this.win = parent;

parent.drawers = parent.drawers || {};


this.resizeHandles = this.side;
parent.drawers[this.side] = this;


this.el.on("mousedown", this.win.toFront, this.win);

this.win.on('tofront', this.onBeforeShow, this);

this.win.on('toback', this.onBeforeShow, this);

this.win.on('ghost', this.onBeforeResize, this);

this.win.on('beforehide', function() {
this.hide(true);
}, this);


this.win.on('move', this.setAlignAndShow, this);

var drawerSetAlignAndShow = this.setAlignAndShow.createDelegate(this); // Needed for the anon function so we don't confuse scope.

(function() {
if (this.win.resizer) {
this.win.resizer.on('resize', this.setAlignAndShow.createDelegate(this));
}
this.win.el.win = this.win; //need this reference

/*
Hook after the window's element.moveTo method
*/
this.win.el.moveTo = this.win.el.moveTo.createSequence(function() {
drawerSetAlignAndShow();
},this.win.el);


}).defer(500, this);
//this.win.on('resize', this.setAlignAndShow.createDelegate(this), this);

if(this.resizable){
this.resizer = new Ext.Resizable(this.el, {
minWidth : this.minWidth,
minHeight : this.minHeight,
handles : this.resizeHandles || null,
pinned : true,
resizeElement : this.resizerAction
});
this.resizer.window = this;
this.resizer.on("beforeresize", this.beforeResize, this);
}

},

initComponent : function() {

Ext.apply(this, {
renderTo : Ext.getBody(),
frame : true,
closeAction : 'hide',
draggable : false,
//title : '',
alignToParams : {}
});
this.on('beforeshow', this.onBeforeShow, this);

if (this.size) {
if (this.side == 'e' || this.side == 'w') {
this.width = this.size;
}
else {
this.height = this.size;
}
}
drawer.superclass.initComponent.call(this, arguments);

},
setAlignAndShow : function() {
this.setAlignments();
if (! this.hidden) {
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY );

/*
Simple fix for IE, where the bwrap doesn't properly resize.
*/
if (Ext.isIE) {
this.bwrap.hide();
this.bwrap.show();
Ext.log('here');
}


}
else {
//this.el.alignTo(document.body, 'tl', [-1, -1]);
}

if (this.showAgain) {
this.show(true);
}
this.showAgain = false;
},
onBeforeResize : function() {
if (! this.hidden) {
this.showAgain = true;
}

this.hide(true);
},
onBeforeShow : function() {
this.setAlignments();
this.setZIndexModified(this.win.el.getZIndex() - 2);
},
show : function(skipAnim){
if (! this.hidden) {
return;
}
skipAnim = skipAnim || false;

if(!this.rendered){
this.render(Ext.getBody());
}
if(this.fireEvent("beforeshow", this) === false){
return;
}

this.hidden = false;
this.beforeShow();
this.afterShow(skipAnim);

},
afterShow : function(skipAnim){
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY );

if (this.animate && ! skipAnim) {
this.el.slideIn(this.alignToParams.slideDirection, {
duration : this.animDuration || .25
});
}
else {
drawer.superclass.afterShow.call(this);
}
},
setAlignments: function() {
switch (this.side) {
case 'n' :
this.setWidth(this.win.el.getWidth() - 10);

this.alignToParams = Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [ 5, (this.el.getComputedHeight() * -1) + 5],
slideDirection : 'b'
});

break;

case 's' :
this.setWidth(this.win.el.getWidth() - 10);

this.alignToParams = Ext.apply(this.alignToParams, {
alignTo : 'bl',
alignToXY : [5, (Ext.isIE6) ? -2 : -7],
slideDirection : 't'
});

break;

case 'e' :
this.setHeight(this.win.el.getHeight() - 10);
this.alignToParams = Ext.apply(this.alignToParams, {
alignTo : 'tr',
alignToXY : [-5, 5],
slideDirection : 'l'
});

break;


case 'w' :
this.setHeight(this.win.el.getHeight() - 10);
this.alignToParams = Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [(this.el.getComputedWidth() * -1) + 5, 5],
slideDirection : 'r'
});

break;
}
},
beforeHide : function() {
//console.info('beforehide');

},
hide : function(skipAnim){
skipAnim = skipAnim || false;
if (this.hidden) {
return;
}

//this.hidden = true;
if(this.animate === true && skipAnim === false){
this.el.disableShadow(true);

this.el.slideOut(this.alignToParams.slideDirection, {
duration : this.animDuration || .25,
callback : function() {
drawer.superclass.hide.call(this);
},
scope : this
});
}
else {
drawer.superclass.hide.call(this);
}

},

// private
initEvents : function(){
Ext.Window.superclass.initEvents.call(this);
if(this.animateTarget){
this.setAnimateTarget(this.animateTarget);
}
if(this.draggable){
this.header.addClass("x-window-draggable");
}
this.initTools();

this.el.on("mousedown", this.toFront, this);
this.manager = this.manager || Ext.WindowMgr;
this.manager.register(this);
this.hidden = true;
if(this.maximized){
this.maximized = false;
this.maximize();
}
if(this.closable){
var km = this.getKeyMap();
km.on(27, this.onEsc, this);
km.disable();
}
},

toFront : Ext.emptyFn,
setZIndex : Ext.emptyFn,

setZIndexModified : function(index){
if(this.modal){
this.mask.setStyle("z-index", index);
}
this.el.setZIndex(++index);
index += 5;

if(this.resizer){
this.resizer.proxy.setStyle("z-index", ++index);
}

this.lastZIndex = index;
}

});

DigitalSkyline
16 Oct 2008, 10:34 AM
Nice work, No use for it yet but it looks great!

Saeven
19 Oct 2008, 10:50 PM
Yep that worked, good work, and thanks!

mystix
3 Nov 2008, 8:30 PM
/*
Author : Jay Garcia
Site : http://tdg-i.com
Contact Info : jgarcia@tdg-i.com
Purpose : Window Drawers for Ext 2.x Ext.Window class, which emulates OS X behaviors
Warranty : none
Price : free
Version : ????
Date : ????
*/

// Need to override the Window DnD to allow events to fire.
Ext.override(Ext.Window.DD, {
// private - used for dragging
startDrag : function() {
var w = this.win;
w.fireEvent('ghost', []);
this.proxy = w.ghost();
if (w.constrain !== false) {
var so = w.el.shadowOffset;
this.constrainTo(w.container, {right: so, left: so, bottom: so});
} else if (w.constrainHeader !== false) {
var s = this.proxy.getSize();
this.constrainTo(w.container, {right: -(s.width - this.headerOffsets[0]), bottom: -(s.height - this.headerOffsets[1])});
}
}
});


// Need to override the Window class to allow events to fire for front and back movement.
Ext.override(Ext.Window, {
setZIndex : function(index) {
var newZIndex = ++index;

if (this.modal) {
this.mask.setStyle("z-index", index);
}

this.el.setZIndex(newZIndex);
index += 5;

if (this.resizer) {
this.resizer.proxy.setStyle("z-index", ++index);
}
if (newZIndex > this.lastZIndex) {
this.fireEvent('tofront', this);
} else {
this.fireEvent('toback', this);
}
this.lastZIndex = index;
}
});

Ext.ns('Ext.ux.plugins');

// Drawer Base Class
Ext.ux.plugins.WindowDrawer = Ext.extend(Ext.Window, {
closable : false,
resizable : false,

show : function(skipAnim) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.hidden = false;
this.beforeShow();
this.afterShow(!!skipAnim);
}
},

hide : function(skipAnim) {
if (this.hidden) {
return;
}

if (this.animate === true && !skipAnim) {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
this.el.disableShadow();
}

this.el.slideOut(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.hide.call(this);
}

// REQUIRED!!!
this.hidden = true;
},

// private
init : function(parent) {
this.win = parent;
this.resizeHandles = this.side; // allow resizing only on 1 side (if resizing is allowed)

parent.drawers = parent.drawers || {};
parent.drawers[this.side] = this; // add this WindowDrawer to the parent's drawer collection
parent.on({
scope: this,

tofront : this.beforeShow,
toback : this.beforeShow,
ghost : this.onBeforeResize,
move : this.alignAndShow,
resize : this.alignAndShow,
destroy : this.destroy,

render: function(p) {
// render WindowDrawer to parent's container, if available
this.render(p.ownerCt? p.ownerCt.getEl() : Ext.getBody());
},

beforehide: function() {
this.hide(true);
}
});
},

// private
initComponent : function() {
Ext.apply(this, {
frame : true,
draggable : false,
modal : false,
closeAction : 'hide',
alignToParams : {}
});

this.on('beforeshow', this.beforeShow, this);

if (this.size) {
if (this.side == 'e' || this.side == 'w') {
this.width = this.size;
} else {
this.height = this.size;
}
}

Ext.ux.plugins.WindowDrawer.superclass.initComponent.call(this);
},

// private
onBeforeResize : function() {
if (!this.hidden) {
this.showAgain = true;
}
this.hide(true);
},

// private
beforeShow : function() {
this.setAlignment();
this.setZIndex(this.win.el.getZIndex() - 3);
},

// private
afterShow : function(skipAnim) {
if (this.animate && !skipAnim) {
this.el.slideIn(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
// re-enable shadows after animation
this.el.enableShadow(true);
}

// REQUIRED!!
this.el.show(); // somehow forces the shadow to appear
}
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.afterShow.call(this);
}
},

// private
alignAndShow : function() {
this.setAlignment();

if (this.showAgain) {
this.show(true);
}
this.showAgain = false;
},

// private
setAlignment: function() {
switch(this.side) {
case 'n' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [5, (this.el.getComputedHeight() * -1) + 5],
slideDirection : 'b'
});
break;

case 's' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'bl',
alignToXY : [5, (Ext.isIE6)? -2 : -7],
slideDirection : 't'
});
break;

case 'e' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tr',
alignToXY : [-5, 5],
slideDirection : 'l'
});
break;

case 'w' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [(this.el.getComputedWidth() * -1) + 5, 5],
slideDirection : 'r'
});
break;
}

if (!this.hidden) {
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY);

// Simple fix for IE, where the bwrap doesn't properly resize.
if (Ext.isIE) {
this.bwrap.hide();
this.bwrap.show();
}
}

// force doLayout()
this.doLayout();
},

// private
toFront: function() {
this.win.toFront(); // first bring WindowDrawer's parent to the front
this.setZIndex(this.win.el.getZIndex() - 3); // then place WindowDrawer behind its parent
return this;
}
});


[ edit ]
oh crap... i overwrote all my previous comments with the updated code too... geez...

jay@moduscreate.com
4 Nov 2008, 4:48 AM
Most Excellent Marc. I'm going to test this. Mind if I post this update on my blog? :)

mystix
4 Nov 2008, 7:20 AM
Mind if I post this update on my blog? :)
nope, not at all. :)
please do.

mystix
4 Nov 2008, 6:24 PM
fixed the missing drawer shadows (updated the code in post #54, and inadvertently wiped out all my previous comments surrounding the code block... D'Oh!!! :">)

[ edit 1 ]
one last todo: re-enabling shadows for the animated drawers onShow... (currently they only appear when the parent window is dragged). shadows on unanimated drawers appear just fine.
done!

[ edit 2 ]
windowdrawer animation is not recommended for gecko-based browsers atm.
Safari on osx / windows (and i presume GoogleChrome too) perform flawlessly... and beautifully as well.

jay@moduscreate.com
13 Nov 2008, 6:25 AM
Marc, i'm testing the update now. Animation works great in fx3, though i have not tested in fx2.

Thanks for helping out dude.

mystix
13 Nov 2008, 6:39 AM
Marc, i'm testing the update now. Animation works great in fx3, though i have not tested in fx2.


woot woot. ;)
do let us know when you're done testing.

hendricd
13 Nov 2008, 8:46 AM
@jay -- A couple of recommends:

Line 138: should be

Ext.ux.plugins.WindowDrawer.superclass.initComponent.apply(this, arguments);

and, this might be good idea, since the drawers don't live in a layout ?:



parent.on({
scope: this,
beforedestroy : this.destroy,
tofront : this.beforeShow,
toback : this.beforeShow,
.....


Nice progress!

jay@moduscreate.com
13 Nov 2008, 8:50 AM
Doug,

Thanks for the heads up and suggestions dude. :)

mystix
13 Nov 2008, 9:39 AM
Line 138: should be

Ext.ux.plugins.WindowDrawer.superclass.initComponent.apply(this, arguments);

woah... nice catch on that and the destroy code :)

simplified further it should be


Ext.ux.plugins.WindowDrawer.superclass.initComponent.call(this);

since initComponent() doesn't take any arguments.

i've updated the code in post #54 (hooked the destruction of the plugin to the destroy event instead of the beforedestroy event though, just in case the beforedestroy event is cancelled)

[edit]
@jay, regarding windowdrawer animation -- it's slow as molasses (imo) in FF3 when you include anything other than plain html (e.g. a grid / a formpanel) in it.

jay@moduscreate.com
18 Nov 2008, 6:11 AM
Mark, I applied your changes and it seems to work well. Animation seems to work well for me in the grid dnd to grid example that I have in fx3.

I found the culprit for the IE7 drawer incompatability. I need to post a change to the Ext examples SVN soon :).

Thanks so much guys.
-Jay

mystix
18 Nov 2008, 6:36 AM
Mark, I applied your changes and it seems to work well. Animation seems to work well for me in the grid dnd to grid example that I have in fx3.

that's real odd... i guess it must be due to all of the other components i've got rendered on screen... :-?



I found the culprit for the IE7 drawer incompatability. I need to post a change to the Ext examples SVN soon :).

did the changes resolve the rest of the stuff you mentioned in your first post in this thread? (i.e. broken IE examples / z-order issues, Desktop window maximize to normal size not hooked properly and etc??)

jay@moduscreate.com
18 Nov 2008, 6:57 AM
Yeah, 'effects' are expensive ;).


The z-order issue was due to the desktop rendering the window on the desktop el - it's strange.

the fix was to allow the window to render to document.body like it normally does :)

mystix
18 Nov 2008, 7:05 AM
Yeah, 'effects' are expensive ;).
yeah, but they really kick butt. :))



The z-order issue was due to the desktop rendering the window on the desktop el - it's strange.

the fix was to allow the window to render to document.body like it normally does :)

i think i've got just the fix for that (assuming the "desktop" is a valid Container):
http://extjs.com/forum/showthread.php?p=205787#post205787 -- allows you to add the Ext.Window to any valid Container.

jay@moduscreate.com
18 Nov 2008, 7:18 AM
The weird thing was that it only affected IE7 :-\

jay@moduscreate.com
23 Nov 2008, 5:54 PM
1b1 is up, please check http://tdg-i.com/54/extuxpluginswindowdrawers-10-beta-1-released or the first post in this thread

najra
26 Nov 2008, 12:57 AM
I wanted to use drawers in combination with a tabpanel window. Each tab should have it's own drawer. I modified the init function so that parent.drawers[this.side] can be an array:



init: function(parent) {
this.win = parent;
this.resizeHandles = this.side; // allow resizing only on 1 side (if resizing is allowed)

parent.drawers = parent.drawers || {};
if (!parent.drawers[this.side])
parent.drawers[this.side] = this; // add this WindowDrawer to the parent's drawer collection
else {
if (!parent.drawers[this.side].push) {
var d = parent.drawers[this.side];
parent.drawers[this.side] = [];
parent.drawers[this.side].push(d);
}
parent.drawers[this.side].push(this);
}
parent.on({
scope: this,
tofront: this.onBeforeShow,
toback: this.onBeforeShow,
ghost: this.onBeforeResize,
move: this.alignAndShow,
resize: this.alignAndShow,
beforedestroy: this.destroy,
render: function(p) {
// render WindowDrawer to parent's container, if available
this.render(p.ownerCt ? p.ownerCt.getEl() : Ext.getBody());
},

beforehide: function() {
this.hide(true);
}
});
}

mystix
26 Nov 2008, 1:10 AM
I wanted to use drawers in combination with a tabpanel window. Each tab should have it's own drawer. I modified the init function so that parent.drawers[this.side] can be an array:

could you post a screenshot + example usage? thanks.

jay@moduscreate.com
26 Nov 2008, 5:05 AM
I wanted to use drawers in combination with a tabpanel window. Each tab should have it's own drawer. I modified the init function so that parent.drawers[this.side] can be an array:

alright, but that seems wasteful to me! ideally, one drawer with a card layout bound to the tab panel via events.

NeonMonk
17 Dec 2008, 7:49 PM
Can I just make a quick suggestion?

I changed the show & hide functions to actually call hide() on the drawer element. The reason why is that I use a lot of textfields with custom placed icons (absolute positioning) which naturally stays floating in midair after the drawer is apparently "hidden."


show : function(skipAnim) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.el.show();
this.hidden = false;
this.onBeforeShow();
this.afterShow(!!skipAnim);
}
},

hide : function(skipAnim) {
if (this.hidden) {
return;
}

if (this.animate === true && !skipAnim) {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
this.el.disableShadow();
}

this.el.slideOut(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback: function() {
this.el.hide();
}
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.hide.call(this);
}

// REQUIRED!!!
this.hidden = true;
},

mystix
5 Jan 2009, 8:07 PM
i needed to do stuff when drawers were shown / hidden, so i added callbacks to the show / hide methods:


Ext.override(Ext.ux.plugins.WindowDrawer, {
show : function(skipAnim, cb, scope) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.hidden = false;
this.onBeforeShow();
this.afterShow(!!skipAnim, cb, scope);
}
},

hide : function(skipAnim, cb, scope) {
if (this.hidden) {
return;
}

if (this.animate === true && !skipAnim) {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
this.el.disableShadow();
}

this.el.slideOut(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
if (typeof cb == 'function') {
cb.call(scope || this);
}
}
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.hide.call(this, null, cb, scope);
}

// REQUIRED!!!
this.hidden = true;
},

// private
afterShow : function(skipAnim, cb, scope) {
if (this.animate && !skipAnim) {
this.getEl().removeClass('x-panel-animated');
this.el.slideIn(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
// re-enable shadows after animation
this.el.enableShadow(true);
}

// REQUIRED!!
this.el.show(); // somehow forces the shadow to appear

if (typeof cb == 'function') {
cb.call(scope || this);
}
}
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.afterShow.call(this);

if (typeof cb == 'function') {
cb.call(scope || this);
}
}
}
});

HTH. :)

jay@moduscreate.com
6 Jan 2009, 1:31 PM
Nice addition dude.

hendricd
30 Jan 2009, 9:32 AM
@Jay -- I had a nasty need for Window shims (Layers) but there is a bug in layers that returns the wrong initial z-index for a shimmed Element. This override fixes that, places shimmed drawers properly behind a shimmed parent:



Ext.override(Ext.Layer, {
getZIndex : function(){
return this.zindex || parseInt((this.getShim()||this).getStyle("z-index"), 10) || 11000;
}
}); ( Will report that again separately )

Also, since Window can be rendered in ANY container element, I modified the parent.render event.

And, added parent expand/collapse tracking:



// private
init : function(parent) {
this.win = parent;
this.resizeHandles = this.side; // allow resizing only on 1 side (if resizing is allowed)
this.shim = parent.shim; //shim the kids too

parent.drawers = parent.drawers || {};
parent.drawers[this.side] = this; // add this WindowDrawer to the parent's drawer collection
parent.on({
scope: this,
destroy : this.destroy,
tofront : this.beforeShow,
toback : this.beforeShow,
ghost : this.onBeforeResize,
move : this.alignAndShow,
resize : this.alignAndShow,

render: function(p) {
// render WindowDrawer to parent's container
this.render(p.el.parent());
},
beforecollapse : function() {if(!this.hidden){ this.wasVisible=true; this.hide(true); }},
expand : function() {if(this.showAgain = this.wasVisible){ this.alignAndShow();}},
beforehide: function() { this.wasVisible = !this.hidden; this.hide(true); }
});
},

// private
afterShow : function(skipAnim, cb, scope) {
if (this.animate && !skipAnim) {
this.el.slideIn(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
// re-enable shadows after animation
this.el.enableShadow(true);
}

// REQUIRED!!
this.el.show(); // somehow forces the shadow to appear
if (typeof cb == 'function') {
cb.call(scope || this);
}
}
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.afterShow.call(this);
}
this.wasVisible = true;
},

;)

jay@moduscreate.com
30 Jan 2009, 9:45 AM
Awesome!! I'm going to add this to the distributable.

Thanks for sharing, bro!

benmclendon
3 Mar 2009, 6:10 AM
Jay,

First of all, I love Windrawers, Thanks for the contribution!!!!

It seems that creating the form fields first and passing them to the 'items' is cleaner, especially since I need them for both edit and add forms. This works with a formpanel in a new window but not the drawer.



var idHidden = new Ext.form.Hidden({fieldLabel: 'ID', name: 'id'});
var makeTextField = new Ext.form.TextField({fieldLabel: 'Make', name: 'make'});
var locationCombo = new Ext.form.ComboBox({
store: storeLocations,
fieldLabel: "Location",
name: 'location',
displayField: 'name',
valueField: 'id',
hiddenName: 'location',
mode: 'local',
triggerAction: 'all',
selectOnFocus: false
});



These are passed as items to the form panel and the formpanel is passed as items to the drawer.

Thanks!!

jay@moduscreate.com
3 Mar 2009, 6:13 AM
Hi Ben,

Can you please elaborate on "cleaner" ?

benmclendon
3 Mar 2009, 6:33 AM
By cleaner I mean.... I can create the form fields once with all their parameters, and then use them in multiple formpanels by reference in the items.



Ext.onReady(function(){

// Variables
var win;
var mySQLtable = 'it_assets';
var tableName ='ITAssets';

// MAIN data store
var storeGridRows = new Ext.data.JsonStore({
url: '/json/' + tableName + '.php',
root: mySQLtable,
totalProperty: 'total',
id: 'id',
fields: [ 'id', 'make', 'model', 'serial_number', 'location', 'user', 'notes', 'status', 'last_update', 'inactive'], /* List columns returned to store */
remoteSort: true,
autoload: true
});
storeGridRows.load({params:{start:0, limit:15, sort: 'id', dir: 'ASC'}});

// Combobox data stores
var storeEmployees = new Ext.data.JsonStore({
url: '/json/Employees.php',
root: "employees",
totalProperty: 'total',
id: 'empid',
fields: [ 'empid', 'fullname'],
remoteSort: false,
autoload: true
});
storeEmployees.load({params:{start:0, limit:999, sort: 'lname', dir: 'ASC'}});

var storeLocations = new Ext.data.JsonStore({
url: '/json/AllLocations.php',
root: "locations",
totalProperty: 'total',
id: 'id',
fields: [ 'id', 'name'],
remoteSort: false,
autoload: true
});
storeLocations.load({params:{start:0, limit:999, sort: 'lname', dir: 'ASC'}});

// Form Fields
var employeeCombo = new Ext.form.ComboBox({
store: storeEmployees,
fieldLabel: "User",
name: 'user',
displayField: 'fullname',
valueField: 'empid',
hiddenName: 'user',
mode: 'local',
triggerAction: 'all',
selectOnFocus: false
});
var locationCombo = new Ext.form.ComboBox({
store: storeLocations,
fieldLabel: "Location",
name: 'location',
displayField: 'name',
valueField: 'id',
hiddenName: 'location',
mode: 'local',
triggerAction: 'all',
selectOnFocus: false
});
var idHidden = new Ext.form.Hidden({fieldLabel: 'ID', name: 'id'});
var makeTextField = new Ext.form.TextField({fieldLabel: 'Make', name: 'make'});
var modelTextField = new Ext.form.TextField({fieldLabel: 'Model', name: 'model'});
var serialNumberTextField = new Ext.form.TextField({fieldLabel: 'Serial #', name: 'serial_number'});
var notesTextArea = new Ext.form.TextArea({fieldLabel: 'Notes', name: 'notes'});
var statusTextField = new Ext.form.TextField({fieldLabel: 'Status', name: 'status'});
var inactiveCheckBox = new Ext.form.Checkbox({fieldLabel: 'Inactive', name: 'inactive'});

// Grid Filters
var filters = new Ext.ux.grid.GridFilters({filters:[
{type: 'numeric', dataIndex: 'id'},
{type: 'string', dataIndex: 'make'},
{type: 'string', dataIndex: 'model'},
{type: 'string', dataIndex: 'serial_number'},
{type: 'numeric', dataIndex: 'location'},
{type: 'date', dataIndex: 'last_update'},
{type: 'boolean', dataIndex: 'inactive'}
]});

// Column Model
var cm = new Ext.grid.ColumnModel([{
dataIndex: 'id',
header: 'Id',
width: 40
}, {
dataIndex: 'make',
header: 'Make',
width: 60
}, {
dataIndex: 'model',
header: 'Model',
width: 100
}, {
dataIndex: 'serial_number',
header: 'Serial #',
width: 120
}, {
dataIndex: 'location',
header: 'Location',
width: 100
}, {
dataIndex: 'last_update',
header: 'Time Stamp',
width: 120
}]);
cm.defaultSortable = true;


// The Grid
var grid = new Ext.grid.GridPanel({
id: mySQLtable + 'Master',
store: storeGridRows,
ds: storeGridRows,
cm: cm,
enableColLock: false,
loadMask: true,
plugins: filters,
height: 415, // Window height minus 35
border : false,
stripeRows: true,
// Bottom Button Bar
bbar: new Ext.PagingToolbar({
store: storeGridRows,
pageSize: 15,
width: '100%',
plugins: filters
}),
// Top Button Bar
tbar: [{
text: 'Add Record',
tooltip: 'Click to add a new record',
iconCls:'icon-add',
handler: addRecord //what happens when user clicks on it
}]
});

// Edit Form in Drawer
var editFormPanel = new Ext.form.FormPanel({
url : '/json/crud' + tableName + '.php',
border : false,
autoScroll : true,
bodyStyle : 'background-color: #CAD9EC; padding: 2px;',
defaultType : 'textfield',
defaults : {
width : 150,
labelWidth : 80
},
items : [ idHidden, makeTextField, modelTextField, serialNumberTextField, locationCombo, employeeCombo, notesTextArea, statusTextField, inactiveCheckBox ],
// items : [{fieldLabel : 'Make', name : 'make'}],
buttons : [
{
text : 'save',
formBind : true,
// Function that fires when user clicks the button
handler:function(){
editFormPanel.getForm().submit({
method : 'POST',
params : {crud: "U"},
waitTitle : 'Processing',
waitMsg : 'Please Wait',
// Functions that fire (success or failure) when the server responds.
success:function(){
win.drawers.e.hide();
refreshGrid();
},
failure:function(form, action){
if(action.failureType == 'server'){
obj = Ext.util.JSON.decode(action.response.responseText);
Ext.Msg.alert('Process Failed!', obj.errors.reason);
}else{
Ext.Msg.alert('Warning!', 'The server is unreachable : ' + action.response.responseText);
}
chgSessionLocation.getForm().reset();
}
});
}
}, {
text : 'Delete',
handler : function() {
Ext.Msg.confirm('Confirm', 'Are you sure?', validateDelete);
}
}
]
}); // End of Edit Form Panel

grid.on('rowclick', function(grid, rowIndex, eventObj) {
var record = grid.getStore().getAt(rowIndex);
win.drawers.e.show();
editFormPanel.form.setValues(record.data);
});

// WinDrawer that contails the edit form
var rightDrawer = new Ext.ux.plugins.WindowDrawer({
size : 275,
side : 'e', // Can be n e s w (North, East, South, West)
animate : true,
plain : true,
layout : 'fit',
closable : true,
title : 'Edit record',
items : editFormPanel
});

// Window that contains the Grid
win = new Ext.Window({
layout : 'absolute',
x : 20,
y : 20,
width : 575, // Total Columns widths + 35
height : 450,
minHeight : 350,
closeAction : 'hide',
plain : true,
closable : false,
constrain : true,
resizable : false, // Required for now
title : 'Master File - ' + tableName,
buttonAlign : 'center',
items : grid,
plugins : [
rightDrawer
]
});

// Add Form
var addForm = new Ext.FormPanel({
labelWidth : 100,
url : '/json/crud' + tableName + '.php',
frame : true,
title : 'Add Record',
defaultType : 'textfield',
defaults : {
width : 150,
labelWidth : 80
},
monitorValid : true,
// The form fields
items : [ makeTextField, modelTextField, serialNumberTextField, locationCombo, employeeCombo, notesTextArea, statusTextField, inactiveCheckBox ],
// Define the buttons and their actions
buttons : [{
text : 'Save',
formBind : true,
// Function that fires when user clicks the button
handler : function(){
addForm.getForm().submit({
method : 'POST',
params : {crud: "C"},
waitTitle : 'Processing',
waitMsg : 'Please Wait',
// Functions that fire (success or failure) when the server responds.
success : function(){
addWin.hide();
refreshGrid();
},
failure : function(form, action){
if(action.failureType == 'server'){
obj = Ext.util.JSON.decode(action.response.responseText);
Ext.Msg.alert('Process Failed!', obj.errors.reason);
}else{
Ext.Msg.alert('Warning!', 'The server is unreachable : ' + action.response.responseText);
}
}
});
}
}, {
text : 'Cancel',
handler : function(){
addWin.hide();
}
}]
}); // End Add Form

// Create a window to wrap the form. The addForm object is passed to the 'items' collection.
var addWin = new Ext.Window({
layout : 'form',
width : 300,
height : 350,
closable : false,
resizable : false,
plain : true,
border : false,
shadow : true,
shadowOffset : 6,
items : [addForm]
});

// Functions for Button Actions
function addRecord() {
win.drawers.e.hide();
storeLocations.load({params:{start:0, limit:99, sort: 'name', dir: 'ASC'}});
storeEmployees.load({params:{start:0, limit:99, sort: 'fullname', dir: 'ASC'}});
addWin.show();
}
// Refresh Action
function refreshGrid() {
storeGridRows.reload();
}; // end refresh
// Delete Action
function validateDelete(bn){
if(bn == "yes") {
editFormPanel.getForm().submit({
method : 'POST',
params : {crud: "D"},
waitTitle : 'Processing',
waitMsg : 'Please Wait',
// Functions that fire (success or failure) when the server responds.
success : function(){
win.drawers.e.hide();
refreshGrid();
},
failure : function(form, action){
if(action.failureType == 'server'){
obj = Ext.util.JSON.decode(action.response.responseText);
Ext.Msg.alert('Process Failed!', obj.errors.reason);
}else{
Ext.Msg.alert('Warning!', 'The server is unreachable : ' + action.response.responseText);
}
}
})
} else {
Ext.Msg.alert('Notice','Operation Canceled. The record was not deleted');
}
} // End Delete Action
win.show(); // Show Grid Window
});

jay@moduscreate.com
3 Mar 2009, 6:39 AM
I'm confused. A child can only exist in one parent.


Paste this in firebug, click spawn a few times.


var idHidden = new Ext.form.Hidden({fieldLabel: 'ID', name: 'id'});
var makeTextField = new Ext.form.TextField({fieldLabel: 'Make', name: 'make'});
var modelTextField = new Ext.form.TextField({fieldLabel: 'Model', name: 'model'});
var serialNumberTextField = new Ext.form.TextField({fieldLabel: 'Serial #', name: 'serial_number'});
var notesTextArea = new Ext.form.TextArea({fieldLabel: 'Notes', name: 'notes'});
var statusTextField = new Ext.form.TextField({fieldLabel: 'Status', name: 'status'});
var inactiveCheckBox = new Ext.form.Checkbox({fieldLabel: 'Inactive', name: 'inactive'});

var newWindow = function() {

new Ext.Window({

layout : 'form',
height : 300,
width : 500,
defaults : {
anchor : '-10'
},
items : [ idHidden, makeTextField, modelTextField, serialNumberTextField, notesTextArea, statusTextField, inactiveCheckBox ],
buttons : [
{
text : 'spawn',
handler : newWindow
}
]
}).show()
}

newWindow()

Please watch: http://tdg-i.com/58/ext-js-screencast-005-containers-add-and-remove and you'll understand more of what i mean.

benmclendon
3 Mar 2009, 7:33 AM
OK... I get it. Great screencast!

I think I'm back on track now.

Thanks!

angeldimitrov
13 May 2009, 4:23 PM
Hi ! First thanks for sharing this wonderful plugin, i really love it. I found only one problem that i can't solve.
After moving the main window - the scrollbar in the drawer disappears.
Here is a small screencast with the same problem in your example:

http://screencast.com/t/dkUn7BnYLs

Thanks in advance!

angeldimitrov
17 May 2009, 5:34 PM
Anyone ?
Thanks a lot

jay@moduscreate.com
18 May 2009, 3:25 AM
Angel, what browser is that?

angeldimitrov
18 May 2009, 4:35 AM
Firefox 3.0.10, tested on Windows and Mac - same issue.
THANKS !

jay@moduscreate.com
18 May 2009, 4:38 AM
what version of Ext are you using this for? err was this the online example?

angeldimitrov
18 May 2009, 4:51 AM
Yes,
the screencast is from your online example, but i have the same problem with complete other configuration with Ext 2.2.1. I made the screencast with your example to make it easy for you to debug if needed.

THANKS !

elfantasy
19 May 2009, 1:46 AM
Yes,
the screencast is from your online example, but i have the same problem with complete other configuration with Ext 2.2.1. I made the screencast with your example to make it easy for you to debug if needed.

THANKS !

I noticed that this problem only happen on firefox, both 2.0.0.20 and 3.0.10
i tried another browsers (Chrome, IE7, Safari, Adobe AIR) to view the page, they are work fine.

pbarnes
19 May 2009, 7:22 AM
I noticed that this problem only happen on firefox, both 2.0.0.20 and 3.0.10
i tried another browsers (Chrome, IE7, Safari, Adobe AIR) to view the page, they are work fine.

I had this same problem and I tracked it down to an Ext CSS setting in 'ext-all.css'

.ext-gecko .x-panel-animated div{overflow:hidden!important;}If you remove the '!important' the scroll bars will stay whether you move the window or not. However, I have no idea what other parts of the framework this will impact, but I thought I'd pass it along.

I'm not a CSS expert or anything, but I didn't see a way to 'reverse' the '!important' declaration using CSS (which if you could,I suppose it would defeat the purpose).

This appears to be some sort of strange edge-case FF bug more than an Ext issue.

mystix
19 May 2009, 7:36 AM
Firefox scrollbar issues are caused by the calls to addClass('x-panel-animated') in onBeforeShow() and onBeforeHide().

to resolve this, simply call removeClass('x-panel-animated') in afterShow() and hide().

[edit]
i just realised i'm using a(n) (self-)updated version which differs slightly from the one @jay has up on his site.
i'll just post the full working plugin i'm using in my application now:


/*
Author : Jay Garcia
Site : http://tdg-i.com
Contact Info : jgarcia@tdg-i.com
Purpose : Window Drawers for Ext 2.x Ext.Window class, which emulates OS X behaviors
Contributors : Mystix, http://extjs.com/forum/member.php?u=1459
Hendricd, http://extjs.com/forum/member.php?u=8730

Warranty : none
Price : free
Version : ??? IT'S UP TO JAY TO DECIDE =)
Date : ???
*/

// Need to override the Window DnD to allow events to fire.
Ext.override(Ext.Window.DD, {
// private - used for dragging
startDrag : function() {
var w = this.win;
w.fireEvent('ghost', []);
this.proxy = w.ghost();
if (w.constrain !== false) {
var so = w.el.shadowOffset;
this.constrainTo(w.container, {right: so, left: so, bottom: so});
} else if (w.constrainHeader !== false) {
var s = this.proxy.getSize();
this.constrainTo(w.container, {right: -(s.width - this.headerOffsets[0]), bottom: -(s.height - this.headerOffsets[1])});
}
}
});


// Need to override the Window class to allow events to fire for front and back movement.
Ext.override(Ext.Window, {
setZIndex : function(index) {
var newZIndex = ++index;

if (this.modal) {
this.mask.setStyle("z-index", index);
}

this.el.setZIndex(newZIndex);
index += 5;

if (this.resizer) {
this.resizer.proxy.setStyle("z-index", ++index);
}
if (newZIndex > this.lastZIndex) {
this.fireEvent('tofront', this);
} else {
this.fireEvent('toback', this);
}
this.lastZIndex = index;
}
});

// Drawer Base Class
Ext.ux.plugins.WindowDrawer = Ext.extend(Ext.Window, {
closable : false,
resizable : false,

show : function(skipAnim, cb, scope) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.hidden = false;
this.onBeforeShow();
this.afterShow(!!skipAnim, cb, scope);
}
},

hide : function(skipAnim, cb, scope) {
if (this.hidden) {
return;
}

if (this.animate === true && !skipAnim) {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
this.el.disableShadow();
}

this.el.slideOut(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
this.el.removeClass('x-panel-animated');

if (typeof cb == 'function') {
cb.call(scope || this);
}
}
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.hide.call(this, null, cb, scope);
}

// REQUIRED!!!
this.hidden = true;
},

// private
init : function(parent) {
this.win = parent;
this.resizeHandles = this.side; // allow resizing only on 1 side (if resizing is allowed)
this.shim = parent.shim; // shim the kids too (modification by @hendricd -- http://extjs.com/forum/showthread.php?p=281140#post281140)

parent.drawers = parent.drawers || {};
parent.drawers[this.side] = this; // add this WindowDrawer to the parent's drawer collection
parent.on({
scope : this,
tofront : this.onBeforeShow,
toback : this.onBeforeShow,
ghost : this.onBeforeResize,
move : this.alignAndShow,
resize : this.alignAndShow,
destroy : this.destroy,

// modifications by @hendricd -- http://extjs.com/forum/showthread.php?p=281140#post281140
render : function(p) {
// render WindowDrawer to parent's container, if available
this.render(p.el.parent());
},
beforecollapse : function() {
if (!this.hidden) {
this.wasVisible = true;
this.hide(true);
}
},
expand : function() {
if (this.showAgain = this.wasVisible) {
this.alignAndShow();
}
},
beforehide: function() {
this.wasVisible = !this.hidden;
this.hide(true);
}
});
},

// private
initComponent : function() {
Ext.apply(this, {
frame : true,
draggable : false,
modal : false,
closeAction : 'hide',
alignToParams : {}
});

this.on({
scope : this,
beforeshow : this.onBeforeShow,
beforehide : this.onBeforeHide
});

if (this.size) {
if (this.side == 'e' || this.side == 'w') {
this.width = this.size;
} else {
this.height = this.size;
}
}

Ext.ux.plugins.WindowDrawer.superclass.initComponent.call(this);

},

// private
onBeforeResize : function() {
if (!this.hidden) {
this.showAgain = true;
}
this.hide(true);
},

// private
onBeforeHide : function() {
if (this.animate) {
this.getEl().addClass('x-panel-animated');
}
},


// private
onBeforeShow : function() {
if (this.animate) {
this.el.addClass('x-panel-animated');
}
this.setAlignment();
this.setZIndex(this.win.el.getZIndex() - 3);
},

// private
afterShow : function(skipAnim, cb, scope) {
if (this.animate && !skipAnim) {
this.el.slideIn(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
this.el.removeClass('x-panel-animated');

if (this.el.shadow) { // honour WindowDrawer's "shadow" config
// re-enable shadows after animation
this.el.enableShadow(true);
}

// REQUIRED!!
this.el.show(); // somehow forces the shadow to appear

if (typeof cb == 'function') {
cb.call(scope || this);
}
}
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.afterShow.call(this);

if (typeof cb == 'function') {
cb.call(scope || this);
}
}

// modification by @hendricd -- http://extjs.com/forum/showthread.php?p=281140#post281140
this.wasVisible = true;
},

// private
alignAndShow : function() {
this.setAlignment();

if (this.showAgain) {
this.show(true);
}
this.showAgain = false;
},

// private
setAlignment: function() {
switch(this.side) {
case 'n' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [5, (this.el.getComputedHeight() * -1) + 5],
slideDirection : 'b'
});
break;

case 's' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'bl',
alignToXY : [5, (Ext.isIE6)? -2 : -7],
slideDirection : 't'
});
break;

case 'e' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tr',
alignToXY : [-5, 5],
slideDirection : 'l'
});
break;

case 'w' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [(this.el.getComputedWidth() * -1) + 5, 5],
slideDirection : 'r'
});
break;
}

if (!this.hidden) {
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY);

// Simple fix for IE, where the bwrap doesn't properly resize.
if (Ext.isIE) {
this.bwrap.hide();
this.bwrap.show();
}
}

// force doLayout()
this.doLayout();
},


// private
toFront: function() {
this.win.toFront(); // first bring WindowDrawer's parent to the front
return this;
}
});

Ext.reg('windowdrawer', Ext.ux.plugins.WindowDrawer);

@jay, feel free to use this if you wish :)

pbarnes
19 May 2009, 9:08 AM
Firefox scrollbar issues are caused by the calls to addClass('x-panel-animated') in onBeforeShow() and onBeforeHide().

to resolve this, simply call removeClass('x-panel-animated') in afterShow() and hide().

[edit]
i just realised i'm using a(n) (self-)updated version which differs slightly from the one @jay has up on his site.
i'll just post the full working plugin i'm using in my application now:


Thanks for the heads up Mystix. I was using the version off of @jay's site, so all I needed to do was move the 'removeClass' function after the 'else' of afterShow, like so:



// private
afterShow : function(skipAnim) {
if (this.animate && !skipAnim) {
// this.getEl().removeClass('x-panel-animated'); // moved after else below
this.el.slideIn(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
// re-enable shadows after animation
this.el.enableShadow(true);
}

// REQUIRED!!
this.el.show(); // somehow forces the shadow to appear
}
});
}
else {

Ext.ux.plugins.WindowDrawer.superclass.afterShow.call(this);
}
this.getEl().removeClass('x-panel-animated');
},
.. because the animation code isn't called after the panel is already shown (but just moved), but the class added in onBeforeShow() still needs to be removed.

angeldimitrov
19 May 2009, 9:31 AM
Thank you all ! This solved the issue !

jay@moduscreate.com
19 May 2009, 9:35 AM
Many thanks Marc. Been crazy busy with the book and all to even look at this much. I'm going to post this on my blog and about it.

mystix
19 May 2009, 10:40 AM
I'm going to post this on my blog and about it.

i shall just pretend i don't know about the typo. :))

jay@moduscreate.com
19 May 2009, 11:01 AM
what typo? :)

tobiu
22 May 2009, 4:57 AM
hi jay,

i like your plugin (as usual ;)).
any reason it is under gpl and not lgpl?


kind regards, tobiu

jay@moduscreate.com
29 May 2009, 6:16 AM
Hi Tobiu,

Is LGPL the totaly free one? if so, i'll add that to my files.

jay@moduscreate.com
29 May 2009, 6:16 AM
Mark, may i have your permission to add your changes to an LGPL version of this on my site?

mystix
29 May 2009, 7:45 AM
Mark, may i have your permission to add your changes to an LGPL version of this on my site?

be my guest :D

p.s. btw, how's the book coming along?
(haven't bought it 'cos i seldom read :"> )

p.s.s it's marc, not mark ;)

hendricd
29 May 2009, 10:47 AM
p.s.s it's marc, not mark ;)

Cumon! It's just a name. It's still Mystix, no matter how it's (mis)spelled. ;)

mystix
29 May 2009, 10:52 AM
Cumon! It's just a name. It's still Mystix, no matter how it's (mis)spelled. ;)

right on, henry :))

hendricd
29 May 2009, 10:59 AM
That's 'hindlick' to you! :))

tobiu
2 Jun 2009, 1:43 PM
hi jay,

the "totally free one" would be the MIT-licence.
LGPL means, that you are allowed to use it in commercial products, but if you change the code of the plugin / ux, you have to post these changes and allow others to use them as well. GPL is a bit problematic, because under that terms you have to publish all of your javascript-code using that ux, which is something no one who is develloping a commercial app (or planing to do so) would consider.

ok, this description is more than a bit simplified, but its getting late here ;)


good night, tobiu

gurufaction
10 Jun 2009, 7:53 AM
Is Ext.Window.Drawer compatible with Ext 3.0rc2?

jay@moduscreate.com
10 Jun 2009, 8:14 AM
Is Ext.Window.Drawer compatible with Ext 3.0rc2?

waiting for stable

varsos
22 Jun 2009, 11:50 AM
When the window displays over a flash object, the "drawer' slides out ok, but when it slides in, the shim behind it does not get redrawn, leaving a while box.

Any ideas?

fangzhouxing
22 Jun 2009, 6:04 PM
Great!

gurufaction
9 Jul 2009, 2:26 PM
When will we have Window Drawer for Ext JS 3.0?

jay@moduscreate.com
9 Jul 2009, 4:40 PM
care to fund it?

Kidding.

On a serious note, Ive been pushing forward with Ext JS in Action, which means that these types of projects take a back seat.

mystix
9 Jul 2009, 10:00 PM
When will we have Window Drawer for Ext JS 3.0?

i think the more appropriate question would be:
have you even tried to use it with Ext 3.0?

gurufaction
10 Jul 2009, 5:38 AM
@jgarcia

I understand. I am really excited about the book.

@mystix

I haven't tried it with Ext 3 so I will give it a try. How different is Ext 3 compared to Ext 2?

jay@moduscreate.com
10 Jul 2009, 6:05 AM
The short answer is 'not very'. But there is some code for the windowdrawers that required some private overrides, so I cannot guarantee the compatability.

Anyone know how i can clone myself like 5x over?

gurufaction
16 Jul 2009, 9:50 AM
I was able to get WindowDrawer working with Ext 3.0 after a small change. There is no getZIndex() method on Ext.Element and for some reason the window drawer appears in front of the panel unless I change ' - 3' to '- 5'.

Original:


this.setZIndex(this.win.el.getZIndex() - 3);


Change:


this.setZIndex(this.win.el.getStyle("z-index") - 5);

mystix
16 Jul 2009, 9:53 AM
I was able to get WindowDrawer working with Ext 3.0 after a small change. There is no getZIndex() method on Ext.Element and for some reason the window drawer appears in front of the panel unless I change ' - 3' to '- 5'.

Original:


this.setZIndex(this.win.el.getZIndex() - 3);


Change:


this.setZIndex(this.win.el.getStyle("z-index") - 5);


good job =)
is that change backwards compatible?
(iirc getZIndex() was included as an override in the WindowDrawer code)

gurufaction
16 Jul 2009, 11:42 AM
I spoke too soon. Even though the Window Drawer works in both IE7 and FF3 the drawer appears behind the main panel correctly in IE7 but appears in front in FF3. I seems they're some issues with 'z-index' being set to 'auto' in FF3. I will research further :)

squarefan
29 Jul 2009, 1:11 AM
Hi,

first of all thank you soo much for this great extension! I encountered a problem though and wanted to know if you may have a fix for that.

I am using it currently within a Desktop environment...

So if I first open a window and extend the drawer, then open a second windows (e.g. form with update functionality) and place it over window drawer everything is fine. Now I update something, the waiting message (modal) kicks in and the drawer jumps in front over all other currently opened windows.

I have to first select the "parent" form to get a focus and then close the drawer so that it jumps again behind the "parent". Did somebody else encounter this problem or is there a fix for that?

thanks in advance,
Alex

border9
29 Jul 2009, 8:07 AM
Is it possible to make it so that a different drawer will open on the same side as a current one.

IE: 2 Drawers, One with one id, 2nd with another id but both open on the same side when you click on a button or call it forward?

Thanks

squarefan
20 Aug 2009, 10:09 PM
Hi,just wanted to ask again if somebody already has a fix that the drawer stays behind the parent panel at all times -- as described above, sometimes when moving the window or another widget sets the screen to modal (e.g. form.submit/load) the drawer - when shown - jumps in front of all other panels!

help would be greatly appreciated!!

cheers,
squarefan

mystix
20 Aug 2009, 10:17 PM
Hi,just wanted to ask again if somebody already has a fix that the drawer stays behind the parent panel at all times -- as described above, sometimes when moving the window or another widget sets the screen to modal (e.g. form.submit/load) the drawer - when shown - jumps in front of all other panels!

help would be greatly appreciated!!

cheers,
squarefan

which code are you using?

squarefan
20 Aug 2009, 10:29 PM
wow quick answer!

i used the one from Jay's HP - but also looked through the forums. Heres the extension file:



/*
Author : Jay Garcia
Site : http://tdg-i.com
Contact Info : jgarcia@tdg-i.com
Purpose : Window Drawers for Ext 2.x Ext.Window class, which emulates OS X behaviors
Contributors : Mystix, http://extjs.com/forum/member.php?u=1459
Hendricd, http://extjs.com/forum/member.php?u=8730

Warranty : none
Price : free
Version : 1.0 Beta 1
Date : 11/23/2008
*/

// Need to override the Window DnD to allow events to fire.
Ext.override(Ext.Window.DD, {
// private - used for dragging
startDrag : function() {
var w = this.win;
w.fireEvent('ghost', []);
this.proxy = w.ghost();
if (w.constrain !== false) {
var so = w.el.shadowOffset;
this.constrainTo(w.container, {right: so, left: so, bottom: so});
} else if (w.constrainHeader !== false) {
var s = this.proxy.getSize();
this.constrainTo(w.container, {right: -(s.width - this.headerOffsets[0]), bottom: -(s.height - this.headerOffsets[1])});
}
}
});


// Need to override the Window class to allow events to fire for front and back movement.
Ext.override(Ext.Window, {
setZIndex : function(index) {
var newZIndex = ++index;

if (this.modal) {
this.mask.setStyle("z-index", index);
}

this.el.setZIndex(newZIndex);
index += 5;

if (this.resizer) {
this.resizer.proxy.setStyle("z-index", ++index);
}
if (newZIndex > this.lastZIndex) {
this.fireEvent('tofront', this);
} else {
this.fireEvent('toback', this);
}
this.lastZIndex = index;
}
});

Ext.ns('Ext.ux.plugins');


// Drawer Base Class
Ext.ux.plugins.WindowDrawer = Ext.extend(Ext.Window, {
closable : false,
resizable : false,

// listener for formatting fix
listeners: {
beforeshow: function(self) {
self.getEl().addClass('x-panel-animated');
},

beforehide: function(self) {
self.getEl().addClass('x-panel-animated');
},

show: function(self) {
self.getEl().removeClass('x-panel-animated');
}
},

show : function(skipAnim) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.hidden = false;
this.onBeforeShow();
this.afterShow(!!skipAnim);
}
},

hide : function(skipAnim) {
if (this.hidden) {
return;
}

if (this.animate === true && !skipAnim) {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
this.el.disableShadow();
}

this.el.slideOut(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.hide.call(this);
}

// REQUIRED!!!
this.hidden = true;
},


// private
init : function(parent) {
this.win = parent;
this.resizeHandles = this.side; // allow resizing only on 1 side (if resizing is allowed)

parent.drawers = parent.drawers || {};
parent.drawers[this.side] = this; // add this WindowDrawer to the parent's drawer collection
parent.on({
scope : this,
tofront : this.onBeforeShow,
toback : this.onBeforeShow,
ghost : this.onBeforeResize,
move : this.alignAndShow,
resize : this.alignAndShow,
beforedestroy : this.destroy,
render : function(p) {
// render WindowDrawer to parent's container, if available
this.render(p.ownerCt? p.ownerCt.getEl() : Ext.getBody());
},

beforehide: function() {
this.hide(true);
}
});
},

// private
initComponent : function() {
Ext.apply(this, {
frame : true,
draggable : false,
modal : false,
closeAction : 'hide',
alignToParams : {}
});

this.on({
beforeshow : {
scope : this,
fn : this.onBeforeShow
},
beforehide: {
scope : this,
fn : this.onBeforeHide
}
});

if (this.size) {
if (this.side == 'e' || this.side == 'w') {
this.width = this.size;
} else {
this.height = this.size;
}
}

Ext.ux.plugins.WindowDrawer.superclass.initComponent.apply(this);

},

// private
onBeforeResize : function() {
if (!this.hidden) {
this.showAgain = true;
}
this.hide(true);
},

//private
onBeforeHide : function() {
if (this.animate) {
this.getEl().addClass('x-panel-animated');
}
},


// private
onBeforeShow : function() {
this.el.addClass('x-panel-animated');
this.setAlignment();
this.setZIndex(this.win.el.getZIndex() - 3);
},

// private
afterShow : function(skipAnim) {
if (this.animate && !skipAnim) {
// this.getEl().removeClass('x-panel-animated'); //
this.el.slideIn(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
// re-enable shadows after animation
this.el.enableShadow(true);
}

// REQUIRED!!
this.el.show(); // somehow forces the shadow to appear
}
});
}
else {

Ext.ux.plugins.WindowDrawer.superclass.afterShow.call(this);
}
this.getEl().removeClass('x-panel-animated'); // moved here according to forum
},

// private
alignAndShow : function() {
this.setAlignment();

if (this.showAgain) {
this.show(true);
}
this.showAgain = false;
},

// private
setAlignment: function() {
switch(this.side) {
case 'n' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [5, (this.el.getComputedHeight() * -1) + 5],
slideDirection : 'b'
});
break;

case 's' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'bl',
alignToXY : [5, (Ext.isIE6)? -2 : -7],
slideDirection : 't'
});
break;

case 'e' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tr',
alignToXY : [-5, 5],
slideDirection : 'l'
});
break;

case 'w' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [(this.el.getComputedWidth() * -1) + 5, 5],
slideDirection : 'r'
});
break;
}

if (!this.hidden) {
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY);

// Simple fix for IE, where the bwrap doesn't properly resize.
if (Ext.isIE) {
this.bwrap.hide();
this.bwrap.show();
}
}

// force doLayout()
this.doLayout();
},


// private
toFront: function() {
this.win.toFront(); // first bring WindowDrawer's parent to the front
//this.setZIndex(this.win.el.getZIndex() - 3); // then place WindowDrawer behind its parent
return this;
}
});



cheers,
Alex

mystix
20 Aug 2009, 10:33 PM
wow quick answer!

i used the one from Jay's HP - but also looked through the forums. Heres the extension file:

try the one from post #90.
i'm not sure if @jay's already updated the one on his site.

squarefan
20 Aug 2009, 10:58 PM
Mystix,

thanks for the tip. Unfortunately still behaving the same way --> the moment you move the window around a little bit and a modal state is introduced again the drawer will jump on top of all other.


here a quick picture i just took. To let it jump back to the back you first have to select the parent window and then the other one to display it correctly:
http://lychee.cc/dev/drawer_problem.png


cheers,
Alex

jay@moduscreate.com
21 Aug 2009, 2:24 AM
try the one from post #90.
i'm not sure if @jay's already updated the one on his site.
This is already on my tall list of things go to :)

squarefan
10 Sep 2009, 10:11 PM
Hi@all,

just wanted to ask if anybody has a clue how to avoid the internet explorer drawer jumping "bug" <-- two posts up.

just can't figure out how to let the window behave correctly:

IE: drawers jumps in front of all other windows
FireFox: items move to the "right" by 50% after another window is brought to front. When the window is moved slightly, the problem corrects itself.

thanks in advance,
Alex

mtpaper
5 Oct 2009, 7:09 PM
Hi
I am not a designer or developer. I'm just starting to have an application developed, and I think EXTjs would work well for the project.

Can a drawer have tabs? Or do I need to have a button-bar on my primary window, and each button would call-forth a different drawer?

Example:
primary grid is contact names
drawer for addresses (multiple addresses per contact)
drawer for phone numbers (multiple per contact)
drawer for email addresses (multiple per contact)

This is just a small piece of a larger project.
Thanks
Marion

mystix
5 Oct 2009, 9:37 PM
Hi
I am not a designer or developer. I'm just starting to have an application developed, and I think EXTjs would work well for the project.

Can a drawer have tabs? Or do I need to have a button-bar on my primary window, and each button would call-forth a different drawer?


drawers are just Ext.Windows. They can contain anything a stock Ext.Window can contain.
so yes, tabpanels in drawers are good to go.

jay@moduscreate.com
6 Oct 2009, 3:33 AM
drawers are just Ext.Windows. They can contain anything a stock Ext.Window can contain.
so yes, tabpanels in drawers are good to go.

you're letting out my secret :s


Kidding.

I am hoping to spend some time on this code soon, documenting and hopefully making an ext-doc page for it.

jay@moduscreate.com
6 Oct 2009, 3:34 AM
Hi@all,

just wanted to ask if anybody has a clue how to avoid the internet explorer drawer jumping "bug" <-- two posts up.

just can't figure out how to let the window behave correctly:

IE: drawers jumps in front of all other windows
FireFox: items move to the "right" by 50% after another window is brought to front. When the window is moved slightly, the problem corrects itself.

thanks in advance,
Alex


Hey dude, are you using the latest code?

mystix
6 Oct 2009, 7:31 AM
you're letting out my secret :s

bite me >:)

jay@moduscreate.com
6 Oct 2009, 7:36 AM
feisty!!

http://s2.buzzfeed.com/static/imagebuzz/web02/2009/2/15/19/the-matrix-cat-fight-10633-1234742594-0.jpg

mystix
6 Oct 2009, 7:40 AM
* ouch *

your photo-hunting skills remain unmatched to date! :)

jay@moduscreate.com
6 Oct 2009, 7:47 AM
lol. at least i can do something right :P

Dumbledore
3 Dec 2009, 1:11 AM
Hi,

i just download the last package from your site. Is this code really right?


Ext.ux.plugins.WindowDrawer = Ext.extend(Ext.Window, {
closable : false,
resizable : false,

show : function(skipAnim) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.hidden = false;
this.onBeforeShow();
this.afterShow(!!skipAnim); // <---
}
},

I must be only one exclamation mark, or?

mystix
3 Dec 2009, 2:08 AM
Hi,

i just download the last package from your site. Is this code really right?


Ext.ux.plugins.WindowDrawer = Ext.extend(Ext.Window, {
closable : false,
resizable : false,

show : function(skipAnim) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.hidden = false;
this.onBeforeShow();
this.afterShow(!!skipAnim); // <---
}
},

I must be only one exclamation mark, or?

yes it's correct.
a double negation in javascript coerces any value into a real boolean value.

are you experiencing actual problems with that line, or are you just stating an observation?

Dumbledore
22 Dec 2009, 4:26 AM
ok, i only look in the code. Have no problems with this line...

squarefan
22 Dec 2009, 5:59 AM
Hey dude, are you using the latest code?

@Jay

yes i think so, i took the code from page #90, as mystix mentioned that this would be the latest build. I also tested some time ago with various builds from your web page and forum posts.. but the problem persits.

Is there an updated version after November 23rd (Jay's webpage) or can you replicate the behavious as described by my previous post?

cheers,
Alex

almerelc
18 Feb 2010, 12:55 PM
Love to see this migrated to ext 3.x ( it works well in 3 accept for some minor issues )

jay@moduscreate.com
18 Feb 2010, 12:57 PM
if you enumerate those issues, I can look at it within the next few weeks :)

mystix
18 Feb 2010, 8:20 PM
if you enumerate those issues, I can look at it within the next few weeks :)

ditto. i'm sure it'll be fun. :)

Peter88
19 Feb 2010, 4:17 PM
The attached file contains slight modifications to original that provided alternate behaviour for when parent window is maximised. And is (mostly) compatible with Ext 3.x except haven't checked/tested DD compatibility. NB search for comment with "+X+" string within comments to view changes.



/*
Author : Jay Garcia
Site : http://tdg-i.com
Contact Info : jgarcia@tdg-i.com
Purpose : Window Drawers for Ext 2.x Ext.Window class, which emulates OS X behaviors
Contributors : Mystix, http://extjs.com/forum/member.php?u=1459
Hendricd, http://extjs.com/forum/member.php?u=8730
Warranty : none
Price : free
Version : 1.0 Beta 1
Date : 11/23/2008
*/

// Need to override the Window DnD to allow events to fire.
Ext.override(Ext.Window.DD, {
// private - used for dragging
startDrag : function() {
var w = this.win;
w.fireEvent('ghost', []);
this.proxy = w.ghost();
if (w.constrain !== false) {
var so = w.el.shadowOffset;
this.constrainTo(w.container, {right: so, left: so, bottom: so});
} else if (w.constrainHeader !== false) {
var s = this.proxy.getSize();
this.constrainTo(w.container, {right: -(s.width - this.headerOffsets[0]), bottom: -(s.height - this.headerOffsets[1])});
}
}
});


// Need to override the Window class to allow events to fire for front and back movement.
Ext.override(Ext.Window, {
setZIndex : function(index) {
var newZIndex = ++index;

if (this.modal) {
this.mask.setStyle("z-index", index);
}

this.el.setZIndex(newZIndex);
index += 5;

if (this.resizer) {
this.resizer.proxy.setStyle("z-index", ++index);
}
if (newZIndex > this.lastZIndex) {
this.fireEvent('tofront', this);
} else {
this.fireEvent('toback', this);
}
this.lastZIndex = index;
}
});

Ext.ns('Ext.ux');

// Drawer Base Class
Ext.ux.WindowDrawer = Ext.extend(Ext.Window, {
closable : false,
resizable : false,

show : function(skipAnim) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.hidden = false;
this.onBeforeShow();
this.afterShow(!!skipAnim);
}
},

hide : function(skipAnim) {
if (this.hidden) {
return;
}

if (this.animate === true && !skipAnim) {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
this.el.disableShadow();
}

this.el.slideOut(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function(){ //+X+ ADDED
this.fireEvent('hide',this); //+X+ Added
}
});
} else {
Ext.ux.WindowDrawer.superclass.hide.call(this);
}

// REQUIRED!!!
this.hidden = true;
},

// private
init : function(parent) {
this.win = parent;
// Set resize handles to this.side and it's opposite for when window is maximised.
//+X+ ADDED START
if (this.side == 'e' || this.side == 'w'){
this.resizeHandles = 'e w';
}
else{
this.resizeHandles = 'n s';
}
//+X+ END ADDED
//this.resizeHandles = this.side; // allow resizing only on 1 side (if resizing is allowed)

parent.drawers = parent.drawers || {};
parent.drawers[this.side] = this; // add this WindowDrawer to the parent's drawer collection
parent.on({
scope : this,
tofront : this.onBeforeShow,
toback : this.onBeforeShow,
ghost : this.onBeforeResize,
move : this.alignAndShow,
resize : this.alignAndShow,
maximize : this.onToggleMaximize,
restore : this.onToggleMaximize,
beforedestroy : this.destroy,
render : function(p) {
// render WindowDrawer to parent's container, if available
this.render(p.ownerCt? p.ownerCt.getEl() : Ext.getBody());
},

beforehide: function() {
this.hide(true);
}
});
},

// private
initComponent : function() {
Ext.apply(this, {
frame : true,
draggable : false,
modal : false,
closeAction : 'hide',
alignToParams : {}
});

this.on({
beforeshow : {
scope : this,
fn : this.onBeforeShow
},
beforehide: {
scope : this,
fn : this.onBeforeHide
}
});

if (this.size) {
if (this.side == 'e' || this.side == 'w') {
this.width = this.size;
} else {
this.height = this.size;
}
}

Ext.ux.WindowDrawer.superclass.initComponent.apply(this);

},

//+X+ ADDED Method START
// private
onToggleMaximize : function() {
if (!this.hidden) {
this.showAgain = true;
}
this.hide(true);
this.alignAndShow.defer(100,this);
},
//+X+ ADDED Method END

// private
onBeforeResize : function() {
if (!this.hidden) {
this.showAgain = true;
}
this.hide(true);
},

//private
onBeforeHide : function() {
if (this.animate) {
this.getEl().addClass('x-panel-animated');
}
},

// private
onBeforeShow : function() {
this.el.addClass('x-panel-animated');
this.setAlignment();
this.setZIndex(this.win.el.getZIndex() + (this.win.maximized ? 3 : -3)); //+X+ Changed so that in front if maxed
},

// private
afterShow : function(skipAnim) {
if (this.animate && !skipAnim) {
this.getEl().removeClass('x-panel-animated');
this.el.slideIn(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
// re-enable shadows after animation
this.el.enableShadow(true);
}
// REQUIRED!!
this.el.show(); // somehow forces the shadow to appear
this.fireEvent('show',this); //+X+ Added
}
});
}
else {
Ext.ux.WindowDrawer.superclass.afterShow.call(this);
}
},

// private
alignAndShow : function() {
this.setAlignment();
if (this.showAgain) {
this.show(true);
}
this.showAgain = false;
},

// private
setAlignment: function() {
var isMaxed = this.win.maximized; //+X+ Added isMaxed variable here and wherever referenced in below
switch(this.side) {
case 'n' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : isMaxed ? [5, (Ext.isIE6)? 5 : -2] : [5, (this.el.getComputedHeight() * -1) + 5],
slideDirection : isMaxed? 't' : 'b'
});
break;

case 's' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'bl',
alignToXY : isMaxed ? [5, (this.el.getComputedHeight() * -1) - 1] : [5, (Ext.isIE6)? -2 : -7],
slideDirection : isMaxed? 'b' : 't'
});
break;

case 'e' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tr',
alignToXY : isMaxed ? [(this.el.getComputedWidth() * -1) + 5, 10] : [-5, 5],
slideDirection : isMaxed ? 'r' : 'l'
});
break;

case 'w' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : isMaxed ? [-5, 10] : [(this.el.getComputedWidth() * -1) + 5, 5],
slideDirection : isMaxed? 'l' : 'r'
});
break;
}

if (!this.hidden) {
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY);

// Simple fix for IE, where the bwrap doesn't properly resize.
if (Ext.isIE) {
this.bwrap.hide();
this.bwrap.show();
}
}

// force doLayout()
this.doLayout();
},


// private
toFront: function() {
if(!this.win.maximized){ //+X+ Added
this.win.toFront(); // first bring WindowDrawer's parent to the front
} else { //+X+ Added
this.setZIndex(this.win.el.getZIndex() + 3); //+X+ Added
}
return this;
}
});

// register ptype
Ext.preg('windowdrawer', Ext.ux.WindowDrawer);

// backwards compat
Ext.WindowDrawer = Ext.ux.WindowDrawer;

almerelc
21 Feb 2010, 12:27 PM
Anyone mentioned that when a window is DD form labelwidth is changed, and that tbar buttons are moved to a different spott in the bar?

My window has paddings and form also... could that harm the window?

greets

[EDIT]

Never mind after the fix a few post-pages back ( pasting "this.getEl().removeClass('x-panel-animated');" a few lines down as described ) it works allmost perfect in 3.x ( accept for the z-index bug ). But hey.... i dont care :)

darkwolfe
15 Mar 2010, 4:41 PM
Great plugin. I find myself using it everywhere an extra popup window or where i would've normally used a border layout. I noticed, when using the desktop, that on some windows, if the drawer is hidden and the window is moved, the contents of the drawer would show up on the left side of the document. i fixed this issue by commenting out the line that would align the drawer to the document body if the drawer was hidden in the setAlignAndShow function. Perhaps there is a reason why the drawer would need to be aligned if it's not being shown, but i can't think of a reason to do anything to it if you can't see it.

dudecool
5 Apr 2010, 8:02 PM
Hi, Once the drawer is loaded how do i make the whole(parent window+drawer) thing center to the screen? currently i am using 3.1.1 and am unable to drag the parent window when i drag the window it comes back the initial location any idea what might be causing this? does the new beta version supports extjs 3.2?

dudecool
5 Apr 2010, 8:57 PM
the drag problem is solved by using the code given by "Peter88 (http://www.extjs.com/forum/member.php?u=97414)" still any idea on how to center the window with drawer?

Boxcopter
11 May 2010, 7:12 AM
Thanks! This might fit exactly what I need. Excellent job!

juljupy
18 May 2010, 8:29 PM
what about createGhost method to implement, when dragging the parent window it also shows drawer's ghost like www.kohibe.com sidepanel, i'd be cool.

b091
4 Jun 2010, 2:00 AM
After upgrading Extjs from 3.0 to 3.2.1 the plugin crush with an error:




this.el is undefined
this.el.addClass('x-panel-animated');

Ext.ux.plugins.WindowDrawer.js (line 173)



It looks like the plugin is trying to add class to element wich has not been rendered yet.
I tried adding forceLayout:true, but it don't change anything

b091
7 Jun 2010, 1:21 AM
Solved.

to make it work with 3.2.1 you need to add one line inside init()

this.render(this.ownerCt? this.ownerCt.getEl() : Ext.getBody());


Complete plugin code:


/*
Author : Jay Garcia
Site : http://tdg-i.com
Contact Info : jgarcia@tdg-i.com
Purpose : Window Drawers for Ext 2.x Ext.Window class, which emulates OS X behaviors
Contributors : Mystix, http://extjs.com/forum/member.php?u=1459
Hendricd, http://extjs.com/forum/member.php?u=8730

Warranty : none
Price : free
Version : 1.0 Beta 1
Date : 11/23/2008
*/

// Need to override the Window DnD to allow events to fire.
Ext.override(Ext.Window.DD, {
// private - used for dragging
startDrag : function() {
var w = this.win;
w.fireEvent('ghost', []);
this.proxy = w.ghost();
if (w.constrain !== false) {
var so = w.el.shadowOffset;
this.constrainTo(w.container, {right: so, left: so, bottom: so});
} else if (w.constrainHeader !== false) {
var s = this.proxy.getSize();
this.constrainTo(w.container, {right: -(s.width - this.headerOffsets[0]), bottom: -(s.height - this.headerOffsets[1])});
}
}
});


// Need to override the Window class to allow events to fire for front and back movement.
Ext.override(Ext.Window, {
setZIndex : function(index) {
var newZIndex = ++index;

if (this.modal) {
this.mask.setStyle("z-index", index);
}

this.el.setZIndex(newZIndex);
index += 5;

if (this.resizer) {
this.resizer.proxy.setStyle("z-index", ++index);
}
if (newZIndex > this.lastZIndex) {
this.fireEvent('tofront', this);
} else {
this.fireEvent('toback', this);
}
this.lastZIndex = index;
}
});

Ext.ns('Ext.ux.plugins');

// Drawer Base Class
Ext.ux.plugins.WindowDrawer = Ext.extend(Ext.Window, {
closable : false,
resizable : false,

show : function(skipAnim) {
if (this.hidden && this.fireEvent("beforeshow", this) !== false) {
this.hidden = false;
this.onBeforeShow();
this.afterShow(!!skipAnim);
}
},

hide : function(skipAnim) {
if (this.hidden) {
return;
}

if (this.animate === true && !skipAnim) {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
this.el.disableShadow();
}

this.el.slideOut(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25
});
} else {
Ext.ux.plugins.WindowDrawer.superclass.hide.call(this);
}

// REQUIRED!!!
this.hidden = true;

this.fireEvent("afterhide", this);
},

// private
init : function(parent) {
this.win = parent;
this.render(this.ownerCt? this.ownerCt.getEl() : Ext.getBody());
this.resizeHandles = this.side; // allow resizing only on 1 side (if resizing is allowed)

parent.drawers = parent.drawers || {};
parent.drawers[this.side] = this; // add this WindowDrawer to the parent's drawer collection
parent.on({
scope : this,
tofront : this.onBeforeShow,
toback : this.onBeforeShow,
ghost : this.onBeforeResize,
move : this.alignAndShow,
resize : this.alignAndShow,
beforedestroy : this.destroy,
render : function(p) {
// render WindowDrawer to parent's container, if available
this.render(p.ownerCt? p.ownerCt.getEl() : Ext.getBody());
},

beforehide: function() {
this.hide(true);
}
});
},

// private
initComponent : function() {
Ext.apply(this, {
frame : true,
draggable : false,
modal : false,
closeAction : 'hide',
alignToParams : {}
});

this.on({
beforeshow : {
scope : this,
fn : this.onBeforeShow
},
beforehide: {
scope : this,
fn : this.onBeforeHide
}
});

if (this.size) {
if (this.side == 'e' || this.side == 'w') {
this.width = this.size;
} else {
this.height = this.size;
}
}

Ext.ux.plugins.WindowDrawer.superclass.initComponent.apply(this);

},

// private
onBeforeResize : function() {
if (!this.hidden) {
this.showAgain = true;
}
this.hide(true);
},

//private
onBeforeHide : function() {
if (this.animate) {
this.getEl().addClass('x-panel-animated');
}
},


// private
onBeforeShow : function() {
this.el.addClass('x-panel-animated');
this.setAlignment();
this.setZIndex(this.win.el.getZIndex() - 3);
},

// private
afterShow : function(skipAnim) {
if (this.animate && !skipAnim) {
this.getEl().removeClass('x-panel-animated');
this.el.slideIn(this.alignToParams.slideDirection, {
scope : this,
duration : this.animDuration || .25,
callback : function() {
if (this.el.shadow) { // honour WindowDrawer's "shadow" config
// re-enable shadows after animation
this.el.enableShadow(true);
}

// REQUIRED!!
this.el.show(); // somehow forces the shadow to appear
}
});
}
else {
Ext.ux.plugins.WindowDrawer.superclass.afterShow.call(this);
}
this.fireEvent("aftershow", this);
},

// private
alignAndShow : function() {
this.setAlignment();

if (this.showAgain) {
this.show(true);
}
this.showAgain = false;
},

// private
setAlignment: function() {
switch(this.side) {
case 'n' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [5, (this.el.getComputedHeight() * -1) + 5],
slideDirection : 'b'
});
break;

case 's' :
this.setWidth(this.win.el.getWidth() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'bl',
alignToXY : [5, (Ext.isIE6)? -2 : -7],
slideDirection : 't'
});
break;

case 'e' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tr',
alignToXY : [-5, 5],
slideDirection : 'l'
});
break;

case 'w' :
this.setHeight(this.win.el.getHeight() - 10);
Ext.apply(this.alignToParams, {
alignTo : 'tl',
alignToXY : [(this.el.getComputedWidth() * -1) + 5, 5],
slideDirection : 'r'
});
break;
}

if (!this.hidden) {
this.el.alignTo(this.win.el, this.alignToParams.alignTo, this.alignToParams.alignToXY);

// Simple fix for IE, where the bwrap doesn't properly resize.
if (Ext.isIE) {
this.bwrap.hide();
this.bwrap.show();
}
}

// force doLayout()
this.doLayout();
},


// private
toFront: function() {
this.win.toFront(); // first bring WindowDrawer's parent to the front
//this.setZIndex(this.win.el.getZIndex() - 3); // then place WindowDrawer behind its parent
return this;
}
});

wm003
11 Aug 2011, 11:56 PM
Thank you for this plugin, it's been a while but now i am in the need of such feature. thanks to all you posters this even works in Ext 3.4.0 now. Thanks a alot :)