PDA

View Full Version : TreePanelFilter Plugin



mabello
5 Jun 2008, 9:56 AM
I keep updating this first post with the updated version of the extension and examples (see attachment)

Extension goal:
Adding a filter to a TreePanel (API Doc style), so that you can have a TextField in the toolbar (bottom or top, depending on the cfg object passed to the TreePanelFilter ;) ) and use it to filter the nodes in the tree.

This extension make use of the extension of the prototype of the native javascript array you can find here:
http://extjs.com/forum/showthread.php?t=37697
It has been included in the attachment.

Besides, in the example (attachment) I'm using another extension for the creation of the TreePanel (http://extjs.com/forum/showthread.php?p=124458#post124458);
However, the plugin works with a normal TreePanel.


Development history:

Version 1.2 alfa
****************
ADDED CLASS:
Ext.ux.SearchField as a nice clearer text field.

ADDED IN
TreePanelFilterPlugin cfg object: textFieldType, support 2 value
1) 'auto' means that the search start with the keydown event of the text field (after the buffering time)
2) 'manual' means that you need to click in the search button next to the text field or press enter when the text field has focus to start searching; default to 'manual'

ADDED FILE:
Ext.us.TreeFilterPluginAllInOne.js as a all in one solution to use the extension

Version 1.1 alfa
****************

ADDED: Ext.ux.StartWithTreeFilter class; it has the responsability to filter the nodes.
Must honour this contract interface


//@Public function called before filter is applied(before the execution of the filterFn;); return true to cancel the execution of the operation.
this.beforeFilterFn = function(text, treePanel, treeFilter){
return false;
}

//@Public function called for each node on the tree starting from the root. Return true if you want to keep the node; all the nodes are processed starting from the root
this.filterFn = function(node, text, treePanel, treeFilter){
}

//@Public function called after the execution of the filterFn.
this.afterFilterFn = function(text, treePanel, treeFilter){
}

CHANGED: cfg object to pass to an instance of Ext.ux.TreeFilterPlugin (see the example)


var cfg = {
toolbarPosition: //OPTIONAL @String: 'top', 'bottom', the toolbar position in which you want to add the TextField used to filter. If does not exit it will be created.
,insertAt: //OPTIONAL @Integer: the position in which you want to add the TextField filter in the toolbar.
,width: //OPTIONAL @String: TextField width.
,emptyText: //OPTIONAL @String: TextField empty text.
,label: //OPTIONAL@String: label before the text field; null or '' if you do not want to show any label.
,treeFilterCfg: //OPTIONAL @Object: TreeFilter cfg object (see API TreeFilter)
,filterInstance://OPTIONAL @Object: need to honour the contract described by Ext.ux.StartWithTreeFilter
,nodeAttribute://OPTIONAL @Object: the neame of the attribute that will be passed to the filterInstance in the filterFn
};

ATTACHMENT: in the example I'm using another extension for the creation of the TreePanel (http://extjs.com/forum/showthread.php?p=124458#post124458);
However, the plugin works with a normal TreePanel ;)


Version 1.0alfa
****************

-Initial release

By default, the plugin executes a "start with" filter on the text attribute of the node (it will be configurble).
You can pass a cfg object to an instance of TreeFilterPlugin:


var cfg = {
toolbarPosition: //OPTIONAL @String: 'top', 'bottom', the toolbar position in which you want to add the TextField used to filter. If does not exit it will be created.
,insertAt: //OPTIONAL @Integer: the position in which you want to add the filter.
,width: //OPTIONAL @String: TextField width.
,emptyText: //OPTIONAL @String: TextField empty text.
,label: //OPTIONAL@String: label before the text field; null or '' if you do not want to show any label.
,treeFilterCfg: //OPTIONAL @Object: TreeFilter cfg object (see API TreeFilter)
,beforeFilterFn(text, treePanel, treeFilter): //OPTIONAL @Function called before filter is applied(before the execution of the filterFn;); return true to cancel the execution of the operation.
,filterFn(node, text, treePanel, treeFilter): //OPTIONAL @Function called for each node on the tree starting from the root.
,aftetFilterFn(text, treePanel, treeFilter): //OPTIONAL@Function called after filter after the execution of the filterFn.
,filterFnScope: //OPTIONAL @Object: the scope of the filterFn function, default the current node.
};


Public methods:



//@Return the inner TreeFilter instance.
getTreeFilter()

//@Return the inner TextField instance.
getTextField()

//@clear the filter and the value of the TextField
clearFilter():


****************

Examples and explanations:

