PDA

View Full Version : [2.x] Ext.ux.WindowBlind



sean
25 Feb 2008, 6:43 PM
Hello all,

Nothing real fancy here but something that I've found to be fairly useful for applications that are window driven. In essence a blind is nothing more than a panel that slides in/out from the bottom of a window's header to display some information or to gather input. When visible the blind is the focus of the window and must be dismissed before the user can interact with the window again.

View the demo here (http://mcdconsultingllc.com/blinds).

I've added extensions for blinds that contain forms and grids. Feel free to hit me up with any ?s you may have. Not sure if there is much interest in these types of widgets but I have a few more, including a window drawer that I'll get published soon.

Disclaimer: I haven't looked at this solution on doze. I had problems with the animations and elements that had overflow when I initially wrote something similar 10 month back. Looks good in safari and ff on osx. I'll check it out in the morn and fix any visual issues if they exist.

Sean

franckxx
25 Feb 2008, 8:11 PM
thx, very beautiful effects !

its look great !

jack.slocum
25 Feb 2008, 10:25 PM
That's pretty hot. Great work and thanks for sharing!

brian.moeskau
25 Feb 2008, 10:37 PM
Really nice. If you have other examples, keep them coming ;)

galdaka
25 Feb 2008, 11:42 PM
Excellent work!!

Grid blind fails in IE6.

Thanks for share,

madrabaz
26 Feb 2008, 3:50 AM
Very nice and useful work!

Thanks a lot;

sean
26 Feb 2008, 9:02 PM
Thanks fellas. Hope to have a drawer widget in the next couple of weeks.

Sean

dearsina
27 Feb 2008, 3:52 AM
Grid blind breaks in IE6, probably because of the 10000px CSS "bug":

http://extjs.com/forum/showthread.php?t=21355

Great plug-in though, looking forward to trying it at home.

Animal
27 Feb 2008, 4:08 AM
That's very good work, and shows a thorough understanding of complex Ext classes and effects, compliments on reading the docs, and understanding the complexities!

I'm not sure it's the most efficient way though.

The great thing about Ext is the foundation it gives you for creating widgets like this.

Extending Ext.Panel offers so much in terms of capabilities. And the Blind should be a plugin applicable to any other Panel subclass.

Just for illustration, unzip the attached file into examples/window.

It's the "hello world" window example which uses a very simple Ext.ux.PanelBlind class to implement a blind effect over the popped up window.

I think it should be able to be applied to any Panel subclass including FormPanels, and ordinary Ext.Panels.

4959

dearsina
27 Feb 2008, 5:30 AM
animal, this might not come as a surprise, but that example did not work in ie6.

Animal
27 Feb 2008, 5:32 AM
Damn IE! I'll go and test it. I only have IE7, but...

Animal
27 Feb 2008, 5:34 AM
It's the clasic trailing comma after the dismiss function!

Animal
27 Feb 2008, 5:37 AM
Attachment updated...

@sean, feel free to take ownership of this, and upgrade it to include those extra animation configs and make it as configurable as your original class.

sean
27 Feb 2008, 6:39 AM
Animal, I definitely considered extending Ext.Panel to inherit a lot of the code that can be found in the WindowBlind class. I also considered binding the blind to a panel and making it fit more into the ext 2.x way of doing things. Thanks for the input.

Sean

sean
27 Feb 2008, 10:07 AM
animal, with your solution i see that the zee is set once. what happens when there are multiple dialogs and the one that is blinded goes to the back and then to the front, ie its zee changes. i found that i needed to render the blind inside the window's el so this stacking was handled correctly, ie containment eased this management from my code.

i didn't have any luck with your code. this.el.disableShadow() is not a function. i thought i was using 2.0.1.

sean

Animal
27 Feb 2008, 11:02 AM
You need to download 2.0.2.

I'll have a look at the multiple window issue.

Animal
27 Feb 2008, 12:56 PM
Try this as hello.js, it works fully for me with 2.0.2:



