PDA

View Full Version : [1.0b3][3.2-beta] Ext.ux.TabStripHide



mitchellsimoens
8 Mar 2010, 10:06 AM
This is a beta version of something I'm working on. I wanted to hide the tab strip when there is only 1 tab. When a tab gets added, it shows the tab.

Thanks to Animal for helping me figure out how to do this and he suggested adding a new toggle function to hide/show the strip so I did this as well.

Demo is here (http://www.simoens.org/projects/Ext.ux.TabStripHide/)


Ext.ns("Ext.ux");
Ext.ux.TabStripHide = Ext.extend(Object, {
autoHide: true,
stripHideAnim: true,
constructor: function(config) {
config = config || {};
Ext.apply(this, config);
},
init: function(tabpanel) {
this.tabpanel = tabpanel;

this.tabpanel.autoHide = this.autoHide;
this.tabpanel.stripHideAnim = this.stripHideAnim;
this.tabpanel.toggleHideStrip = this.toggleHideStrip;
this.tabpanel.hideStrip = this.hideStrip;
this.tabpanel.showStrip = this.showStrip;

this.tabpanel.on("render", this.onRender);
if (this.autoHide === true) {
this.tabpanel.on("remove", this.onRemove);
this.tabpanel.on("add", this.onAdd);
}
},
onRender: function() {
this.header.setVisibilityMode(Ext.Element.DISPLAY);
this.header.hidden = false;
if (this.autoHide === true) {
var numTabs = this.items.items.length;
this.header.hidden = (numTabs > 1) ? false : true;
if (this.header.hidden === true) {this.hideStrip();}
}
},
hideStrip: function(doAnim) {
doAnim = (doAnim === undefined) ? this.stripHideAnim : doAnim;
if (doAnim === true) {
this.header.slideOut("t", {
easing: "easeOut",
duration: .5,
remove: false
});
} else {
this.header.hide();
}
this.bwrap.removeClass("x-tab-panel-body-top");
this.bwrap.addClass("x-panel-body-noheader");
this.header.hidden = true;
},
showStrip: function(doAnim) {
doAnim = (doAnim === undefined) ? this.stripHideAnim : doAnim;
if (doAnim === true) {
this.header.slideIn("t", {
easing: "easeOut",
duration: .5
});
} else {
this.header.show();
}
this.bwrap.addClass("x-tab-panel-body-top");
this.bwrap.removeClass("x-panel-body-noheader");
this.header.hidden = false;
},
toggleHideStrip: function(doAnim) {
if (this.header.hidden === false) {
this.hideStrip(doAnim);
} else {
this.showStrip(doAnim);
}
},
onRemove: function() {
if (this.items.items.length === 1) {
this.hideStrip(this.stripHideAnim);
}
},
onAdd: function(tabpanel, tab) {
if (this.header.hidden === true) {
this.hideTabStripItem(tab);
this.showStrip(this.stripHideAnim);
new Ext.util.DelayedTask(function(){
this.unhideTabStripItem(tab);
tab.show();
}, this).delay(500);
}
}
});

Ext.reg("tabstriphide", Ext.ux.TabStripHide);

Usage:


new Ext.TabPanel({
activeTab: 0,
renderTo: Ext.getBody(),
width: 800,
height: 600,
plugins: new Ext.ux.TabStripHide({autoHide: true, stripHideAnim: true}),
defaults: {
closable: true
},
items: [{
title: "Tab One",
html: "blah blah blah"
}]
})

You can see there is a config option in the plugin.. it defaults to true. This option is what turns on/off the auto hide feature. This plugin will still add the toggleHideStrip() function either way.

Github URL:
https://github.com/mitchellsimoens/Ext.ux.TabStripHide

Animal
8 Mar 2010, 11:08 AM
Bad way of creating an object!

Each time you run that constructor, you create seven new functions!

Put init in the prototype, and create private functions by returning the prototype from a closure.

mitchellsimoens
8 Mar 2010, 9:03 PM
refactored code.... demo and root post are updated

jay@moduscreate.com
9 Mar 2010, 12:53 PM
It's good start mitch.

I think there are some optimizations that can be done, such calling tabpanel and not this.tabpanel, when you have the "tabpanel" reference already in memory.


i would suggest:

Modifying your code to allow for animation or not.

And if animation, then performing the post-animation work, such as setting hidden to true and adding css classes/etc.

mitchellsimoens
9 Mar 2010, 1:16 PM
I think there are some optimizations that can be done, such calling tabpanel and not this.tabpanel, when you have the "tabpanel" reference already in memory.

Good point!



i would suggest:

Modifying your code to allow for animation or not.

And if animation, then performing the post-animation work, such as setting hidden to true and adding css classes/etc.

I've thought of that and will come soon!

Thanks for taking time to look over it!

jay@moduscreate.com
9 Mar 2010, 1:19 PM
I would not fire the 'hide||showstrip' event manually. I would use the OOTB methods hide||showStrip()

mitchellsimoens
9 Mar 2010, 3:14 PM
Worked on code with Jay's suggestions.


Used scope instead of passing the tabpanel object to each event.
Stopped relying on event listeners, used scoping instead.
Added new option 'stripHideAnim' as a default to use animation to show/hide the tab strip. Defaults to true.
Added new option to toggleHideStrip(), hideStrip(), and showStrip() to use animation to show/hide the tab strip. Defaults to 'stripHideAnim'.
Using ExtJS 3.2-beta!


Demo and root post code updated!

Thanks to Animal for his honesty and Jay for taking time out to help me learn. Yay for learning new things!

charleshimmer
13 Apr 2010, 8:07 PM
Pretty cool idea mitch. Don't you love the help you get with the ExtJS community?

mitchellsimoens
13 Apr 2010, 8:09 PM
Pretty cool idea mitch. Don't you love the help you get with the ExtJS community?

Thanks... and as abrasive as it could be, it's help nonetheless.

Asken
18 Oct 2010, 11:03 PM
Put init in the prototype, and create private functions by returning the prototype from a closure.

Kindof an old post but this is quite interesting to me to know what you mean... can you give a very short example of how to use prototypes to not create multiple functions?

Update: never mind... I found a very comprehensive page which explained it all very well.
http://jibbering.com/faq/notes/closures/

devtig
3 Nov 2010, 3:46 AM
I'd like to add a little to your extensions. Instead of counting all tabs, like your doing:

var numTabs = this.items.items.length;

i'd like to count he number of tabStripItems that are visible (not hidden through hideTabStripItem)

But, I don't seem to be able to distinguish hidden tabStripItems from visible ones. This is what I am trying:


var numTabs =0;
this.items.each(function() {
var tabStripEl=Ext.get(this.tabEl);
console.log(tabStripEl);
console.log(tabStripEl.isVisible()); //always returns true
console.log(tabStripEl.getStyle('display')); //always returns list-item
console.log(tabStripEl.is('li{display=none}')); //always returns false

if(some clever check for a visible tabStripItem) {
numTabs++;
}
});


I am getting the same values for hidden and visible tabStripItems. How can I count the number of visible tabStripItems?

devtig
3 Nov 2010, 4:46 AM
I even went crazy and tried this!!



var lis3 = this.strip.query("li{display!=none}:not([className^=x-tab-edge])");
console.log('lis3', lis3);


which...in result.... gave me also the tabs made hidden. And it is realy hidden. See for yourself. Learned a cool domquery though :)