Simply, add the plugin to a TreePanel:



var treeFilterPlugin = new Ext.ux.TreeFilterPlugin({
toolbarPosition:'top'
,width: '170'
,label: 'Start with: '
});

treePanel = new Ext.tree.TreePanel({
title: 'Users',
...
plugins: [treeFilterPlugin]
});

Cheers

NoahK17
5 Jun 2008, 11:30 AM
tbar.insertAt is not a function

Is the error I get. Not sure what's going on with this line: tbar.insertAt(textField, defaultCfg.insertAt);

mabello
5 Jun 2008, 12:03 PM
Dear NoahK17,

Sorry about that.

I'm using also this extension (I've forgotten to include it!)

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

Now I have included it in the .zip and I have uploaded the right attachment (hopefully) ;)

The plugin is also changed, check out the first post.

Sorry again and thank you very much for your help.

Marco

galdaka
5 Jun 2008, 11:24 PM
Live example for test please!!

Thanks in advance,

galdaka
6 Jun 2008, 1:12 AM
Hi,

Live demo in: http://www.galdaka.es/

1) Is posible that not appears vertical scroolbar?

2) The search not work for me

3) Is posible put config text like "no itens found" in tree when the search resturn nothing.

4) Use Clearable textfield for erase the text.


Thanks in advance,

mabello
6 Jun 2008, 1:30 AM
Dear galdaka,
Thanks for your help and for the live demo.
I will upload an example asap, and probably I have also to change a little the TreeFilterPlugin class (I will update my first post).

1)Scrollbars depends on the TreePanel config, TreePaanelFilter is completely independent from the configuration of the TreePanel, so I don't think it could be the problem.

2)About the search, I need to upload the next version of TreeFilterPanel Plugin: in the current release, the search is done as a "start as filter" using the text attribute of the node. Anyway,I will upload an example and a small enhanchment to the plugin to fix it.

3)I think it is easy to achieve, but I still need to make up my mind about different things, this is a very alpha release, so thanks fo the suggestion.

4)Yes, this is another funcionality that could be easly be achievable, so I will do that asap, thanks again

So for now, I will update the first post with an example.

Thanks again and sorry for the problems.

mabello
6 Jun 2008, 5:25 AM
I have added an example in my attachment and I have also changed the architecture of the plugin.
Thanks
@Galdaka: let me know if it works for you please and sorry again.

galdaka
6 Jun 2008, 5:24 PM
Is posible put all .js in one UX?

Or put two version of your plugin: separately version (Your architecture and All-in-one)

I think is much easy for use All-in-one,


Thanks in advance,

galdaka
7 Jun 2008, 1:36 AM
I have added an example in my attachment and I have also changed the architecture of the plugin.
Thanks
@Galdaka: let me know if it works for you please and sorry again.

Hi,

Not work properly in www.galdaka.es (http://www.galdaka.es).

1) The search field not appears correctly (Without empty text, etc...) and in some case (View 'Proyectos' treepanel not appears!!)

2) I make a mistake, the search work fine; But only work in parent childs. Not work in childnodes...

3) Is posible auto-adjust the searchfield in toolbar? Or make a config option for auto-adjust?

Thanks in advance,

mabello
9 Jun 2008, 1:47 AM
Dear Galdaka,

Yes, I've seen that in your nodes the text was starting with an empty character " Ext" so the problem for the search was that.

1.
I have also fixed the emptyText for the TextField, not it works right for me and I have add as you suggested the Ext.ux.TreeFilterPluginAllInOne file as a nice solution to use the plugin using only this "all in one" file. Please check out my first post, I have upload it with the last changes.

About the error that the search field does not appear, I have to try and play with it, but I have made a small hack to create dinamically the toolbar, so I will fix it asap, thanks for pointing out the bug.

2.
The search works according to the implementation of the TreeFilter class of ext: when you filter a node, also the children are filtered no matter what (see function filter and filterBy of Ext.tree.TreeFilter); however, if you check out my example, yuo can easly implement your StartWithTreeFilter that do not cut leaves or whatever; this is really more "business dependent" I mean it depends on your application needs. I'm sure it will be simple to implement your own filter following the Ext.ux.StartWithTreeFilter interface.

3.
What do you mean with auto-adjust? In this moment you can specify the width of the TextField and the position in the toolbar (if your toolbar has already buttons etc, you can use the cfg property insertAt to insert the textField in the position you like). Can you explain me what do you mean with that, so I can check if I can easly implement it

Thanks

galdaka
9 Jun 2008, 3:32 AM
(Sorry for my English)

Thanks for your response,


