PDA

View Full Version : [2.2] Ext.ux.Locationbar



temporary
25 Sep 2008, 8:38 AM
Hi folks,

here you can find the first (not complete) version of my Locationbar component.

The Locationbar is a WindowsVista-Explorer-Adressbar-like Toolbar extension that displays the currently selected node in a tree in a breadcrumb-like way. It has some features like node reload (for AsyncTreeNodes), back/forward (forward is fubar right now), and provides quick access to subfolders in the current node path (like Vista).

The component can be run in automatic or manual mode, in automatic mode you just provide the target tree as a configuration option, it will listen on selection changes and do all the stuff automagically. In manual mode you have finer control, you can set the currently active node and provide handlers for selection and reload.

Example is included in the package, code has been testes on Firefox3 and IE7 (only windows). Please let me know if you find bugs or have good ideas about it.
The forward button is disabled right now, since the history stuff is really fubar ;-)

An online demo will follow soon.

update 2008-06-28:
New version that fixes a typo (thx denkoo) and has changed the path for ext, you can just unpack it to your ext examples folder and it should work (thx galdaka). No new features (removed v0.1 because of the changes)

galdaka
25 Sep 2008, 11:58 AM
Excellent screenshot!!

Any example that simply Drag & drop to Ext 2.2 examples folder and run?

Thanks in advance,

P.D: I think would be a good feature implement Location strategy (View Ext.ux.Spinner) to your component for valid to Tree or other pourposes like pages navigation.

ludoo
25 Sep 2008, 12:02 PM
Great job !!

I started a similar component based on a combobox & menu, not a toolbar...
But I think finally your way is better !

I will follow your project with a lot attention, because i will try to include it in my project

I suggest a missing feature : full text address access (when click on blank part of locationbar)

ajaxvador
25 Sep 2008, 12:07 PM
great job =D>

denkoo
25 Sep 2008, 8:38 PM
Thanks sharing

I create on my serer a demo online for communauty
http://213.251.166.160/~extjs/examples/Ext.ux.Locationbar/Locationbar-render.html
http://213.251.166.160/~extjs/examples/Ext.ux.Locationbar/Locationbar-component.html

Be carrefull : On linux, case is important => you call LocationBar.css and your have Locationbar.css

temporary
26 Sep 2008, 1:06 AM
Thanks for your feedback.

More stuff will come, this is a very first version ;-)

temporary
26 Sep 2008, 6:07 AM
Be carrefull : On linux, case is important => you call LocationBar.css and your have Locationbar.css

uhh thanks for the hint, i missed that. will fix it and upload a new version.

wojan
27 Sep 2008, 6:23 AM
Thanks so much for posting this!!!!

Jowood
27 Sep 2008, 8:05 AM
cool,Thank you shard

Scorpie
23 Jan 2009, 5:41 AM
Very nice, vista like toolbar!

millenovecento
27 Feb 2009, 9:01 AM
Hi temporary,

Very good work but i have a problem because i use n asynctreenode and the current item doesn't display the menu at start but only when you before expand it children and then return on it.

You've add an asynctreenode feature. I haven't found it.

Again... very cool!!

Foggy
23 Apr 2009, 5:25 AM
Hi Temporary

Great stuff, thanks for sharing.
Are you planning migrate this UX to Ext 3.0?

I've done some effort in this direction, maybe you are interested in changes wich i had to do:

repaint: function() {
if (this.items && this.items.length) {
var _doLayout = true;
this.items.each(function(item){
this.items.remove(item);
item.destroy();
}, this.items);
} else {
var _doLayout = false;
}

// your original stuff here...

if (_doLayout === true) {
this.doLayout();
}
}


But there is also a small css bug, wich i can't locate currently. I'm not sure if it is a bug in Ext.Toolbar or in the UX.

Sesshomurai
8 May 2009, 9:52 PM
Hi,
I think I fixed that CSS error with LocationBar in EXT 3.0. I added a new Fill class.