Ext.ux.PanelBlind = Ext.extend(Ext.Panel, {

constructor: function(config) {
config = Ext.apply({
autoHeight: true,
floating: true,
cls: 'x-blind',
bodyStyle: {
'border-width': '0px'
},
buttonAlign: 'center',
buttons: [{
text: 'Dismiss',
handler: this.dismiss,
scope: this
}]
}, config);
Ext.ux.PanelBlind.superclass.constructor.call(this, config);
},

init: function(client) {
this.client = client;
client.blind = this;
this.client.constructor.prototype.showBlind = this.clientShowBlind;
this.client.constructor.prototype.dismissBlind = this.clientDismissBlind;
this.client.on('destroy', this.destroy, this);
},

clientShowBlind: function() {
this.blind.show();
},

clientDismissBlind: function() {
this.blind.dismiss();
},

show: function() {
var mask = this.client.getEl().mask();
if (!this.rendered) {
this.render(this.client.getEl());
}

// Synchronize this blind's z-index to be one above the client Element's mask
this.el.setZIndex(Number(mask.getStyle('z-index')) + 1);

this.el.disableShadow();
this.setWidth(this.client.body.getSize(true).width);
this.el.alignTo(this.client.body, 'tl-tl');
this.el.slideIn('t', {
callback: function() {
this.el.visible = true; // Ext bug. Flag not set causes enableShadow to fail.
this.el.enableShadow(true);
},
scope: this
});
},

dismiss: function() {
this.el.disableShadow();
this.el.slideOut('t');
this.client.getEl().unmask();
}

});

Ext.onReady(function(){
var win;
var button = Ext.get('show-btn');
var blind = new Ext.ux.PanelBlind({
html: 'foo<br>bar<br>and<br>bletch'
});

button.on('click', function(){
var winId = Ext.id(null, 'test');
win = new Ext.Window({
id: winId,
plugins: new Ext.ux.PanelBlind({
html: 'foo<br>bar<br>and<br>bletch'
}),
layout:'fit',
width:500,
height:300,
closeAction:'hide',
hideMode: 'visibility',
plain: true,

items: new Ext.TabPanel({
autoTabs:true,
activeTab:0,
deferredRender:false,
border:false,
items: [
{
id: winId + 'Tab1',
title: 'Tab 1',
plugins: new Ext.ux.PanelBlind({
html: "Tab<br>One's<br>blind<br>element"
}),
buttons: [{
text: 'Blind',
tabId: winId + 'Tab1',
handler: function(b) {
Ext.getCmp(b.tabId).showBlind();
}
}]
}, {
id: winId + 'Tab2',
title: 'Tab 2',
plugins: new Ext.ux.PanelBlind({
html: "Tab<br>Two's<br>blind<br>element"
}),
buttons: [{
text: 'Blind',
tabId: winId + 'Tab2',
handler: function(b) {
Ext.getCmp(b.tabId).showBlind();
}
}]
}
]
}),

buttons: [{
text:'Submit',
disabled:true
}, {
text: 'Blind',
winId: winId,
handler: function(b) {
Ext.getCmp(b.winId).showBlind();
}
},{
text: 'Close',
handler: function(){
win.hide();
}
}]
});
win.show(this);
});
});

sean
27 Feb 2008, 12:56 PM
alrighty. i set up the zee statically with css so all blinds are on top of the window el's mask (+3). since the blind is a child of the window's containing el, any element that is dragged over a blinded window (other windows for instance), would case the blind to be clipped along with the window. if your panel blind could be rendered as a child component of a panel then you would get this behavior too.

something else that i thought was necessary was to manage the height of the blind so that it remains contained within the window's body el.

sean

Animal
27 Feb 2008, 1:08 PM
What I've done is to hook a sequence onto the end of the Window's setZIndex call which adjusts's its blind's z-index at the same time to its own z-index plus one. This keeps it correct.



if (this.client.setZIndex) {
this.client.setZIndex = this.client.constructor.prototype.setZIndex.createSequence(this.adjustBlindZIndex);
}


That calls the adjustBlindZIndex in the scope of the Window, so it operates on "this.blind".

I also call that just before showing it to ensure it is correct at that point.



if (this.client.setZIndex) {
this.adjustBlindZIndex.call(this.client);
}


That explicitly calls adjustBlindZIndex in the scope of the client Window.

sean
27 Feb 2008, 1:59 PM
yeah i see that in the new version, pretty slick. i wonder if it makes more sense to leave the z-index in css and not worry about needing to readjust but that forces the blind to be rendered within its 'client'. your solution is much more in tune with the ext 2 way of doing things.

i'll noodle through expanding your solution out some over the next couple of days. i've spent the last 10 -11 months doing primarily JS dev on top of 1.1.1 so i still am trying to learn the new component and plugin model. i've been reviewing the new samples and your code also is a good demonstration as to the right way to do things in 2.0

sean

Animal
27 Feb 2008, 10:26 PM
Just thinking about this...

I think you had the location of the blind Layer correct initially. It has to be rendered into the client's el.

It's just that on each show, it has to be moved in front of the mask.

The reason is that if the blind is hiding a Panel that is within a draggable Window, then if the Window is moved, the blind on the child Panel will not.