1) I remove the blank spaces for beginning of text nodes. Now the search works fine. Thanks. But in my case, the return nodes not contains chilnodes as your example. For example, If you search "Ext" only return the node that contain "Ext" and not her childnodes.

2) If you have a lot of nodes, when you click "X" for return from the search. The original tree expands all nodes and is very dificult view the original structure of the tree. This is a minor thing.

3) I think the best architecture is: Ext.ux.TreeFilterPluginAllInOne.js but without Ext.ux.SearchField.js. Because search field would be a common piece in many places of the applicattion.

4) The auto-expand option for the seacrh field. I

galdaka
9 Jun 2008, 1:03 PM
I use this modify of Ext.ux.FitToParent for adjust treePanel and hidden scrollbars that appears when your plugin create the toolbar:

http://www.extjs.com/forum/showthread.php?p=179494#post179494

View the results in: www.galdaka.es (http://www.galdaka.es) (West panel)

Greetings,

mabello
9 Jun 2008, 3:02 PM
Good job galdaka!

For the search, I think you need to implement something "ad hoc" for your needs; check out in my example the Ext.ux.DecoratorTreeFilter.js; you probably need to use some infos in your nodes and decide how you want to filter the nodes using that infos. When I have time, I will try to implement the filter you need.

The SearchField component is an extension of the Ext.form.TwinTriggerField; The SearchField class has reference to the TreeFilterPlugin, so is not very generic, it is really business dependent; but you have already the reusable generic component you are looking for, and it is the Ext.form.TwinTriggerField. You can see SearchField as an internal class of my plugin, it is not intended to be a reusable component, because the reusable component in my opinion is Ext.form.TwinTriggerField; check SearchField implementation out, the only code I have added is not reusable if not in the context of my plugin.

I agree with you, I can remove the expand all of the tree, I will do that in the next release, and I will try to fix the bug you have pointed out about the TextField not appearing in accordion layout...

About the auto-expand option: the toolbar is not a container (does not extend Container class), so I'm not sure that http://extjs.com/learn/Extension:FieldAutoExpand will do the job...next release of Ext (3.0) will fix this problem though and the toolbar will be really more powerful and easy to use.

Thanks for your help, I really appreciate it!

And by the way, your english is good!

c.barca
27 Jun 2008, 4:48 AM
Hi Marco,

I'm playing with your TreePanel filter plugin, it work but I need to search a text into all children nodes, include relative parents.

I see your StartWithTreeFilter code, but I don't know how parameter I must set for this search type.

Can you help me please ?

Grazie Marco, ottimo lavoro. :)

Claudio

mabello
28 Jun 2008, 9:15 AM
Dear Claudio,
Can you please try give a shot to the Ext.ux.TreeDecoratorFilter class that you can download with the zip of the extension in my first post?

TreeDecoratorFilter works so that only leaves are filtered using a "start with" filter, while the other nodes are never filtered (it is a "decorator" of the StartWithFilter)



Ext.namespace('Ext.ux');
//Custom filter implementation;
Ext.ux.DecoratorTreeFilter = function(){
var startTreeFilter = new Ext.ux.StartWithTreeFilter();
var re = null;
//@Public function called before filter is applied(before the execution of the filterFn;); return true to cancel the execution of the operation.
this.beforeFilterFn = function(text, treePanel, treeFilter){
return startTreeFilter.beforeFilterFn(text, treePanel, treeFilter);
}
//@Public function called for each node on the tree starting from the root.
this.filterFn = function(node, nodeAttribute, text, treePanel, treeFilter){
//Filter only the lives
return (startTreeFilter.filterFn(node, nodeAttribute, text, treePanel, treeFilter) || node.attributes['leaf'] == false);
}
//@Public function called after filter after the execution of the filterFn.
this.afterFilterFn = function(text, treePanel, treeFilter){
return startTreeFilter.beforeFilterFn(text, treePanel, treeFilter);
}
}

In Ext.ux.DecoratorTreeFilter implementation, filterFn function return always true (true means do not filter the node) if a node is NOT a leaf; if the node IS a leaf, the function return false (false means the node ha to be filtered) ONLY if the text of the node does not start with the sentence written in the SearchTextBox.
Ext.ux.DecoratorTreeFilter requires though that when you build your tree, each node asserts if it is a leaf node or not, like in my example.
Please let me know if it works for you.
Thank you very much for helping to improve the extension, and welcome to the forum
Marco

paulyb263
14 Aug 2008, 2:35 AM
When i download and try to unzip the Ext.ux.TreeFilterPlugin.zip file i am getting the message -