Ext.ux.Fill = Ext.extend(Ext.Toolbar.Spacer, {
// private
render : function(td){

td.style.width = '100%';
Ext.fly(td).addClass('x-locationbar-location');
Ext.ux.Fill.superclass.render.call(this, td);
}
});
Ext.reg('tbfill', Ext.ux.Fill);


and then where it adds the spacer in LocationBar.js I use this:



this.addItem(
{
cls: 'x-locationbar-location x-locationbar-location-last',
xtype: 'tbfill'
});


hth

Foggy
9 May 2009, 9:38 PM
nice, that works...
But ive decided to build complete new locationBar for my self. Cause the great Ext3.0 overflow menu is not working with this ux...
Maybe i can share my code next days...

Scorpie
12 Feb 2010, 1:05 AM
nice, that works...
But ive decided to build complete new locationBar for my self. Cause the great Ext3.0 overflow menu is not working with this ux...
Maybe i can share my code next days...

Have you succeeded in building your own location bar?

Scorpie
3 Aug 2010, 1:23 PM
Extreme bump, but I got this one working under 3.2.1. Here is the code:




/*
* Copyright 2008, brainbits GmbH All rights reserved.
* Author: Stephan Wentz. swentz[at]brainbits.net
*
* http://www.brainbits.net/
*/
/**
* LocationBar class Version: 0.1
*
* @class Ext.ux.Locationbar
* @extends Ext.Toolbar Locationbar class.
* @constructor Creates a new LocationBar
* @param {Object/Array}
* config A config object or an array of buttons to add
*/
Ext.ux.LocationBar = Ext.extend(Ext.Toolbar,
{
/**
* @cfg {Number} maxItem Maximum number of items the Locationbar takes before
* the first items are removed (defaults to 15). Set to 0 for unlimited
* items.
*/
maxItems : 15,
/**
* @cfg {String} emptyText The that is shown if no history is available
* (defaults to 'No node selected.').
*/
emptyText : 'No node selected.',
/**
* @cfg {Boolean} noReload If set to true the reload button will not be
* visible (defaults to false).
*/
noReload : false,
/**
* @cfg {Function} selectHandler The function to call when clicked. Arguments
* passed are:
* <ul>
* <li><b>node</b> : Object
* <p style="margin-left:1em">
* The node associated with the clicked item.
* </p>
* </li>
* </ul>
*/
selectHandler : null,
/**
* @cfg {Function} reloadHandler The function to call when clicked. Arguments
* passed are:
* <ul>
* <li><b>node</b> : Object
* <p style="margin-left:1em">
* The node associated with the current item.
* </p>
* </li>
* </ul>
*/
reloadHandler : null,
/**
* @cfg {String} locationItems Initial items (defaults to []).
*/
locationItems : [],
/**
* @cfg {String} folderIconCls Iconclass for folder icons.
*/
folderIconCls : 'x-locationbar-folder-icon',
/**
* @cfg {String} folderIconCls Iconclass for the backward icon.
*/
backwardIconCls : 'x-locationbar-back-icon',
/**
* @cfg {String} folderIconCls Iconclass for the forward icon.
*/
forwardIconCls : 'x-locationbar-forward-icon',
/**
* @cfg {String} folderIconCls Iconclass for the reload icon.
*/
reloadIconCls : 'x-locationbar-reload-icon',
/**
* @cfg {Ext.tree.TreePanel} tree The treePanel this Locationbar is associated
* with.
*/
tree : null,
// private
historyItemNodes : {},
// private
historyItems : [],
// private
currentItem : false,
// private
historyNext : false,
// private
initComponent : function()
{
if (this.tree)
{
this.tree.getSelectionModel().addListener('selectionchange', function(sm, node)
{
this.setNode(node);
}, this)
}
// this.addListener('render', this.repaint, this);
Ext.ux.LocationBar.superclass.initComponent.call(this);
},
// private
autoCreate :
{
cls : 'x-toolbar x-small-editor x-locationbar',
html : '<table cellspacing="0"><tr></tr></table>'
},
// private
onRender : function(ct, position)
{
Ext.ux.LocationBar.superclass.onRender.call(this, ct, position);
this.repaint();
},
// private
onClick : function(node)
{
if (this.selectHandler)
{
this.selectHandler(node);
} else
{
if (node.parentNode)
{
node.ensureVisible();
}
node.select();
}
},
// private
onReload : function(node)
{
if (this.reloadHandler)
{
this.reloadHandler(node);
} else if (node.reload)
{
node.reload();
}
},
/**
* Clears all items from the LocationBar.
*/
clear : function()
{
this.locationItems = [];
this.repaint;
},
/**
* Sets the current Treenode If a tree was provided as a config to this
* LocationBar, this should be called automatically.
*
* @param {Ext.ux.TreeNode}
* node The currently selected TreeNode
*/
setNode : function(node)
{
var path = [];
var pNode = node;
var i;
do
{
var conf =
{
text : pNode.attributes.text,
node : pNode,
handler : this.onClick.createDelegate(this, [ pNode ], false)
};
if (pNode.childNodes.length)
{
var childs = [];
for (i = 0; i < pNode.childNodes.length; i++)
{
childs[i] =
{
text : pNode.childNodes[i].attributes.text,
node : pNode.childNodes[i],
iconCls : this.folderIconCls,
handler : this.onClick.createDelegate(this, [ pNode.childNodes[i] ], false)
};
}
conf.xtype = 'tbsplit';
conf.menu = childs;
}
conf.fullPath = pNode.getPath('text').substr(1);
path.unshift(conf);
} while (pNode.parentNode && (pNode = pNode.parentNode) && pNode.id != 'root')
this.locationItems = [];
for (i = 0; i < path.length; i++)
{
this.addPathItemRaw(path[i]);
}
this.currentItem = path[path.length - 1];
this.addHistoryItemRaw(this.currentItem);
this.repaint();
},
// private
addHistoryItemRaw : function(item)
{
if (this.historyItems.indexOf(item.text) != -1)
{
this.historyItems.remove(item.text);
delete this.historyItemNodes[item.text];
}
this.historyItems.push(item.text);
this.historyItemNodes[item.text] = item;
},
// private
addPathItemRaw : function(item)
{
// if number of items > maxItems, remove last
if (this.maxItems && this.locationItems.length > this.maxItems)
{
this.locationItems.pop();
}
// put new item at the end
this.locationItems.push(item);
},
// private
repaint : function()
{
if (this.items && this.items.length)
{
var _doLayout = true;
this.items.each(function(item)
{
this.items.remove(item);
item.destroy();
}, this.items);
} else
{
var _doLayout = false;
}
/*
* this.items.each(function(item){ this.items.remove(item); item.destroy(); },
* this.items);
*/
// back button
this.add(
{
cls : 'x-btn-icon',
iconCls : this.backwardIconCls,
handler : function()
{
this.historyNext = this.historyItems.pop();
var itemKey = this.historyItems.pop();
var item = this.historyItemNodes[itemKey];
this.onClick(item.node);
},
scope : this,
disabled : this.historyItems.length > 1 ? false : true
});
// forward button
// TODO: disabled, FUBAR
this.add(
{
cls : 'x-btn-icon',
iconCls : this.forwardIconCls,
handler : function()
{
var node = this.historyNext.node;
this.historyNext = false;
this.onClick(node);
},
scope : this,
disabled : true
// this.historyNext ? false : true
});
this.add(' ', '-', ' ');
if (this.locationItems.length)
{
// folder icon
this.add(
{
cls : 'x-btn-icon',
iconCls : this.folderIconCls,
ctCls : 'x-locationbar-location x-locationbar-location-first',
disabled : true
});
var text;
for ( var i = 0; i < this.locationItems.length; i++)
{
var locationItem = this.locationItems[i];
var item = {};
if (typeof locationItem == 'object')
{
item = locationItem;
} else
{
item.text = locationItem;
}
if (!item.text)
{
item.text = 'n/a';
}
item.handler = this.onClick.createDelegate(this, [ locationItem.node ], false);
item.ctCls = 'x-locationbar-location';
this.add(item);
}
// spacer
// this.addItem(new Ext.ux.LocationBar.Fill());
// new fill class
this.addItem(
{
//cls : 'x-locationbar-location x-locationbar-location-last',
//cls : 'x-locationbar-location',
xtype : 'tbfill'
});
menu = [];
for ( var i = this.historyItems.length - 2; i >= 0; i--)
{
menu.push(
{
text : this.historyItemNodes[this.historyItems[i]].fullPath,
iconCls : this.folderIconCls,
node : this.historyItemNodes[this.historyItems[i]].node,
handler : function(item)
{
this.onClick(item.node);
},
scope : this
});
}
this.add(
{
cls : 'x-btn-icon',
ctCls : 'x-locationbar-location x-locationbar-location-last',
menuAlign : 'tr-br?',
menu : menu
});
if (!this.noReload)
{
this.add(' ');
// reload button
this.add(
{
cls : 'x-btn-icon',
iconCls : this.reloadIconCls,
handler : function()
{
this.onReload(this.currentItem.node);
},
scope : this
});
}
this.add(' ');
} else
{
this.add(
{
cls : 'x-btn-icon',
iconCls : this.folderIconCls,
ctCls : 'x-locationbar-location x-locationbar-location-first',
disabled : true
});
if (this.emptyText)
{
this.add(
{
xtype : 'lbtext',
text : this.emptyText
});
}
this.addItem(new Ext.ux.LocationBar.Fill());
this.add(
{
cls : 'x-btn-icon',
ctCls : 'x-locationbar-location x-locationbar-location-last',
menuAlign : 'tr-br?',
disabled : true
});
this.add(' ');
this.add(
{
cls : 'x-btn-icon',
iconCls : this.reloadIconCls,
disabled : true
});
this.add(' ');
}
if (_doLayout === true)
{
this.doLayout();
}
}
});
Ext.reg('locationbar', Ext.ux.LocationBar);
Ext.ux.Fill = Ext.extend(Ext.Toolbar.Spacer,
{
// private
render : function(td)
{
td.style.width = '100%';
Ext.fly(td).addClass('x-locationbar-location');
Ext.ux.Fill.superclass.render.call(this, td);
}
});
Ext.reg('tbfill', Ext.ux.Fill);
Ext.ux.LocationBar.Fill = Ext.extend(Ext.Toolbar.Fill,
{
// private
render : function(td)
{
td.className = 'x-locationbar-location';
// insert a &nbsp;
var data = document.createTextNode('\u00a0');
this.el.appendChild(data);
Ext.ux.LocationBar.Fill.superclass.render.call(this, td);
}
});
Ext.reg('lbfill', Ext.ux.LocationBar.Fill);
Ext.ux.LocationBar.TextItem = Ext.extend(Ext.Toolbar.TextItem,
{
// private
render : function(td)
{
td.className = 'x-locationbar-location';
Ext.ux.LocationBar.Fill.superclass.render.call(this, td);
}
});
Ext.reg('lbtext', Ext.ux.LocationBar.TextItem);





[/php]




Just replace the contents of the Ext.ux.locationbar class with this, it should work straight away.

temporary
3 Aug 2010, 1:32 PM
Hey guys. We're in the middle migrating our app to Ext 3.x, I'll have a look into this in the next days.
Will update the first post afterwards, thanks for your help, Scorpie

temporary
3 Aug 2010, 2:08 PM
Scorpie, can you post your code again? Looks completely messed up...

Scorpie
3 Aug 2010, 10:56 PM
Will do so tonight. Maybe something went wrong in copy pasting it here...

Scorpie
4 Aug 2010, 10:30 AM
Fixed my original post!