I'll make the change later today.

Animal
28 Feb 2008, 12:30 AM
OK, I got the way to do it.

I've updated the post above, and the zip file containing the full example.

It renders the blind into the client Panel's Element, and on show, ensures that the blind element is z-indexed above the mask.

This means that you can move a Window containing a masked Panel.

The new example allows you to mask each tab within the TabPanel in multiple Windows, then move the Windows around.

I think we're close to the final version here. It just needs those extra configs you allow in your version to be able to specify animation params about how to animate the blind in and out.

sean
28 Feb 2008, 8:52 AM
Animal,

Getting closer. With the ability to blind (non window) panels I think the blind itself needs to resize if the client panel resizes. This situation didn't arise with a window specific binding. Here's a list of other things that I can see will need to be addressed with your code if I were to move forward with it:



externalized button registration, best left to clients of the instance and subtypes.



overflow management of the body el. if overflow is auto and scroll bars are visible they will animate outside of where you would expect them to get clipped. this was perhaps the messiest part of the initial solution (css) but crucial for the fx to work correctly.



hide/dismiss: clients can use hide when a blind is to be reused. dismiss will hide and destroy the blind instance



create subtypes of formpanel and gridpanel


btw: I really like the dynamic extension stuff that you are doing with the client panel (showBlind & dismissBlind) but it is somewhat limiting. Typically custom panels (extensions of Ext.Panel) will be aware of the blinds that they will potentially display. In addition is quite conceivable that a panel will have more than one blind. It is probably best not to make any assmumptions about how they are to be used, ie don't add methods dyanmically to the client and let the Panel decide when to create and display blinds based on internal/external events, state, callbacks, etc. Best to encapsulate IMO, but this solution is cool for the demo.

Thanks again

Animal
28 Feb 2008, 10:13 AM
Well poking a showBlind method in is just a quick way to offer ultimate convenience for one blind. The plugin could "register" itself in a property of its client called blinds which it would set up to be an Array, and just push itself on to.

I'll check the resizing thing when I get home. It will be a simple case of subscribing to the client Panel's "resize" event and synching the width as is done in the show method.

sean
28 Feb 2008, 1:43 PM
After giving it some thought I'm a little unsure if the plugin model fits for this widget Animal. I don't like, for the blind, the upfront initialization that is happening in the client component. Its often unnecessary and can be inefficient, at least the way that I feel blinds are best employed.

Take for instance a simple save success or error blind. These types of informational blinds simply display a message with a required confirmation from the user by way of an 'Ok' button click. In this case I would normally just want to construct and show a blind in either an actioncomplete or actionfailed callback from the Ext.BasicForm instance and immediately dismiss (hide & destroy) when the button is clicked. No need to pre-instantiate and keep an instance around. I think lazy construction and rendering is probably a best practice.

There are other times when keeping a reference to the blind and reusing it for the lifecycle of the window (panel) makes total sense. I do this for summary (list) data interactions when I have a grid on a window and a blind that contains a form for filtering this list. In this case the window will construct the filterblind lazily in a callback from a toolbar item and keep the reference for later.

I've also created grid blinds in response to context menu events on a row. These displayed historical or audit information related to the business data represented by the row. In this case I also wanted to keep the reference around and simply reload the grid based on a context switch.

The majority of the time however I like to construct blinds and toss them as soon as they hide.

Animal
28 Feb 2008, 2:13 PM
OK, like an MsgBox, but sliding down instead of popping up.

That can also be configured into that class pretty easily. Make it destroy itself on dismiss, couldn't be easier. add destroyOnDismiss:true, and then add if (this.destroyOnDismiss) this.destroy() to the dismiss method.

Then you can instantiate the Blind with client:myWindow (which if set, should set this.client), and then call show.

sean
28 Feb 2008, 2:49 PM
Yes, I was thinking about mentioning MsgBox in my previous post. Main difference is that it isn't a window it doesn't follow the singleton pattern. So in summary very close to my original solution but extending Panel.

dawesi
28 Feb 2008, 6:35 PM
super, super, super cool!

dawesi
28 Feb 2008, 6:38 PM
It would be nice also to do a 'push' blind (without mask) that pushes the content down so that the blind doesn't cover the form...

sean
28 Feb 2008, 8:08 PM
Thanks! I accidently implemented a push blind at one point. Do you think this would be useful? The implementation would be fairly easy, just need to render the blind as a sibling above the window's body el and forget about the zIndex. May also need to position it relative.