'The compressed folder is invalid or corrupt'

Would someone be so kind as to send me the file?

Thanks :)

mystix
14 Aug 2008, 7:19 AM
download with FF instead of IE

paulyb263
14 Aug 2008, 7:43 AM
Great worked a treat! thanks :D

paulyb263
16 Aug 2008, 1:05 AM
This is a neat plugin, however, Im having trouble getting it to filter out all non-leaf nodes that dont contain the search text

So at the moment my tree looks like this:-

http://img186.imageshack.us/img186/411/isst9.gif

As you can see it is not filtering the non-leaf nodes that dont contain the text 'Test'

I want it to look like this:-

http://img507.imageshack.us/img507/6794/wantax6.gif

Like in the GWT implemention:-

http://extjs.com/explorer/#filtertree

http://img524.imageshack.us/img524/618/srcrr6.gif

Ive tried modifying the code so that it filters out non-leaf nodes but then it filters out the child nodes aswell including the ones that include the search text

Anyone done anything similar or have any ideas?

Ive spent a lot of hours on this and I'm starting to think its not possible :(

mabello
25 Aug 2008, 9:04 AM
@paulyb263
Hi there,
I was on holiday, I'm really sorry for my late answer!
Yeah, I know what you mean.
I think that for something like that, the easy way is to create the tree from the beginning, since the plugin is based on the TreeFilter implementation of ext, to achieve what you need could be not that trivial.
If I found an easy way to achieve your goal, I'll let you know!
Thanks

mabello
18 Dec 2008, 4:11 AM
@paulyb263

Hi there.
Internally I was using Ext.tree.TreeFilter.
Instead of the Ext default implementation, you can use Ext.ux.tree.TreeFilterX from Saki's extension:

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

So you can:

1)Add Saki's extension.
2)Change my code Ext.ux.TreeFilterPlugin
to use Ext.ux.tree.TreeFilterX


textField = new Ext.ux.SearchField(textFieldCfg);

filter = new Ext.ux.tree.TreeFilterX (treePanel, defaultCfg.treeFilterCfg); //<------ use TreeFilterX

tbar.insertAt(textField, defaultCfg.insertAt);

3)Create the contains filter and use it



//Custom filter implementation;
Ext.ux.ContainsTreeFilter = function(){
//@Public function called before filter is applied(before the execution of the filterFn;); return true to cancel the execution of the operation.
this.beforeFilterFn = function(text, treePanel, treeFilter){
return false
}
//@Public function called for each node on the tree starting from the root.
this.filterFn = function(node, nodeAttribute, text, treePanel, treeFilter){
var re = new RegExp('.*' + text + '.*', 'i');
return re.test(node.attributes[nodeAttribute]);
}
//@Public function called after filter after the execution of the filterFn.
this.afterFilterFn = function(text, treePanel, treeFilter){
return;
}
}


Hope this helps

victorlrf
15 Jan 2009, 10:30 AM
hi guys it's my first post and sorry about my english :)
so i'm try use this code but a don't
how implement this in my code

this my code
[html]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<title>OS</title>
<link rel="stylesheet" type="text/css" href="/sig/FrameWorks/ext/resources/css/ext-all.css"/>
<script type="text/javascript" src="/sig/FrameWorks/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="/sig/FrameWorks/ext/ext-all.js"></script>