To be abolutely clear on this. I'm still looking for a way to count the number of visible tabStripItems.

mitchellsimoens
3 Nov 2010, 6:31 AM
Here is what I just tested...

I have my example panel and added a second tab. I listened to the 'afterrender' event and hide the second tab using the hideTabStripItem function, passing the index 1. This seems like it just adds the style 'display: none' to the tab. So using your query got only the tab that is shown. So how isn't it getting only the shown tabs for you?

Thanks for teaching me the query, never have used that!

devtig
3 Nov 2010, 7:25 AM
I discovered the cause. It's about timing. The query runs in your onRender. I also run hideTabStripItems (that hides specific tabs) on render of the tabpanel. It appears that the hideTabStripItems in my on render happend after your onRender. That's why the query gave only visible elements. I always debugged seconds after when the tabStripItemswere already hidden, leaving my confused.

I changed these 2 lines


this.tabpanel.on('afterrender', this.onRender);



var numTabs = this.strip.query("li{display!=none}:not([className^=x-tab-edge])").length;

Works now!

mitchellsimoens
3 Nov 2010, 7:26 AM
Do you have a Github account? I will add you as a collaborator if you would like!

devtig
3 Nov 2010, 7:41 AM
yep I do (just got one) username is devtig. I changed my previous post, because I got the timing solution.

mitchellsimoens
3 Nov 2010, 7:45 AM
Right on man. You have been added and thank you for furthering my code!

devtig
9 Nov 2010, 10:36 PM
Found another one. My TabPanel contains panels that contain many components. When those components are added/removed, it triggers a add/remove event listener set on the TabPanel. onAdd and onRemove should only execute if the added component's ownerCt is the TabPanel.


onRemove: function(tabpanel, tab) {
if (tab.ownerCt instanceof Ext.TabPanel && this.items.items.length === 1) {
this.hideStrip(this.stripHideAnim);
}
},
onAdd: function(tabpanel, tab) {
if (tab.ownerCt instanceof Ext.TabPanel && this.header.hidden === true) {
this.hideTabStripItem(tab);
this.showStrip(this.stripHideAnim);
new Ext.util.DelayedTask(function(){
this.unhideTabStripItem(tab);
tab.show();
}, this).delay(500);
}
}

I will change on github. Mitchell, will you change first post?