sean
28 Feb 2008, 8:16 PM
A cool easing combination to try is show easing: 'back out' & hide easing: 'back in'. It actually looks & feels like a real roller window shade. I'm always writing apps for biz users so it's fun to be able to play with this wiz bang stuff.

jerrybrown5
28 Feb 2008, 10:23 PM
I think this is pretty cool. However, I think it would be outright incredible if you made a validation method on any container (especially including FormPanel and TabPanel) to automatically display a blind if there were failure(s) of nested fields. Furthermore, you could make an option on TabPanel to not allow a tab change on such validation failures. Inside the blind it would display a listing of the fields and their failed validation messages.

Animal
29 Feb 2008, 1:11 AM
Latest zip file in there syncs the blind size with the size of its client when the client resizes.

Also registers itself in a MixedCollection within its client enabling the client to have multiple blinds, and show/dismiss them by ID/index.

sean
29 Feb 2008, 10:25 AM
Hey Jerry,

I've used validation blinds in the past and my users preferred this over the native Ext form validation icons with tips. I ended up using both. The individual validation errors would be visually apparent when a field blurred and the blind would be the gate keeper that stopped the submit. In any case I think what you are looking for is more focused on the panel itself. Perhaps a ValidateableFormPanel or ValidateableTabPanel that employed a blind to communicate validation errors and prevented context switching from the panel or tab would be useful. I see the blind as more of a building block for constructing these higher level concepts. Your idea btw could be a very useful extension.

cheers

jerrybrown5
29 Feb 2008, 9:46 PM
Sean,
I see versions of your Blind being plastered across the Ext community. I believe it is that good of an idea. Kudos to you.

Jerry

sean
1 Mar 2008, 6:47 AM
Jerry,

What do you mean? Can you reference one or two of these to me?

Sean

DigitalSkyline
1 Mar 2008, 7:12 AM
Not to be a killjoy, but every time I try the demo in IE7, select a "styled message", the message shows, then IE hard crashes with no errors, the IE window just disappears!

Maybe I just need a reboot, or maybe its a bug. Can anyone confirm?

Animal
1 Mar 2008, 7:49 AM
What, my plugin in that attached zip, or sean's version?

sean
1 Mar 2008, 8:41 AM
Damn crashes the browser, that's odd indeed.

Animal, I think this would be my version as he references the 'sytled' blind in my demo. I don't have a doze system so I can't confirm. Not really a killjoy, my version is .1 so I wouldn't be surprised if things like these come up. I think I put a disclaimer in the original post regarding this too.

In any case the only difference in the implementation of the styled blind is css. Are all the other blind variations working in IE7 for you? Apparently there is also a problem in IE6 with the grid extension?

Thanks for the feedback. I'll look into this issue next week when I have access to a windows system.

jerrybrown5
1 Mar 2008, 11:47 AM
I can confirm that it is Sean's version and not Animal's. It happens to my IE also.

sean
1 Mar 2008, 12:07 PM
Jerry, what about the other examples?

jerrybrown5
1 Mar 2008, 12:44 PM
Only the simplest example worked for me in IE7. The rest instantly crashed the browser.

sean
1 Mar 2008, 1:16 PM
ok, thanks. i'll look into it early next week. the code looks good to me and the fact that it works in safari and ff on my mac is curious. is anyone aware of things that might cause IE7 is crash?

sheridap
10 Apr 2008, 6:17 AM
A typical gotcha is config statements the end with an extra comma?

Awesome extension!

w011117
24 Apr 2008, 4:46 PM
Sean,
Awesome etension.
I am trying to get this to work with a panel in a tabpanel.
Any insight?
Have you ever tried this?

Thanks,
Timmer

sean
26 Apr 2008, 4:33 AM
Timmer,

You will need to use Animal's solution for that. My blind is targeted at an instance of a window. His solution is targeted for panels. I think there is a Ext.ux.Panel blind in the hello.zip file attached at the beginning of this thread.

sean

w011117
28 Apr 2008, 9:03 AM
Thanks Sean,
I will look into Animals version...

Thanks,
Timmer

sheridap
30 Apr 2008, 8:18 PM
Sean,

the following definition is causing the IE7 crash:



.ux-win-blind-inactive div {
overflow: hidden;
}

.ux-win-blind .ux-win-blind-bwrap {
padding: 5px 5px 2px 5px;
}


You've got them defined in the WindowBlind.html file. Remove both css definitions and things should work fine.

It's somehow tied into your hide() or destroy() calls.
I didnt debug any further but enough to peg it as the cause.

Can someone else confirm this fix also works for IE6?