<style type="text/css">
html, body {font: normal 11px verdana;}
#main-panel td {padding:5px;}
.add-feed {background-image: url(feed-viewer/images/rss_add.gif) !important;}
.remove-feed {background-image: url(feed-viewer/images/rss_delete.gif) !important;}
.x-tree-node div.feeds-node{
background:#eee url(images/cmp-bg.gif) repeat-x;
margin-top:1px;border-top:1px solid #ddd;
border-bottom:1px solid #ccc;
padding-top:2px;padding-bottom:1px;}
.feeds-node .x-tree-node-icon {display:none;}
.feed {border:1px solid #fff;margin:3px;}
.feed .x-tree-ec-icon {display:none;}
.feed-icon {background-image:url(/sig/FrameWorks/ext/examples/layout-browser/images/page_attach.png) !important;}

#header { background: #7F99BE url(/sig/FrameWorks/ext/examples/layout-browser/images/layout-browser-hd-bg.gif) repeat-x center;}
#header h1 {font-size: 16px;color: #fff; font-weight: normal;padding: 5px 10px;}
</style>
<script type="text/javascript">



Ext.onReady(function() {

var titulo ={
xtype: 'box'
,title: 'Extend Ordem de Servi

mabello
15 Jan 2009, 10:40 AM
Dear victorlrf,
Welcome to the forum.
In my opinion you'd better off posting that in the help forum, in which you can have more help since in your code you are not using the extension as far as I can tell.

And another gold rule is to embed your code using the HTML or PHP tags, so that it is more readable and you have more chances to get help and fix your problems.

victorlrf
15 Jan 2009, 10:58 AM
[quote=mabello;274216]Dear victorlrf,
Welcome to the forum.
In my opinion you'd better off posting that in the help forum, in which you can have more help since in your code you are not using the extension as far as I can tell.

And another gold rule is to embed your code using the HTML or PHP tags, so that it is more readable and you have more chances to get help and fix your problems.
[html]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<title>OS</title>
<link rel="stylesheet" type="text/css" href="/sig/FrameWorks/ext/resources/css/ext-all.css"/>
<script type="text/javascript" src="/sig/FrameWorks/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="/sig/FrameWorks/ext/ext-all.js"></script>

<style type="text/css">
html, body {font: normal 11px verdana;}
#main-panel td {padding:5px;}
.add-feed {background-image: url(feed-viewer/images/rss_add.gif) !important;}
.remove-feed {background-image: url(feed-viewer/images/rss_delete.gif) !important;}
.x-tree-node div.feeds-node{
background:#eee url(images/cmp-bg.gif) repeat-x;
margin-top:1px;border-top:1px solid #ddd;
border-bottom:1px solid #ccc;
padding-top:2px;padding-bottom:1px;}
.feeds-node .x-tree-node-icon {display:none;}
.feed {border:1px solid #fff;margin:3px;}
.feed .x-tree-ec-icon {display:none;}
.feed-icon {background-image:url(/sig/FrameWorks/ext/examples/layout-browser/images/page_attach.png) !important;}

#header { background: #7F99BE url(/sig/FrameWorks/ext/examples/layout-browser/images/layout-browser-hd-bg.gif) repeat-x center;}
#header h1 {font-size: 16px;color: #fff; font-weight: normal;padding: 5px 10px;}
</style>
<script type="text/javascript">



Ext.onReady(function() {

var titulo ={
xtype: 'box'
,title: 'Extend Ordem de Servi

badgerd
22 Mar 2009, 2:32 PM
I am successfully using this Plugin with many "correct" results returned in the tree.

However, when the tree has lots of results it appears that the tree "freezes" and does not show that it is working. After a while the results show up.

I have tried using a loading mask in the code, but it does not display/hide at the right time.

I wish to display a "searching..." mask when the user hits the enter key and then removes the mask once all the results are filtered/displayed.

Where in the code would be the best place to put the mask function in? I have tried beforeFilterFn, afterFilterFn, but it does not work correctly there.

mabello
23 Mar 2009, 8:43 AM
So something like this:



this.beforeFilterFn = function(text, treePanel, treeFilter){
treePanel.body.mask("Loading data...");//<------
return startTreeFilter.beforeFilterFn(text, treePanel, treeFilter);
}
//@Public function called for each node on the tree starting from the root.
this.filterFn = function(node, nodeAttribute, text, treePanel, treeFilter){
//Do not filter the lives if the node is to keep
return (startTreeFilter.filterFn(node, nodeAttribute, text, treePanel, treeFilter) || node.attributes['leaf'] == true);
}
//@Public function called after filter after the execution of the filterFn.
this.afterFilterFn = function(text, treePanel, treeFilter){
treePanel.body.unmask();//<------
return startTreeFilter.beforeFilterFn(text, treePanel, treeFilter);
}


does not work?
I guess because to display the mask takes time and if the rendering of the tree start strightaway after treePanel.body.mask("Loading data...") the mask does not show up since the browser freezes before displaying it...

asalee200
10 Dec 2010, 2:00 PM
Hi mabello,

I need to make a panel, just like the Extjs API with a TreePanel and filter field.

Therefore, I am trying to use TreePanelFilter plugin, you have attached on this thread. I am using the AllinOne script but I am getting this error.
tbar.insertAt is not a function

I have gone the thru the script, it does contain the insertAt function.

I would really appreciate your help, it kind of urgent for me.

asalee200
10 Dec 2010, 2:43 PM
Hi,

I have fixed the tbar.insertAt is not a function error. But now, I have new error.

this.topToolbar.render is not a function.

I can't even find this function in the scripts.

Please help.

ucoxk
3 Jul 2012, 2:47 AM
i also have this error tbat.insertAt is not a function. how can i fix it?