View Full Version : How to make and navigation menu like Jack's Blog
met4lz
4 Dec 2006, 11:18 AM
Hi guys, I'm quite new to this wonderfull user interface, and I got a question.
How can I make a navigation menu with stacked collapsible panels like the ones found in Jack's Blog at: Downloads ----> Build your own yui-ext.js (Tab).
I'm using the borderlayout, and when I try to add another panel it is created on a new tab.
Thx
jbowman
4 Dec 2006, 2:40 PM
He's using nested layouts, in a layoutDialog... A layoutDialog is nothing more than a BasicDialog who's body element has had a BorderLayout inserted into it. So you can take this and modify it to fit your BorderLayout.
Jacks Download Dialog
showDialog : function(){
if(!dialog){
dialog = new YAHOO.ext.LayoutDialog("download-dlg", {
modal: true,
shim:true,
width:600,
height:450,
shadow:true,
minWidth:500,
minHeight:350,
autoTabs:true,
autoScroll:false,
center:{
tabPosition: 'top',
alwaysShowTabs: true
}
});
dialog.addKeyListener(27, dialog.hide, dialog);
dialog.setDefaultButton(dialog.addButton('Close', dialog.hide, dialog));
dlBtn = dialog.addButton('Build It!', this.getDownload, this);
var innerLayout = new YAHOO.ext.BorderLayout('dl-inner', {
east: {
initialSize: 200,
autoScroll:true,
split:true
},
center: {
autoScroll:true
}
});
innerLayout.beginUpdate();
innerLayout.add('east', new YAHOO.ext.ContentPanel('dl-details'));
innerLayout.add('center', new YAHOO.ext.ContentPanel('selection-panel'));
innerLayout.endUpdate(true);
var layout = dialog.getLayout();
dialog.beginUpdate();
var sp = layout.add('center', new YAHOO.ext.ContentPanel('standard-panel',
{title: 'Download the Source', fitToFrame:true}));
sp.on('activate', function(){
dlBtn.getEl().setStyle('display', 'none');
dlInfo.hide();
});
var p = layout.add('center', new YAHOO.ext.NestedLayoutPanel(innerLayout,
{title: 'Build your own yui-ext.js'}));
p.on('activate', function(){
dlBtn.getEl().setStyle('display', '');
dlInfo.show();
if(!detailTpl){
this.render();
}
}, this, true);
layout.getRegion('center').showPanel(sp);
dialog.endUpdate();
}
if(typeof Commentable != 'undefined' && Commentable.isOpen()){
Commentable.closeComment();
this.showDialog.defer(200, this);
return;
}
dialog.show(showBtn.dom);
},
brian.moeskau
4 Dec 2006, 3:39 PM
If you are specifically asking about how to make the panels that expand and collapse, at the moment there is not a nice, packaged widget for this. However, the code to create it is pretty straight-forward. Here's a version I pulled out of Jack's source and have been playing with (note: it's not necessarily complete or working correctly at the moment, but it should point you in the right direction -- YMMV):
var Collapser = function(clickEl, collapseEl){
this.clickEl = getEl(clickEl);
this.collapseEl = getEl(collapseEl);
this.clickEl.addClass('accordion-expanded');
this.enabled = true;
this.clickEl.mon('click', function(){
if (this.enabled) this.collapsed === true ?
this.expand() : this.collapse();
}, this, true);
};
Collapser.prototype = {
collapse : function(){
this.collapseEl.clip();
this.collapseEl.setHeight(1, true, .35, this.afterCollapse.createDelegate(this), YAHOO.util.Easing.easeOut);
},
afterCollapse : function(){
this.collapsed = true;
this.collapseEl.setDisplayed(false);
this.clickEl.replaceClass('accordion-expanded','accordion-collapsed');
},
expand : function(){
this.collapseEl.setDisplayed(true);
this.collapseEl.autoHeight(true, .35, this.afterExpand.createDelegate(this), YAHOO.util.Easing.easeOut);
},
afterExpand : function(){
this.collapsed = false;
this.collapseEl.unclip();
this.collapseEl.setStyle('height', '');
this.clickEl.replaceClass('accordion-collapsed','accordion-expanded');
},
enable : function(){
this.enabled = true;
this.clickEl.removeClass('disabled');
},
disable : function(){
this.enabled = false;
this.collapse();
this.clickEl.addClass('disabled');
}
};
And then to use it you just do something like:
<div id="head">My Box</div>
<div id="body">Content goes here.</div>
<script>
var collapser = new Collapser('head', 'body');
collapser.expand();
</script>
Ultimately, it needs some more functionality and polish, and maybe I (or someone else) will eventually turn it into more of a component like the rest of Jack's stuff :)
Brian
met4lz
6 Dec 2006, 4:06 AM
Thanks guys, your tips were very useful to the project I'm working at.
And thanks for the quick answer too :D
luismalheiro
8 Dec 2006, 12:06 PM
Hi! I'm really a new newbie to this, but I've done some improvements to the Collapser posted above by Brian (bmoeskau). In particular, I added a state manager to it. I'm sure I could have done it in a better way, but my knowledged of YUI and YUI-ext is still limited. So, please, feel free to point out parts that could be improved.
Thanks!
Luis
// Collapser
var Collapser = function(collapsableContainer){
this.id = collapsableContainer.id;
this.clickEl = getEl(YAHOO.util.Dom.getElementsByClassName('ycollapsable-menuhead', null, collapsableContainer)[0]);
this.collapseEl = getEl(YAHOO.util.Dom.getElementsByClassName('ycollapsable-menucontent', null, collapsableContainer)[0]);
this.clickEl.addClass('ycollapsable-expanded');
this.enabled = true;
this.clickEl.mon('click', function(){
if (this.enabled) this.collapsed === true ?
this.expand() : this.collapse();
}, this, true);
this.events = {
'expanded' : new YAHOO.util.CustomEvent('expanded'),
'collapsed' : new YAHOO.util.CustomEvent('collapsed'),
'enabled' : new YAHOO.util.CustomEvent('enabled'),
'disabled' : new YAHOO.util.CustomEvent('disabled')
};
};
YAHOO.extendX(Collapser, YAHOO.ext.util.Observable, {
collapse : function(animate){
if (!this.collapsed) {
this.collapseEl.clip();
if (animate == null || animate == true) {
this.collapseEl.setHeight(1, true, .35, this.afterCollapse.createDelegate(this), YAHOO.util.Easing.easeOut);
} else {
this.collapseEl.setHeight(1);
this.afterCollapse();
}
}
},
afterCollapse : function(){
this.collapsed = true;
this.collapseEl.setDisplayed(false);
this.clickEl.replaceClass('ycollapsable-expanded','ycollapsable-collapsed');
this.fireEvent('collapsed', this);
},
expand : function(animate){
if (this.collapsed) {
this.collapseEl.setDisplayed(true);
if (animate == null || animate == true) {
this.collapseEl.autoHeight(animate, .35, this.afterExpand.createDelegate(this), YAHOO.util.Easing.easeOut);
} else {
this.collapseEl.autoHeight();
this.afterExapand();
}
}
},
afterExpand : function(){
this.collapsed = false;
this.collapseEl.unclip();
this.collapseEl.setStyle('height', '');
this.clickEl.replaceClass('ycollapsable-collapsed','ycollapsable-expanded');
this.fireEvent('expanded', this);
},
enable : function(){
this.enabled = true;
this.clickEl.removeClass('ycollapsable-disabled');
this.fireEvent('enabled', this);
},
disable : function(){
this.enabled = false;
this.collapse();
this.clickEl.addClass('ycollapsable-disabled');
this.fireEvent('disabled', this);
},
restoreState : function(provider){
if(!provider){
provider = YAHOO.ext.state.Manager;
}
var sm = new CollapserStateManager();
sm.init(this, provider);
}
});
var CollapserStateManager = function(collapserObject, provider){
this.state = {
collapsed: true,
enabled: true
};
};
CollapserStateManager.prototype = {
init : function(collapser, provider){
this.provider = provider;
var state = provider.get(collapser.id+'-collapser-state');
if(state){
if(state.collapsed){
collapser.collapse(false);
} else {
collapser.expand(false);
}
if(state.enabled == true){
collapser.enable();
}else{
collapser.disable();
}
this.state = state;
}
this.collapser = collapser;
collapser.on('collapsed', this.onCollapsed, this, true);
collapser.on('expanded', this.onExpanded, this, true);
collapser.on('enabled', this.onEnabled, this, true);
collapser.on('disabled', this.onDisabled, this, true);
},
storeState : function(){
this.provider.set(this.collapser.id+'-collapser-state', this.state);
},
onCollapsed : function(){
this.state.collapsed = true;
this.storeState();
},
onExpanded : function(){
this.state.collapsed = false;
this.storeState();
},
onEnabled : function(){
this.state.enabled = true;
this.storeState();
},
onDisabled : function(){
this.state.enabled = false;
this.storeState();
}
};
//
//Usage example:
//
//
// <div id="config-collapser" class="ycollapsable">
// <div class="ycollapsable-menuhead">
// <asp:Label ID="MenuHeader0" runat="server" Text="Configuração"></asp:Label>
// </div>
// <div class="ycollapsable-menucontent">
// <div>
// <asp:LinkButton ID="UserAdmLinkPage" runat="server" Text="Gerenciamento de Usuário"></asp:LinkButton>
// </div>
// <div>
// <asp:LinkButton ID="LinkButton1" runat="server" Text="Parâmetros"></asp:LinkButton>
// </div>
// </div>
// </div>
//
// <div id="monitoring-collapser" class="ycollapsable">
// <div class="ycollapsable-menuhead">
// <asp:Label ID="Label1" runat="server" Text="Monitoring"></asp:Label>
// </div>
// <div class="ycollapsable-menucontent">
// <div>
// <asp:LinkButton ID="LinkButton6" runat="server" Text="Diagnosticos"></asp:LinkButton>
// </div>
// <div>
// <asp:LinkButton ID="LinkButton7" runat="server" Text="Modelos"></asp:LinkButton>
// </div>
// </div>
// </div>
//
// <script>
//
// var collapsables = YAHOO.util.Dom.getElementsByClassName('ycollapsable')
//
// for (i in collapsables) {
// var collapser = new Collapser(collapsables[i]);
// collapser.restoreState();
// collapser.enable();
// }
//
// </script>
brian.moeskau
8 Dec 2006, 3:38 PM
Hey Luis,
Nice job! I took your improvements one step further:
- Added a default cookie provider if none is specified since the StateManager doesn't do anything without a valid provider.
- Changed restoreState() to accept an optional defaultState parameter that gets used the first time through when there is no valid saved state.
- Added: containerEl = getEl(collapsableContainer); as the first line of the constructor so that you can simply pass in an id from the page (although passing an element will still work).
- Added functionality in the sample to demonstrate disabling/enabling a panel. Also made the sample html a little more generic, included the style defs, etc.
Let me know if you improve it even further :)
- Brian
New script (collapser.js):
// Collapser
var Collapser = function(collapsableContainer){
containerEl = getEl(collapsableContainer);
this.clickEl = getEl(YAHOO.util.Dom.getElementsByClassName('ycollapsable-menuhead', null, collapsableContainer)[0]);
this.collapseEl = getEl(YAHOO.util.Dom.getElementsByClassName('ycollapsable-menucontent', null, collapsableContainer)[0]);
this.clickEl.addClass('ycollapsable-expanded');
this.id = containerEl.id;
this.enabled = true;
this.collapsed = false;
this.clickEl.mon('click', function(){
if (this.enabled) this.collapsed == true ?
this.expand() : this.collapse();
}, this, true);
this.events = {
'expanded' : new YAHOO.util.CustomEvent('expanded'),
'collapsed' : new YAHOO.util.CustomEvent('collapsed'),
'enabled' : new YAHOO.util.CustomEvent('enabled'),
'disabled' : new YAHOO.util.CustomEvent('disabled')
};
};
YAHOO.extendX(Collapser, YAHOO.ext.util.Observable, {
collapse : function(animate){
if (!this.collapsed) {
this.collapseEl.clip();
if (animate == null || animate == true) {
this.collapseEl.setHeight(1, true, .15, this.afterCollapse.createDelegate(this), YAHOO.util.Easing.easeIn);
} else {
this.collapseEl.setHeight(1);
this.afterCollapse();
}
}
},
afterCollapse : function(){
this.collapsed = true;
this.collapseEl.setDisplayed(false);
this.clickEl.replaceClass('ycollapsable-expanded','ycollapsable-collapsed');
this.fireEvent('collapsed', this);
},
expand : function(animate){
if (this.collapsed) {
this.collapseEl.setDisplayed(true);
if (animate == null || animate == true) {
this.collapseEl.autoHeight(animate, .25, this.afterExpand.createDelegate(this), YAHOO.util.Easing.easeOut);
} else {
this.collapseEl.autoHeight();
this.afterExapand();
}
}
},
afterExpand : function(){
this.collapsed = false;
this.collapseEl.unclip();
this.collapseEl.setStyle('height', '');
this.clickEl.replaceClass('ycollapsable-collapsed','ycollapsable-expanded');
this.fireEvent('expanded', this);
},
enable : function(){
this.enabled = true;
this.clickEl.removeClass('ycollapsable-disabled');
this.fireEvent('enabled', this);
},
disable : function(animate){
this.enabled = false;
this.collapse(animate);
this.clickEl.addClass('ycollapsable-disabled');
this.fireEvent('disabled', this);
},
restoreState : function(defaultState, provider){
if(!provider){
YAHOO.ext.state.Manager.setProvider(new YAHOO.ext.state.CookieProvider());
provider = YAHOO.ext.state.Manager;
}
var sm = new CollapserStateManager();
sm.init(this, provider, defaultState);
}
});
var CollapserStateManager = function(collapserObject, provider){
this.state = {
collapsed: true,
enabled: true
};
};
CollapserStateManager.prototype = {
init : function(collapser, provider, defaultState){
this.provider = provider;
if (!defaultState) {
defaultState = { enabled: true, collapsed: false };
}
var savedState = provider.get(collapser.id+'-collapser-state');
this.state = savedState || defaultState;
if(this.state.collapsed){
collapser.collapse(false);
} else {
collapser.expand(false);
}
if(this.state.enabled == true){
collapser.enable();
}else{
collapser.disable();
}
this.collapser = collapser;
collapser.on('collapsed', this.onCollapsed, this, true);
collapser.on('expanded', this.onExpanded, this, true);
collapser.on('enabled', this.onEnabled, this, true);
collapser.on('disabled', this.onDisabled, this, true);
},
storeState : function(){
this.provider.set(this.collapser.id+'-collapser-state', this.state);
},
onCollapsed : function(){
this.state.collapsed = true;
this.storeState();
},
onExpanded : function(){
this.state.collapsed = false;
this.storeState();
},
onEnabled : function(){
this.state.enabled = true;
this.storeState();
},
onDisabled : function(){
this.state.enabled = false;
this.storeState();
}
};
New html:
<html>
<head>
<script type="text/javascript" src="scripts/yahoo-debug.js"></script>
<script type="text/javascript" src="scripts/dom-debug.js"></script>
<script type="text/javascript" src="scripts/event-debug.js"></script>
<script type="text/javascript" src="scripts/animation-debug.js"></script>
<script type="text/javascript" src="scripts/yui-ext-debug.js"></script>
<script type="text/javascript" src="scripts/collapser.js"></script>
<style>
.ycollapsable-menuhead {border:1px solid #555;background:#369;color:#fff;cursor:pointer;padding-left:10px;}
.ycollapsable-menucontent {border:1px solid #555;padding:20px;}
.ycollapsable-disabled {background:#999;color:#ddd;cursor:default;}
</style>
</head>
<body>
<div id="collapser1" class="ycollapsable">
<div class="ycollapsable-menuhead">
Header
</div>
<div class="ycollapsable-menucontent">
<div>
Content
Content
Content
Content
</div>
</div>
</div>
<div id="collapser2" class="ycollapsable">
<div class="ycollapsable-menuhead">
Header 2
</div>
<div class="ycollapsable-menucontent">
<div>
Content 2
Content 2
</div>
</div>
</div>
<input id="toggleButton" type="button" value="Enable" /></p>
<script>
var coll1 = new Collapser('collapser1');
var coll2 = new Collapser('collapser2');
coll1.restoreState({enabled: true, collapsed: true});
coll2.restoreState({enabled: false});
setButtonState();
YAHOO.util.Event.on('toggleButton', 'click', toggleCollapser, coll2, true);
function toggleCollapser(){
if (coll2.enabled) {
coll2.disable(false);
}
else {
coll2.enable(false);
}
setButtonState();
}
function setButtonState() {
YAHOO.util.Dom.get('toggleButton').value = (coll2.enabled ? "Disable" : "Enable");
}
</script>
</body>
</html>
Powered by vBulletin® Version 4.1.5 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.