sean
1 May 2008, 12:56 AM
Thanks Pat!

MarkB
10 Oct 2008, 10:59 AM
Has anyone tried combo boxes on Animal's FormBlind?

My drop down lists are appearing behind the Blind. Is there a solution to this? I know the nasty solution would be to use a dynamic radio group but I would rather not do this approach.

Thanks,
Mark

jmariani
17 Nov 2008, 12:23 PM
Hi, Sean.

I really like your work and your implementation of this GUI widget. I want to use it as a message box like "An error has occurred when saving the record" when processing a form submit. So I tried to implement your Ext.ux.ExampleStyledMessageBlind, but I can't find a way to set the text (usually the text will come from a server response).

My code is:


menuBrowserEditForm.getForm().submit({
method:'POST',
waitTitle:'Grabando datos...',
waitMsg:'Por favor, espere un momento.',
failure: function(f, a){
console.log(f);
console.log(a);
console.log(a.result.errors.dbError);
var dialog = new Ext.ux.ExampleStyledMessageBlind('warning-blind', Ext.getCmp('menuBrowserEditWindow'), {
showFx: Ext.Fx.slideIn,
hideFx: Ext.Fx.slideOut,
showEasing: 'easeOut',
hideEasing: 'easeOut',
fxDuration: .2
});
dialog.text = a.result.errors.dbError;
dialog.addButton('Aceptar');
dialog.show();
}
});
Can you guide me? I have to tell you I'm a newbie.

I've tried dialog.text = a.result.errors.dbError;, dialog.MSG = a.result.errors.dbError;, dialog.msg = a.result.errors.dbError; with no luck.

Thanks in advance.

jmariani
17 Nov 2008, 12:53 PM
Ok, solved.

I had to set the text property within the config.

Here's the code:


handler:function(){
menuBrowserEditForm = Ext.getCmp('menuBrowserEditForm');
menuBrowserEditForm.getForm().submit({
method:'POST',
waitTitle:'Grabando datos...',
waitMsg:'Por favor, espere un momento.',
failure: function(f, a){
console.log(f);
console.log(a);
console.log(a.result.errors.dbError);
var dialog = new bdApp.errorBlind('error-blind', Ext.getCmp('menuBrowserEditWindow'), {
showFx: Ext.Fx.slideIn,
hideFx: Ext.Fx.slideOut,
showEasing: 'easeOut',
hideEasing: 'easeOut',
fxDuration: .2,
text: "Ha ocurrido un error al grabar los datos: </br>" + a.result.errors.dbError
});
//dialog.text += a.result.errors.dbError;
dialog.addButton('Aceptar');
dialog.show();
console.log(dialog);
}
});
}


Attached is a screenshot.

Thank you for sharing this great piece of code.

jmariani
18 Nov 2008, 6:49 AM
Hi, Sean.

Looks like the blind is asynchronous, like the Ext.msg. Is there any way to make it synchronous like javascript alert() or any way to put code to the "Dismiss" button, like Ext.msg?

Thank you in advance.

jay@moduscreate.com
18 Nov 2008, 6:58 AM
You will have to modify it to allow a callback for the button.

jmariani
26 Nov 2008, 4:26 PM
Hi.

I was needing a way to close the parent window of the blind when I click the "Ok" button.
Since I couldn't find a way to get the parent window, I added
this.ownerCt = win; to the constructor function of the widget.

So I can happily code:


success: function(f, a){
var dialog = new bdApp.okBlind('ok-blind', thisWindow, {
text: "Los datos se grabaron correctamente"
});
dialog.addButton('Aceptar', function(){this.ownerCt.close();});
dialog.show();
}

Cya

mnask79
1 Dec 2008, 2:54 PM
hi all

really very nice ,

but how if i dont want this example to work in window , and i want it to work in panel ..for example




myPanel = new Ext.Panel({
applyTo : 'blindPanel',
items : new Ext.FormPanel({
labelWidth: 75,
frame: true,
bodyStyle: 'padding: 5px 5px 0',
defaultType: 'combo' .....

})

Ext.TabPanel({
activeTab:0,
deferredRender:false,
border:false ,
items:[myPanel,myPanel2]
})


<div id='blindPanel'></div>



what shall i do ?:">

thanks

jmariani
1 Dec 2008, 5:30 PM
See post #9 on first page of this thread.

mnask79
2 Dec 2008, 3:26 AM
i saw it , but i mean ,, i dont want this to be in window

jmariani
2 Dec 2008, 6:51 AM
i saw it , but i mean ,, i dont want this to be in window

That post in particular talks about panel, not window. Take a look