diff --git a/buildVersion.py b/buildVersion.py
index 704723fcb59dcdf11cf7e130abcfebadbf708908..1985ae0cfa5dd896f57fef3065240ba5de732cfc 100755
--- a/buildVersion.py
+++ b/buildVersion.py
@@ -47,7 +47,7 @@ print '\nStart buildVersion'
 #
 APP = 'mygit_dbui_04x'
 CHANGELOG = 'static/plugin_dbui/CHANGELOG'
-DBUI_W2P = 'web2py.plugin.dbui.w2p'
+DBUI_W2P = 'web2py.plugin.dbui.%s.w2p'
 JSBASE = 'static/plugin_dbui/src/appbase.js'
 JSLIBDEBUG = 'static/plugin_dbui/dbui-debug.js'
 JSLIBMIN = 'static/plugin_dbui/dbui-min.js'
@@ -55,6 +55,11 @@ JSLIBSRC = 'static/plugin_dbui/src'
 NOW = datetime.datetime.now()
 PACK_PLUGIN_URL = 'http://localhost:8000/%s/default/pack_plugin' % APP
 
+def get_version():
+    s = open(JSBASE, 'rb').read()
+    m = re.match("(.+App.version = ')([\w._-]*)(';.*)", s, re.DOTALL)
+    return m.group(2).replace('.', '')
+    
 #-----------------------------------------------------------------------------
 #    define main applications
 #
@@ -132,10 +137,13 @@ if not (opt.update or opt.git or opt.yuicompressor or opt.web2py):
 #-----------------------------------------------------------------------------
 #     clean previous build
 if opt.clean:
-    os.remove(DBUI_W2P)
-    os.remove(JSLIBDEBUG)
-    os.remove(JSLIBMIN)
-    print 'files', DBUI_W2P, JSLIBDEBUG, JSLIBMIN, 'removed.'
+    fn = DBUI_W2P % get_version()
+        
+    for el in (fn , JSLIBDEBUG, JSLIBMIN):
+        if os.path.exists(el): 
+            os.remove(el)
+            print 'file', el, 'is removed.'
+        
     sys.exit(0)
 
 #-----------------------------------------------------------------------------
@@ -229,16 +237,20 @@ if opt.git:
 #    web2py step
 #
 if opt.web2py:
+    # get the plugin version
+    version = get_version()
+
     # build the web2py plugin
     print 'Build the web2py plugin binary file'
     raw_input('Check that the web2py service is running ? Type CR to continue.')
     f = urllib.urlopen(PACK_PLUGIN_URL)
     s = f.read()
     
-    fi = open(DBUI_W2P, 'wb')
+    fn = DBUI_W2P % version
+    fi = open(fn, 'wb')
     fi.write(s)
     fi.close()
-    print 'file', DBUI_W2P, 'is written.'
+    print 'file', fn, 'is written.'
 
 #-----------------------------------------------------------------------------
 #     exit
diff --git a/models/widgets.py b/models/widgets.py
index cc59e2ce336c39dadb7e123c78540a57838a7514..649988e63088c0d91ef0d249dd2f9b0b0609aa13 100755
--- a/models/widgets.py
+++ b/models/widgets.py
@@ -179,19 +179,21 @@ gridModifier.set_filters(*filters,
 #
 # The navigation tree
 #
-formNode = dbui.Node(T('Forms'), 
-                     db.tables, 
-                     configurator=lambda tablename: cvtSvc.to_form_panel(db[tablename]))
-
-gridNode = dbui.Node(T('Tables'), 
-                     db.tables, 
-                     configurator=lambda tablename: cvtSvc.to_grid_panel(db[tablename]))
-
-reportNode = dbui.Node(T('Reports'),
-                       {'report_1': URL(c="reports", f="report_1"),
-                        'report_2': (URL(c="reports", f="report_2"), cvtSvc.to_form_items(dummy.foo1))},
-                       configurators={'report_1': dbui.to_urlPanel,
-                                      'report_2': dbui.to_panelWithUrlSelector})
+formNode = dbui.Node(T('Forms'))
+configurator = lambda tablename: cvtSvc.to_form_panel(db[tablename])
+formNode.add_children(db.tables, func=configurator)
+
+gridNode = dbui.Node(T('Tables'))
+configurator = lambda tablename: cvtSvc.to_grid_panel(db[tablename]) 
+gridNode.add_children(db.tables, func=configurator) 
+
+reportNode = dbui.Node(T('Reports'))
+cfg = dbui.to_urlPanel(URL(c="reports", f="report_1"))
+reportNode.add_child(T('report_1'), cfg)
+
+form_items = cvtSvc.to_form_items(dummy.foo1)
+cfg = dbui.to_panelWithUrlSelector(URL(c="reports", f="report_2"), form_items)
+reportNode.add_child(T('report_2'), cfg)
 
 viewportModifier = dbui.ViewportModifier()
 viewportModifier.add_node(formNode, gridNode, reportNode)
diff --git a/modules/plugin_dbui/navtree.py b/modules/plugin_dbui/navtree.py
index 895a7c1d26e394f2d6cd556ac4da7d4e49dcfa82..bc0d6ad1d8da59ce8a40dfe10471bb420f4c1148 100644
--- a/modules/plugin_dbui/navtree.py
+++ b/modules/plugin_dbui/navtree.py
@@ -9,28 +9,36 @@ from gluon import current
 from helper import is_mathjax
 
 
-def to_panelWithUrlSelector(key, value):
-    """Return the configuration dictionary for a App.PanelWithUrlSelector.
+def to_panelWithUrlSelector(baseUrl, 
+                            formItems, 
+                            ctrlField=None, 
+                            title='Configure'):
+    """Return the configuration dictionary for an App.PanelWithUrlSelector.
     the main panel displays the URL content while the selector panel shows
-    a form allowing to change the URL argument. 
+    a form allowing to change the URL setting. 
     
-        key
-            it the name of the leaf
+        baseUrl
+            well-formed URL string, i.e http://blabla
 
-        value
-            tuple containing a well form URL string 
-            and a list of configuration dictionary defining each items
-            embedded in the form.
+        ctrlField
+            name of the form field defining the controller
+            When define the URL become http://blabla/ctrlFieldValue
+        
+        formItems
+            a list of configuration dictionary defining the
+            widget embedded in the form
+            
+        title
+            title of the box surrounding form widgets
             
     """
-    url, cfg_form_items = value
-    
-    cfg = {'baseUrl': url,
+    cfg = {'baseUrl': baseUrl,
+           'ctrlField': ctrlField,
            'panelCfg': None,
            'selectorCfg':None,
            'xtype': 'xpanelwithurlselector'}
 
-    # configuration of the main panel displaying url
+    # configuration of the main panel displaying URL
     cfg['panelCfg'] = {'plugins': [], 
                        'preventBodyReset': True,
                        'xtype': 'panel'}
@@ -40,22 +48,19 @@ def to_panelWithUrlSelector(key, value):
                            
     # configuration of the selector
     cfg['selectorCfg'] = {'defaults': {'anchor': '99%'},
-                          'items': cfg_form_items,
-                          'title': 'Configure',
+                          'items': formItems,
+                          'title': title,
                           'xtype': 'fieldset'}
       
     return cfg
 
 
-def to_urlPanel(key, url):
+def to_urlPanel(url):
     """Return the configuration dictionary for an Ext.Panel
     displaying an URL.
     
-        key
-            it the name of the leaf
-
         url
-            its content is displayed in the panel
+            well-formed URL string, i.e http://blabla
     
     """
     cfg = {'autoLoad': url,
@@ -72,48 +77,54 @@ def to_urlPanel(key, url):
 class Node(object):
     """Node associating a leaf to a widget.
     
-    Leaf names can be a list of string or dictionary keys.
-    They are translated and sorted by alphabetic order.
-    Some of them my be hidden depending on the context.
-
-    We use a configurator to get the configuration object of the
-    target widget. It is a function getting the leave names, its
-    attributes (dictionary value) and returning a dictionary.
-    
-    Dedicated configurator can be setup for each node if needed.
     """
-    def __init__(self, text, leaves, configurator=None, configurators={}, hidden=[]):
+    def __init__(self, text):
         """Constructor of the node
         
                 text
                     name of the node appearing in the viewport
+                                    
+        """
+        self.text = text
+        self.children = []
+        self.hidden = []
+
+
+    def add_child(self, text, cfg):
+        """Add a child (leaf) to the node.
+        
+                text
+                    the name of the leaf
                     
+                cfg
+                    configuration dictionary for the associated
+                    ExtJS widget
+
+        """
+        di = {'cfg': cfg, 'leaf': True, 'text': text}
+        self.children.append(di)
+
+
+    def add_children(self, leaves, func=None, hidden=[]):
+        """Helper method to add children to the node.
+        
                 leaves
-                    list of string or a dictionary where keys
-                    will be used as leaf names
+                    a list of string
                     
-                configurator
-                    The default configurator apply to all leaves.
-                    Reference to a function accepting either a leave name
-                    or a leave name and the dictionary value. The function
-                    return the configuration dictionary for the ExtJS widget. 
-                    The function defines the type of widget.
-                
-                configurators
-                    A dictionary with references to configurator.
-                    It can be used to associate a different configurator to
-                    each leaf. The key is the leaf name.
+                func
+                    function to translate the leaf name into 
+                    the configuration dictionary of the associated ExtJS widget
+
                 hidden
-                    List of leaves to be hidden. It contains leaves names
-                
-        """
-        self.text = text
-        self.children= []
+                    List of children to be hidden
+                    
+        Leaf names are translated and sorted by alphabetic order.
 
+        """
         # translator
         T = current.T
         
-        # converter to order leaves in alphabetic order 
+        # translate and order leaves in alphabetic order 
         # according to local setting
         cvt = {}
         for el in leaves:
@@ -128,30 +139,7 @@ class Node(object):
             if leaf in hidden:
                 continue
 
-            func = configurator
-            if leaf in configurators:
-                func = configurators[leaf]
-            
-            if isinstance(leaves, (list, tuple)):
-                self._add_children(tr_leaf, func(leaf))
-                
-            elif isinstance(leaves, dict):
-                self._add_children(tr_leaf, func(leaf, leaves[leaf]))
-
-
-    def _add_children(self, text, cfg):
-        """ Add a child (leaf) to the node.
-        
-                text
-                    the name of the leaf
-                    
-                cfg
-                    configuration dictionary for the associated
-                    ExtJS widget
-
-        """
-        di = {'cfg': cfg, 'leaf': True, 'text': text}
-        self.children.append(di)
+            self.add_child(tr_leaf, func(leaf))
                 
 
     def get_node(self):
diff --git a/static/plugin_dbui/CHANGELOG b/static/plugin_dbui/CHANGELOG
index 7f112f12aca61b0f48f21d42adf0858f5c770846..4287c71037ade17c918486efdb155e61381ddeae 100644
--- a/static/plugin_dbui/CHANGELOG
+++ b/static/plugin_dbui/CHANGELOG
@@ -1,7 +1,13 @@
 --------------------------------- CHANGE LOG ----------------------------------
 
 HEAD
-  - script to build the and tag a new version of plugin_dbui
+
+0.4.4 (Jan 2012)
+
+0.4.4 (Jan 2012)
+  - minor release
+  - script to build and tag a new version of plugin_dbui
+  - improve version of AppPanelWithSelector 
   
 4.3.0 (Dec 2011)
   - Major change which is not backward compatible
@@ -119,4 +125,4 @@ HEAD
 
  0.1.1
   - Tags revision 640 as 0.1.1
-  - First prototype running with web2py 1.63 and ExtJS 2.2.1 (see also 0.1.0 log)
\ No newline at end of file
+  - First prototype running with web2py 1.63 and ExtJS 2.2.1 (see also 0.1.0 log)
diff --git a/static/plugin_dbui/dbui-debug.js b/static/plugin_dbui/dbui-debug.js
index 69392cfc2cbb4e1bfb78903f98c446fe2c468428..b720412e50c743ad279c862582efd1a7fb463ce4 100644
--- a/static/plugin_dbui/dbui-debug.js
+++ b/static/plugin_dbui/dbui-debug.js
@@ -22,7 +22,7 @@ Ext.namespace('App');
 /**
  * @param {String} App.version version of the library
  */
-App.version = '0.4.3';
+App.version = '0.4.4';
 
 /**
  * Helper function mimicking the encode_field function running on the server
@@ -1612,7 +1612,11 @@ Ext.preg('pPanelMathJax', App.panel.MathJax);/**
  * the selector allow to setup the url parameters and to launch the
  * request to the server.
  * 
- *  The type of this component is xpanelwithurlselector.
+ * The url is build as baseUrl or baseUrl/CtrlFieldValue if ctrlField is defined.
+ * The value of the other field are pass as Field1=Field1Value ,Field2=Field2Value
+ * in a POST transfert
+ *
+ * The type of this component is xpanelwithurlselector.
  *  
  * @extend: App.PanelWithSelector
  * 
@@ -1622,10 +1626,21 @@ Ext.namespace('App');
 App.PanelWithUrlSelector = Ext.extend(App.BasePanelWithSelector, {
     
     /**
-     * @param {String}
+     * @param {String} baseurl well form url, i.e http://blabla
      */
     baseUrl: null,
     
+    /**
+     * @param {String} ctrFiedl  name of the field defining the controller
+     * When define the url become http://blabla/ctrlFieldValue
+     */
+    ctrlField: null,
+    
+    /**
+     * Private attributes for internationalization
+     */
+    textLoad: 'Loading...',
+    
     /**
      * Require by the ExtJS model
      */    
@@ -1647,17 +1662,22 @@ App.PanelWithUrlSelector = Ext.extend(App.BasePanelWithSelector, {
             i,
             panel = this.getComponent('mainPanel'),
             params = {},
-            selector = this.getComponent('selectorPanel');
+            selector = this.getComponent('selectorPanel'),
+            url = this.baseUrl;
             
         fields = selector.findByType('field');
         for (i = 0; i < fields.length; i += 1) {
-            params[fields[i].getName()] = fields[i].getValue();
+            if(fields[i].getName() === this.ctrlField) {
+                url = url + '/' +  fields[i].getValue();
+            } else {
+                params[fields[i].getName()] = fields[i].getValue();    
+            }
         }
 
         panel.load({
-            url: this.baseUrl,
+            url: url,
             params: params,
-            text: 'Loading...',
+            text: this.textLoad,
             timeout: 30 
         });        
     },
diff --git a/static/plugin_dbui/dbui-min.js b/static/plugin_dbui/dbui-min.js
index 337c4ca42cbbfed123f4176fb1d4227860006c6b..1d29bb54813128725d2d5b9808ff73235826694c 100644
--- a/static/plugin_dbui/dbui-min.js
+++ b/static/plugin_dbui/dbui-min.js
@@ -1 +1 @@
-Ext.namespace("App");App.version="0.4.3";App.encodeField=function(b,d){var a,c;a=b[0].toUpperCase()+b.slice(1,b.length);c=d[0].toUpperCase()+d.slice(1,d.length);return a+c};App.getDirectStore=function(b){var a,c,d;c=Ext.StoreMgr.lookup(b);if(!c&&!Ext.isString(b)){throw new Error('Fail to instanciate the store: "'+b+'"')}if(!c&&Ext.isString(b)){d=b.slice(0,b.search("Store"));a=App.storeCfgs[d];c=new App.data.DirectStore(a)}return c};App.getTableName=function(a){return a.baseParams.tableName};App.isPlugin=function(a,d){var b,c;if(!a.hasOwnProperty("plugins")){return false}for(b=0;b<a.plugins.length;b+=1){c=a.plugins[b];if(c===d){return true}if((typeof(c)==="object")&&c.hasOwnProperty("ptype")&&(c.ptype===d)){return true}}return false};Ext.namespace("App");App.BasePanelWithSelector=Ext.extend(Ext.Panel,{panelCfg:null,selectorCfg:null,textGo:"Go",textReset:"Reset",constructor:function(d){var c,b,a;Ext.apply(this,d);b=Ext.ComponentMgr.create(this.panelCfg);a=Ext.ComponentMgr.create(this.selectorCfg);c={layout:"border",items:[{border:false,layout:"fit",itemId:"mainPanel",items:[b],region:"center",},{buttons:[{ref:"../../goButton",text:this.textGo},{ref:"../../resetButton",text:this.textReset}],collapsible:true,defaults:{anchor:"99%"},frame:true,layout:"form",itemId:"selectorPanel",items:[a],region:"east",split:true,width:300,}]};Ext.apply(this,c);App.BasePanelWithSelector.superclass.constructor.call(this)}});Ext.reg("xpanelwithselector",App.BasePanelWithSelector);Ext.namespace("App");App.ButtonDownload=Ext.extend(Ext.Button,{url:undefined,initComponent:function(){App.ButtonDownload.superclass.initComponent.call(this);this.on("click",this.onDownload,this)},onDownload:function(a,c){try{Ext.destroy(Ext.get("downloadIframe"))}catch(b){}Ext.DomHelper.append(document.body,{tag:"iframe",id:"downloadIframe",frameBorder:0,width:0,height:0,css:"display:none;visibility:hidden;height:0px;",src:this.url})}});Ext.reg("xbuttondownload",App.ButtonDownload);Ext.namespace("App.form");App.form.ComboBox=Ext.extend(Ext.form.ComboBox,{mode:"remote",editable:false,selectOnFocus:true,triggerAction:"all",typeAhead:true,initComponent:function(){if(this.fieldLabel&&!this.emptyText){this.emptyText="Select a "+this.fieldLabel+" ..."}this.store=App.getDirectStore(this.store);App.form.ComboBox.superclass.initComponent.call(this);if(this.store.getCount()===0){this.store.load()}this.store.on("load",function(){this.setValue(this.initialConfig.value)},this)}});Ext.reg("xcombobox",App.form.ComboBox);Ext.namespace("App.form");App.form.FormPanel=Ext.extend(Ext.form.FormPanel,{store:null,autoScroll:true,bodyStyle:"padding:5px 5px 0",buttons:[{formBind:true,text:"Action",ref:"../buttonAction"},{text:"Reset",ref:"../buttonReset"}],defaults:{anchor:"100%"},defaultType:"textfield",frame:true,monitorValid:true,currentAction:null,currentRecord:null,textCreate:"Create",textDestroy:"Delete",textDuplicate:"Duplicate",textReset:"Reset",textUpdate:"Update",initComponent:function(){function a(){this.reset()}App.form.FormPanel.superclass.initComponent.call(this);this.buttonAction.on("click",this.doAction,this);this.buttonReset.on("click",a,this.getForm());this.addFieldToolTipsListeners();this.store=App.getDirectStore(this.store);this.store.on("exception",this.onStoreException,this);this.store.on("write",a,this.getForm());this.setAction("create");this.buttonReset.setText(this.textReset)},addFieldToolTipsListeners:function(){var b;function a(d){new Ext.ToolTip({target:d.getEl(),title:d.fieldLabel,anchor:"left",trackMouse:false,html:Ext.util.Format.htmlEncode(d.tipText)})}b=this.getForm();b.items.each(function(c){if(c.tipText){c.on("render",a)}})},disableFields:function(a){var b=this.getForm();b.items.each(function(c){c.setDisabled(a)})},doAction:function(){var b=this.getForm(),a;if(!b.isValid()){return}if(!this.store){throw new Error("the store is undefined !!!")}switch(this.currentAction){case"create":a=new this.store.recordType();this.updateRecord(a);this.store.add(a);break;case"destroy":this.store.remove(this.currentRecord);break;case"duplicate":a=new this.store.recordType();this.updateRecord(a);this.store.add(a);break;case"update":this.currentRecord.beginEdit();this.updateRecord(this.currentRecord);this.currentRecord.endEdit();break}if(this.store.autoSave===false){this.store.save()}},hardReset:function(){var a=this.getForm();a.items.each(function(b){b.originalValue=Ext.value(b.initialConfig.value,"");b.setValue(b.originalValue)})},onStoreException:function(e,f,b,j,c,i){var g,h,a=this.getForm(),d;for(h in c.errors){if(c.errors.hasOwnProperty(h)){g=a.findField(h);g.markInvalid(c.errors[h])}}d=i[0];this.store.remove(d)},setAction:function(e,a){var d=this.getForm(),c,b;this.buttonReset.show();this.buttonAction.show();this.disableFields(false);this.currentAction=e;this.currentRecord=a;switch(e){case"create":this.hardReset();this.buttonAction.setText(this.textCreate);break;case"destroy":this.buttonAction.setText(this.textDestroy);d.loadRecord(a);break;case"duplicate":this.buttonAction.setText(this.textDuplicate);this.hardReset();c=App.getTableName(this.store);b=App.encodeField(c,"id");delete a.data[b];d.loadRecord(a);break;case"update":this.buttonAction.setText(this.textUpdate);d.loadRecord(a);break;case"view":this.buttonReset.hide();this.buttonAction.hide();d.loadRecord(a);this.disableFields(true);break}},updateRecord:function(b){var g,f,a=[],d,c,h,e;c=this.findByType("field");for(d=0;d<c.length;d+=1){f=c[d];if(f.getXType()!=="compositefield"){a.push(f)}}c=this.findByType("compositefield");for(d=0;d<c.length;d+=1){c[d].items.eachKey(function(j,i){a.push(i)})}for(d=0;d<a.length;d+=1){f=a[d];e=f.getValue();switch(f.getXType()){case"datefield":if(Ext.isDate(e)){e=e.format(f.format)}break;case"xcombobox":g=f;h=g.findRecord(g.valueField,g.getValue());b.set(g.displayField,h.get(g.displayField));break}b.set(f.getName(),e)}}});Ext.reg("xform",App.form.FormPanel);Ext.namespace("App.grid");App.grid.GridFilter=Ext.extend(Ext.form.FieldSet,{filterConditions:{},initialFilterConditions:[],pagingToolbar:null,store:null,defaults:{anchor:"99%",enableKeyEvents:true},initComponent:function(){var c,a,b;App.grid.GridFilter.superclass.initComponent.call(this);a=this.findByType("field");for(b=0;b<a.length;b+=1){c=a[b];if(c.xtype==="xcombobox"){c.on("select",this.onChange,this)}else{c.on("keyup",this.onChange,this,{buffer:500})}}},bind:function(b){var c,a;this.store=b.getStore();if(b.pagingInitialized){this.pagingToolbar=b.getBottomToolbar()}c=this.store.baseParams;for(a=0;a<c.where.length;a+=1){this.initialFilterConditions.push(c.where[a])}},onChange:function(a){this.setupCondition(a)},onReset:function(){var a,b;a=this.findByType("field");for(b=0;b<a.length;b+=1){a[b].reset()}this.filterConditions={};this.store.baseParams.where=this.initialFilterConditions;this.updateStore()},setupCondition:function(f){var e=[],c,a,d,b;d=f.getValue();b=f.name+" "+f.filterOperator+" '"+d+"'";if(d===""){delete this.filterConditions[f.name]}else{this.filterConditions[f.name]=b}for(c=0;c<this.initialFilterConditions.length;c+=1){e.push(this.initialFilterConditions[c])}for(a in this.filterConditions){if(this.filterConditions.hasOwnProperty(a)){e.push(this.filterConditions[a])}}this.store.baseParams.where=e;this.updateStore()},updateStore:function(){if(this.pagingToolbar){this.pagingToolbar.doRefresh()}else{this.store.load()}}});Ext.reg("xgridfilter",App.grid.GridFilter);Ext.namespace("App.grid");App.grid.Grid=Ext.extend(Ext.grid.GridPanel,{rowEditor:null,initComponent:function(){this.store=App.getDirectStore(this.store);this.bbar=new Ext.PagingToolbar();this.bbar.hide();App.grid.Grid.superclass.initComponent.call(this);if(!this.store.getTotalCount()){if(App.isPlugin(this,"pGridPaging")){this.store.load({params:{start:0,limit:10}})}else{this.store.load()}}}});Ext.reg("xgrid",App.grid.Grid);Ext.namespace("App.grid");App.grid.MathJax=Ext.extend(Object,{init:function(a){function b(d){var c=Ext.getDom(d.el);MathJax.Hub.Queue(["Typeset",MathJax.Hub,c])}a.getView().on("refresh",b,a);a.store.on("write",b,a)}});Ext.preg("pGridMathJax",App.grid.MathJax);Ext.namespace("App.grid");App.grid.Paging=Ext.extend(Object,{ptype:"pGridPaging",textExport:"Export",textSlider:"Rows per page",init:function(a){var b;b=a.getBottomToolbar();b.bindStore(a.store);b.add("-",this.textSlider,{xtype:"slider",plugins:new Ext.slider.Tip(),listeners:{changecomplete:this.onChangePageSize,scope:b},minValue:1,width:100},"->",{xtype:"xbuttondownload",text:this.textExport,url:App.csvUrl+"?tableName="+App.getTableName(a.store)});b.show();if(a.store.getTotalCount()>0){this.onInit.call(a,a.store)}else{a.store.on("load",this.onInit,a,{single:true})}a.store.on("write",this.onWrite,a)},onChangePageSize:function(b,c,a){var d=this;d.pageSize=c;d.moveFirst()},onInit:function(b,a,c){var g,e=this,d=b.getCount(),f;g=e.getBottomToolbar();g.pageSize=d;f=g.findByType("slider")[0];f.setMaxValue(b.getTotalCount());f.setValue(d)},onWrite:function(){var c,a=this,b;c=a.getBottomToolbar();c.pageSize=a.store.getCount();b=c.findByType("slider")[0];b.setMaxValue(a.store.getTotalCount());b.setValue(a.store.getCount())}});Ext.preg("pGridPaging",App.grid.Paging);Ext.namespace("App.grid");App.grid.RowEditorContextMenu=Ext.extend(Object,{ptype:"pGridRowEditorContextMenu",textAdd:"Add",textCreate:"Create",textDestroy:"Delete",textDuplicate:"Duplicate",textUpdate:"Update",textView:"View",init:function(a){var b=new Ext.menu.Menu();if(!a.rowEditor){throw new Error("no grid row editor !!!")}a.addListener("containercontextmenu",this.onContainerContextMenu,b);a.addListener("headercontextmenu",this.onHeaderContextMenu,b);a.addListener("rowcontextmenu",this.onRowContextMenu,b);b.add({text:this.textAdd,iconCls:"xaction-create",handler:a.rowEditor.onAddRow,scope:a.rowEditor},"-",{text:this.textDuplicate,iconCls:"xaction-duplicate",handler:a.rowEditor.onDuplicateRow,scope:a.rowEditor},{text:this.textUpdate,iconCls:"xaction-update",handler:a.rowEditor.onEditRow,scope:a.rowEditor},{text:this.textView,iconCls:"xaction-view",handler:a.rowEditor.onViewRow,scope:a.rowEditor},"-",{text:this.textDestroy,iconCls:"xaction-destroy",handler:a.rowEditor.onDeleteRow,scope:a.rowEditor})},onContainerContextMenu:function(a,b){var c=this;b.stopEvent();c.showAt(b.getXY())},onHeaderContextMenu:function(b,a,c){c.stopEvent()},onRowContextMenu:function(a,d,b){var c=this;b.stopEvent();a.selModel.selectRow(d);c.showAt(b.getXY())}});Ext.preg("pGridRowEditorContextMenu",App.grid.RowEditorContextMenu);Ext.namespace("App.grid");App.grid.RowEditor=Ext.extend(Ext.Window,{ptype:"pGridRowEditor",formPanel:null,grid:null,addTitle:"Create a new record...",deleteTitle:"Delete the record...",duplicateTitle:"Duplicate the record...",editTitle:"Update the record...",viewTitle:"View the record...",textMsg:"Select a row please",autoScroll:true,closeAction:"hide",constrainHeader:true,defaults:{autoScroll:true},modal:true,plain:true,init:function(a){var b;this.grid=a;this.grid.rowEditor=this;this.grid.selModel=new Ext.grid.RowSelectionModel({singleSelect:true});this.grid.store.on("write",this.onWrite,this);b=App.getTableName(this.grid.store);Dbui.getForm(b,this.addFormPanel,this)},addFormPanel:function(c,a){var b=a.result;this.formPanel=new App.form.FormPanel(b);this.add(this.formPanel);this.grid.store.on("exception",this.formPanel.onStoreException,this.formPanel)},getSelected:function(){var a=this.grid.getSelectionModel().getSelected();if(!a){Ext.MessageBox.alert("Warning",this.textMsg);return false}return a},onAddRow:function(){this.formPanel.setAction("create");this.setTitle(this.addTitle);this.show()},onDeleteRow:function(){var a=this.getSelected();if(!a){return}this.formPanel.setAction("destroy",a);this.setTitle(this.deleteTitle);this.formPanel.doAction()},onDuplicateRow:function(){var a=this.getSelected();if(!a){return}this.formPanel.setAction("duplicate",a);this.setTitle(this.duplicateTitle);this.show()},onEditRow:function(){var a=this.getSelected();if(!a){return}this.formPanel.setAction("update",a);this.setTitle(this.editTitle);this.show()},onViewRow:function(){var a=this.getSelected();if(!a){return}this.formPanel.setAction("view",a);this.setTitle(this.viewTitle);this.show()},onWrite:function(c,d,a,e,b){this.hide()}});Ext.preg("pGridRowEditor",App.grid.RowEditor);Ext.namespace("App.grid");App.grid.RowEditorToolbar=Ext.extend(Object,{ptype:"pGridRowEditorToolbar",init:function(a){var b;if(!a.rowEditor){throw new Error("no grid row editor !!!")}b=a.getTopToolbar();b.add([{text:"Add",iconCls:"silk-add",handler:a.rowEditor.onAddRow,scope:a.rowEditor}," ",{text:"Delete",iconCls:"silk-delete",handler:a.rowEditor.onDeleteRow,scope:a.rowEditor}," ",{text:"Duplicate",iconCls:"silk-clone",handler:a.rowEditor.onDuplicateRow,scope:a.rowEditor}," ",{text:"Update",iconCls:"silk-update",handler:a.rowEditor.onEditRow,scope:a.rowEditor}," ",{text:"View",iconCls:"silk-view",handler:a.rowEditor.onViewRow,scope:a.rowEditor},"-"])}});Ext.preg("pGridRowEditorToolbar",App.grid.RowEditorToolbar);Ext.namespace("App.grid");App.grid.GridWithFilter=Ext.extend(App.BasePanelWithSelector,{initComponent:function(){var b,a;this.items[1].collapsed=true;App.grid.GridWithFilter.superclass.initComponent.call(this);b=this.findByType("xgridfilter")[0];a=this.findByType("xgrid")[0];b.bind(a);this.goButton.hide();this.resetButton.on("click",b.onReset,b)}});Ext.reg("xgridwithfilter",App.grid.GridWithFilter);Ext.namespace("App.data");App.data.DirectStore=Ext.extend(Ext.data.DirectStore,{autoLoad:true,autoSave:true,constructor:function(c){var a,b;a=Ext.apply({},{encode:false,listful:true,writeAllFields:false},c);a=Ext.apply(a,{api:{create:Dbui.create,destroy:Dbui.destroy,read:Dbui.read,update:Dbui.update}});if(!Ext.isDefined(a.writer)){b=Ext.copyTo({},a,"encode, listful, writeAllFields");a.writer=new Ext.data.JsonWriter(b)}App.data.DirectStore.superclass.constructor.call(this,a);this.on("write",this.onWrite)},onWrite:function(a,b){switch(b){case"create":a.totalLength+=1;break;case"destroy":a.totalLength-=1;break}}});Ext.reg("xdirectstore",App.data.DirectStore);Ext.namespace("App.panel");App.panel.MathJax=Ext.extend(Object,{init:function(a){a.on("render",this.onPanelRender,this,{single:true})},onPanelRender:function(a){var b=a.body.getUpdater();b.on("update",this.onProcess)},onProcess:function(a,b){MathJax.Hub.PreProcess();MathJax.Hub.Process()}});Ext.preg("pPanelMathJax",App.panel.MathJax);Ext.namespace("App");App.PanelWithUrlSelector=Ext.extend(App.BasePanelWithSelector,{baseUrl:null,initComponent:function(){App.PanelWithUrlSelector.superclass.initComponent.call(this);this.goButton.on("click",this.onGo,this);this.resetButton.on("click",this.onReset,this)},onGo:function(){var b,d,c=this.getComponent("mainPanel"),e={},a=this.getComponent("selectorPanel");b=a.findByType("field");for(d=0;d<b.length;d+=1){e[b[d].getName()]=b[d].getValue()}c.load({url:this.baseUrl,params:e,text:"Loading...",timeout:30})},onReset:function(){var b,c,a=this.getComponent("selectorPanel");b=a.findByType("field");for(c=0;c<b.length;c+=1){b[c].reset()}}});Ext.reg("xpanelwithurlselector",App.PanelWithUrlSelector);Ext.namespace("App.form");App.form.SetBox=Ext.extend(Ext.form.ComboBox,{model:null,editable:false,emptyText:"Select...",selectOnFocus:true,triggerAction:"all",typeAhead:true,initComponent:function(){var b,a=[];if(!this.model){throw new Error("the property model is missing !!!")}a=[];for(b=0;b<this.model.setData.length;b+=1){a.push([this.model.setData[b]])}this.store=new Ext.data.ArrayStore({fields:[this.model.name],data:a});this.displayField=this.model.name;this.mode="local";App.form.SetBox.superclass.initComponent.call(this)}});Ext.reg("xsetbox",App.form.SetBox);Ext.namespace("App");App.Viewport=Ext.extend(Ext.Viewport,{tabPanel:null,treePanel:null,constructor:function(d){var e,b,c,f,a;Ext.apply(this,d);c=new Ext.tree.AsyncTreeNode({id:"root",nodeType:"async",expanded:true,text:App.name});b=new Ext.tree.TreeLoader({directFn:Dbui.getTree});cfg={layout:"border",title:"Ext Layout Browser",items:[{autoScroll:true,collapsible:true,itemId:"treePanel",loader:b,region:"west",root:c,rootVisible:false,split:true,title:App.name,width:200,xtype:"treepanel"},{autoScroll:true,defaults:{layout:"fit"},itemId:"tabPanel",region:"center",xtype:"tabpanel"}]};Ext.apply(this,cfg);App.Viewport.superclass.constructor.call(this);this.tabPanel=this.getComponent("tabPanel");this.treePanel=this.getComponent("treePanel");this.treePanel.on("click",this.onCreateTab,this);this.treePanel.on("contextmenu",function(h,g){g.stopEvent()})},onCreateTab:function(d,b){var f,h=d.parentNode,a,c,g=this,e=d.attributes.cfg,i=d.attributes.cfg.xtype;if(!d.isLeaf()){return}c=d.attributes.text+"/"+i;if(this.tabPanel.getComponent(c)){this.tabPanel.setActiveTab(c);return}f={closable:true,itemId:c,title:h.attributes.text+" "+d.attributes.text};if(i==="panel"){delete e.xtype;Ext.apply(f,e)}else{f.items=[d.attributes.cfg]}a=this.tabPanel.add(f);this.tabPanel.setActiveTab(c)}});
\ No newline at end of file
+Ext.namespace("App");App.version="0.4.4";App.encodeField=function(b,d){var a,c;a=b[0].toUpperCase()+b.slice(1,b.length);c=d[0].toUpperCase()+d.slice(1,d.length);return a+c};App.getDirectStore=function(b){var a,c,d;c=Ext.StoreMgr.lookup(b);if(!c&&!Ext.isString(b)){throw new Error('Fail to instanciate the store: "'+b+'"')}if(!c&&Ext.isString(b)){d=b.slice(0,b.search("Store"));a=App.storeCfgs[d];c=new App.data.DirectStore(a)}return c};App.getTableName=function(a){return a.baseParams.tableName};App.isPlugin=function(a,d){var b,c;if(!a.hasOwnProperty("plugins")){return false}for(b=0;b<a.plugins.length;b+=1){c=a.plugins[b];if(c===d){return true}if((typeof(c)==="object")&&c.hasOwnProperty("ptype")&&(c.ptype===d)){return true}}return false};Ext.namespace("App");App.BasePanelWithSelector=Ext.extend(Ext.Panel,{panelCfg:null,selectorCfg:null,textGo:"Go",textReset:"Reset",constructor:function(d){var c,b,a;Ext.apply(this,d);b=Ext.ComponentMgr.create(this.panelCfg);a=Ext.ComponentMgr.create(this.selectorCfg);c={layout:"border",items:[{border:false,layout:"fit",itemId:"mainPanel",items:[b],region:"center",},{buttons:[{ref:"../../goButton",text:this.textGo},{ref:"../../resetButton",text:this.textReset}],collapsible:true,defaults:{anchor:"99%"},frame:true,layout:"form",itemId:"selectorPanel",items:[a],region:"east",split:true,width:300,}]};Ext.apply(this,c);App.BasePanelWithSelector.superclass.constructor.call(this)}});Ext.reg("xpanelwithselector",App.BasePanelWithSelector);Ext.namespace("App");App.ButtonDownload=Ext.extend(Ext.Button,{url:undefined,initComponent:function(){App.ButtonDownload.superclass.initComponent.call(this);this.on("click",this.onDownload,this)},onDownload:function(a,c){try{Ext.destroy(Ext.get("downloadIframe"))}catch(b){}Ext.DomHelper.append(document.body,{tag:"iframe",id:"downloadIframe",frameBorder:0,width:0,height:0,css:"display:none;visibility:hidden;height:0px;",src:this.url})}});Ext.reg("xbuttondownload",App.ButtonDownload);Ext.namespace("App.form");App.form.ComboBox=Ext.extend(Ext.form.ComboBox,{mode:"remote",editable:false,selectOnFocus:true,triggerAction:"all",typeAhead:true,initComponent:function(){if(this.fieldLabel&&!this.emptyText){this.emptyText="Select a "+this.fieldLabel+" ..."}this.store=App.getDirectStore(this.store);App.form.ComboBox.superclass.initComponent.call(this);if(this.store.getCount()===0){this.store.load()}this.store.on("load",function(){this.setValue(this.initialConfig.value)},this)}});Ext.reg("xcombobox",App.form.ComboBox);Ext.namespace("App.form");App.form.FormPanel=Ext.extend(Ext.form.FormPanel,{store:null,autoScroll:true,bodyStyle:"padding:5px 5px 0",buttons:[{formBind:true,text:"Action",ref:"../buttonAction"},{text:"Reset",ref:"../buttonReset"}],defaults:{anchor:"100%"},defaultType:"textfield",frame:true,monitorValid:true,currentAction:null,currentRecord:null,textCreate:"Create",textDestroy:"Delete",textDuplicate:"Duplicate",textReset:"Reset",textUpdate:"Update",initComponent:function(){function a(){this.reset()}App.form.FormPanel.superclass.initComponent.call(this);this.buttonAction.on("click",this.doAction,this);this.buttonReset.on("click",a,this.getForm());this.addFieldToolTipsListeners();this.store=App.getDirectStore(this.store);this.store.on("exception",this.onStoreException,this);this.store.on("write",a,this.getForm());this.setAction("create");this.buttonReset.setText(this.textReset)},addFieldToolTipsListeners:function(){var b;function a(d){new Ext.ToolTip({target:d.getEl(),title:d.fieldLabel,anchor:"left",trackMouse:false,html:Ext.util.Format.htmlEncode(d.tipText)})}b=this.getForm();b.items.each(function(c){if(c.tipText){c.on("render",a)}})},disableFields:function(a){var b=this.getForm();b.items.each(function(c){c.setDisabled(a)})},doAction:function(){var b=this.getForm(),a;if(!b.isValid()){return}if(!this.store){throw new Error("the store is undefined !!!")}switch(this.currentAction){case"create":a=new this.store.recordType();this.updateRecord(a);this.store.add(a);break;case"destroy":this.store.remove(this.currentRecord);break;case"duplicate":a=new this.store.recordType();this.updateRecord(a);this.store.add(a);break;case"update":this.currentRecord.beginEdit();this.updateRecord(this.currentRecord);this.currentRecord.endEdit();break}if(this.store.autoSave===false){this.store.save()}},hardReset:function(){var a=this.getForm();a.items.each(function(b){b.originalValue=Ext.value(b.initialConfig.value,"");b.setValue(b.originalValue)})},onStoreException:function(e,f,b,j,c,i){var g,h,a=this.getForm(),d;for(h in c.errors){if(c.errors.hasOwnProperty(h)){g=a.findField(h);g.markInvalid(c.errors[h])}}d=i[0];this.store.remove(d)},setAction:function(e,a){var d=this.getForm(),c,b;this.buttonReset.show();this.buttonAction.show();this.disableFields(false);this.currentAction=e;this.currentRecord=a;switch(e){case"create":this.hardReset();this.buttonAction.setText(this.textCreate);break;case"destroy":this.buttonAction.setText(this.textDestroy);d.loadRecord(a);break;case"duplicate":this.buttonAction.setText(this.textDuplicate);this.hardReset();c=App.getTableName(this.store);b=App.encodeField(c,"id");delete a.data[b];d.loadRecord(a);break;case"update":this.buttonAction.setText(this.textUpdate);d.loadRecord(a);break;case"view":this.buttonReset.hide();this.buttonAction.hide();d.loadRecord(a);this.disableFields(true);break}},updateRecord:function(b){var g,f,a=[],d,c,h,e;c=this.findByType("field");for(d=0;d<c.length;d+=1){f=c[d];if(f.getXType()!=="compositefield"){a.push(f)}}c=this.findByType("compositefield");for(d=0;d<c.length;d+=1){c[d].items.eachKey(function(j,i){a.push(i)})}for(d=0;d<a.length;d+=1){f=a[d];e=f.getValue();switch(f.getXType()){case"datefield":if(Ext.isDate(e)){e=e.format(f.format)}break;case"xcombobox":g=f;h=g.findRecord(g.valueField,g.getValue());b.set(g.displayField,h.get(g.displayField));break}b.set(f.getName(),e)}}});Ext.reg("xform",App.form.FormPanel);Ext.namespace("App.grid");App.grid.GridFilter=Ext.extend(Ext.form.FieldSet,{filterConditions:{},initialFilterConditions:[],pagingToolbar:null,store:null,defaults:{anchor:"99%",enableKeyEvents:true},initComponent:function(){var c,a,b;App.grid.GridFilter.superclass.initComponent.call(this);a=this.findByType("field");for(b=0;b<a.length;b+=1){c=a[b];if(c.xtype==="xcombobox"){c.on("select",this.onChange,this)}else{c.on("keyup",this.onChange,this,{buffer:500})}}},bind:function(b){var c,a;this.store=b.getStore();if(b.pagingInitialized){this.pagingToolbar=b.getBottomToolbar()}c=this.store.baseParams;for(a=0;a<c.where.length;a+=1){this.initialFilterConditions.push(c.where[a])}},onChange:function(a){this.setupCondition(a)},onReset:function(){var a,b;a=this.findByType("field");for(b=0;b<a.length;b+=1){a[b].reset()}this.filterConditions={};this.store.baseParams.where=this.initialFilterConditions;this.updateStore()},setupCondition:function(f){var e=[],c,a,d,b;d=f.getValue();b=f.name+" "+f.filterOperator+" '"+d+"'";if(d===""){delete this.filterConditions[f.name]}else{this.filterConditions[f.name]=b}for(c=0;c<this.initialFilterConditions.length;c+=1){e.push(this.initialFilterConditions[c])}for(a in this.filterConditions){if(this.filterConditions.hasOwnProperty(a)){e.push(this.filterConditions[a])}}this.store.baseParams.where=e;this.updateStore()},updateStore:function(){if(this.pagingToolbar){this.pagingToolbar.doRefresh()}else{this.store.load()}}});Ext.reg("xgridfilter",App.grid.GridFilter);Ext.namespace("App.grid");App.grid.Grid=Ext.extend(Ext.grid.GridPanel,{rowEditor:null,initComponent:function(){this.store=App.getDirectStore(this.store);this.bbar=new Ext.PagingToolbar();this.bbar.hide();App.grid.Grid.superclass.initComponent.call(this);if(!this.store.getTotalCount()){if(App.isPlugin(this,"pGridPaging")){this.store.load({params:{start:0,limit:10}})}else{this.store.load()}}}});Ext.reg("xgrid",App.grid.Grid);Ext.namespace("App.grid");App.grid.MathJax=Ext.extend(Object,{init:function(a){function b(d){var c=Ext.getDom(d.el);MathJax.Hub.Queue(["Typeset",MathJax.Hub,c])}a.getView().on("refresh",b,a);a.store.on("write",b,a)}});Ext.preg("pGridMathJax",App.grid.MathJax);Ext.namespace("App.grid");App.grid.Paging=Ext.extend(Object,{ptype:"pGridPaging",textExport:"Export",textSlider:"Rows per page",init:function(a){var b;b=a.getBottomToolbar();b.bindStore(a.store);b.add("-",this.textSlider,{xtype:"slider",plugins:new Ext.slider.Tip(),listeners:{changecomplete:this.onChangePageSize,scope:b},minValue:1,width:100},"->",{xtype:"xbuttondownload",text:this.textExport,url:App.csvUrl+"?tableName="+App.getTableName(a.store)});b.show();if(a.store.getTotalCount()>0){this.onInit.call(a,a.store)}else{a.store.on("load",this.onInit,a,{single:true})}a.store.on("write",this.onWrite,a)},onChangePageSize:function(b,c,a){var d=this;d.pageSize=c;d.moveFirst()},onInit:function(b,a,c){var g,e=this,d=b.getCount(),f;g=e.getBottomToolbar();g.pageSize=d;f=g.findByType("slider")[0];f.setMaxValue(b.getTotalCount());f.setValue(d)},onWrite:function(){var c,a=this,b;c=a.getBottomToolbar();c.pageSize=a.store.getCount();b=c.findByType("slider")[0];b.setMaxValue(a.store.getTotalCount());b.setValue(a.store.getCount())}});Ext.preg("pGridPaging",App.grid.Paging);Ext.namespace("App.grid");App.grid.RowEditorContextMenu=Ext.extend(Object,{ptype:"pGridRowEditorContextMenu",textAdd:"Add",textCreate:"Create",textDestroy:"Delete",textDuplicate:"Duplicate",textUpdate:"Update",textView:"View",init:function(a){var b=new Ext.menu.Menu();if(!a.rowEditor){throw new Error("no grid row editor !!!")}a.addListener("containercontextmenu",this.onContainerContextMenu,b);a.addListener("headercontextmenu",this.onHeaderContextMenu,b);a.addListener("rowcontextmenu",this.onRowContextMenu,b);b.add({text:this.textAdd,iconCls:"xaction-create",handler:a.rowEditor.onAddRow,scope:a.rowEditor},"-",{text:this.textDuplicate,iconCls:"xaction-duplicate",handler:a.rowEditor.onDuplicateRow,scope:a.rowEditor},{text:this.textUpdate,iconCls:"xaction-update",handler:a.rowEditor.onEditRow,scope:a.rowEditor},{text:this.textView,iconCls:"xaction-view",handler:a.rowEditor.onViewRow,scope:a.rowEditor},"-",{text:this.textDestroy,iconCls:"xaction-destroy",handler:a.rowEditor.onDeleteRow,scope:a.rowEditor})},onContainerContextMenu:function(a,b){var c=this;b.stopEvent();c.showAt(b.getXY())},onHeaderContextMenu:function(b,a,c){c.stopEvent()},onRowContextMenu:function(a,d,b){var c=this;b.stopEvent();a.selModel.selectRow(d);c.showAt(b.getXY())}});Ext.preg("pGridRowEditorContextMenu",App.grid.RowEditorContextMenu);Ext.namespace("App.grid");App.grid.RowEditor=Ext.extend(Ext.Window,{ptype:"pGridRowEditor",formPanel:null,grid:null,addTitle:"Create a new record...",deleteTitle:"Delete the record...",duplicateTitle:"Duplicate the record...",editTitle:"Update the record...",viewTitle:"View the record...",textMsg:"Select a row please",autoScroll:true,closeAction:"hide",constrainHeader:true,defaults:{autoScroll:true},modal:true,plain:true,init:function(a){var b;this.grid=a;this.grid.rowEditor=this;this.grid.selModel=new Ext.grid.RowSelectionModel({singleSelect:true});this.grid.store.on("write",this.onWrite,this);b=App.getTableName(this.grid.store);Dbui.getForm(b,this.addFormPanel,this)},addFormPanel:function(c,a){var b=a.result;this.formPanel=new App.form.FormPanel(b);this.add(this.formPanel);this.grid.store.on("exception",this.formPanel.onStoreException,this.formPanel)},getSelected:function(){var a=this.grid.getSelectionModel().getSelected();if(!a){Ext.MessageBox.alert("Warning",this.textMsg);return false}return a},onAddRow:function(){this.formPanel.setAction("create");this.setTitle(this.addTitle);this.show()},onDeleteRow:function(){var a=this.getSelected();if(!a){return}this.formPanel.setAction("destroy",a);this.setTitle(this.deleteTitle);this.formPanel.doAction()},onDuplicateRow:function(){var a=this.getSelected();if(!a){return}this.formPanel.setAction("duplicate",a);this.setTitle(this.duplicateTitle);this.show()},onEditRow:function(){var a=this.getSelected();if(!a){return}this.formPanel.setAction("update",a);this.setTitle(this.editTitle);this.show()},onViewRow:function(){var a=this.getSelected();if(!a){return}this.formPanel.setAction("view",a);this.setTitle(this.viewTitle);this.show()},onWrite:function(c,d,a,e,b){this.hide()}});Ext.preg("pGridRowEditor",App.grid.RowEditor);Ext.namespace("App.grid");App.grid.RowEditorToolbar=Ext.extend(Object,{ptype:"pGridRowEditorToolbar",init:function(a){var b;if(!a.rowEditor){throw new Error("no grid row editor !!!")}b=a.getTopToolbar();b.add([{text:"Add",iconCls:"silk-add",handler:a.rowEditor.onAddRow,scope:a.rowEditor}," ",{text:"Delete",iconCls:"silk-delete",handler:a.rowEditor.onDeleteRow,scope:a.rowEditor}," ",{text:"Duplicate",iconCls:"silk-clone",handler:a.rowEditor.onDuplicateRow,scope:a.rowEditor}," ",{text:"Update",iconCls:"silk-update",handler:a.rowEditor.onEditRow,scope:a.rowEditor}," ",{text:"View",iconCls:"silk-view",handler:a.rowEditor.onViewRow,scope:a.rowEditor},"-"])}});Ext.preg("pGridRowEditorToolbar",App.grid.RowEditorToolbar);Ext.namespace("App.grid");App.grid.GridWithFilter=Ext.extend(App.BasePanelWithSelector,{initComponent:function(){var b,a;this.items[1].collapsed=true;App.grid.GridWithFilter.superclass.initComponent.call(this);b=this.findByType("xgridfilter")[0];a=this.findByType("xgrid")[0];b.bind(a);this.goButton.hide();this.resetButton.on("click",b.onReset,b)}});Ext.reg("xgridwithfilter",App.grid.GridWithFilter);Ext.namespace("App.data");App.data.DirectStore=Ext.extend(Ext.data.DirectStore,{autoLoad:true,autoSave:true,constructor:function(c){var a,b;a=Ext.apply({},{encode:false,listful:true,writeAllFields:false},c);a=Ext.apply(a,{api:{create:Dbui.create,destroy:Dbui.destroy,read:Dbui.read,update:Dbui.update}});if(!Ext.isDefined(a.writer)){b=Ext.copyTo({},a,"encode, listful, writeAllFields");a.writer=new Ext.data.JsonWriter(b)}App.data.DirectStore.superclass.constructor.call(this,a);this.on("write",this.onWrite)},onWrite:function(a,b){switch(b){case"create":a.totalLength+=1;break;case"destroy":a.totalLength-=1;break}}});Ext.reg("xdirectstore",App.data.DirectStore);Ext.namespace("App.panel");App.panel.MathJax=Ext.extend(Object,{init:function(a){a.on("render",this.onPanelRender,this,{single:true})},onPanelRender:function(a){var b=a.body.getUpdater();b.on("update",this.onProcess)},onProcess:function(a,b){MathJax.Hub.PreProcess();MathJax.Hub.Process()}});Ext.preg("pPanelMathJax",App.panel.MathJax);Ext.namespace("App");App.PanelWithUrlSelector=Ext.extend(App.BasePanelWithSelector,{baseUrl:null,ctrlField:null,textLoad:"Loading...",initComponent:function(){App.PanelWithUrlSelector.superclass.initComponent.call(this);this.goButton.on("click",this.onGo,this);this.resetButton.on("click",this.onReset,this)},onGo:function(){var b,e,c=this.getComponent("mainPanel"),f={},a=this.getComponent("selectorPanel"),d=this.baseUrl;b=a.findByType("field");for(e=0;e<b.length;e+=1){if(b[e].getName()===this.ctrlField){d=d+"/"+b[e].getValue()}else{f[b[e].getName()]=b[e].getValue()}}c.load({url:d,params:f,text:this.textLoad,timeout:30})},onReset:function(){var b,c,a=this.getComponent("selectorPanel");b=a.findByType("field");for(c=0;c<b.length;c+=1){b[c].reset()}}});Ext.reg("xpanelwithurlselector",App.PanelWithUrlSelector);Ext.namespace("App.form");App.form.SetBox=Ext.extend(Ext.form.ComboBox,{model:null,editable:false,emptyText:"Select...",selectOnFocus:true,triggerAction:"all",typeAhead:true,initComponent:function(){var b,a=[];if(!this.model){throw new Error("the property model is missing !!!")}a=[];for(b=0;b<this.model.setData.length;b+=1){a.push([this.model.setData[b]])}this.store=new Ext.data.ArrayStore({fields:[this.model.name],data:a});this.displayField=this.model.name;this.mode="local";App.form.SetBox.superclass.initComponent.call(this)}});Ext.reg("xsetbox",App.form.SetBox);Ext.namespace("App");App.Viewport=Ext.extend(Ext.Viewport,{tabPanel:null,treePanel:null,constructor:function(d){var e,b,c,f,a;Ext.apply(this,d);c=new Ext.tree.AsyncTreeNode({id:"root",nodeType:"async",expanded:true,text:App.name});b=new Ext.tree.TreeLoader({directFn:Dbui.getTree});cfg={layout:"border",title:"Ext Layout Browser",items:[{autoScroll:true,collapsible:true,itemId:"treePanel",loader:b,region:"west",root:c,rootVisible:false,split:true,title:App.name,width:200,xtype:"treepanel"},{autoScroll:true,defaults:{layout:"fit"},itemId:"tabPanel",region:"center",xtype:"tabpanel"}]};Ext.apply(this,cfg);App.Viewport.superclass.constructor.call(this);this.tabPanel=this.getComponent("tabPanel");this.treePanel=this.getComponent("treePanel");this.treePanel.on("click",this.onCreateTab,this);this.treePanel.on("contextmenu",function(h,g){g.stopEvent()})},onCreateTab:function(d,b){var f,h=d.parentNode,a,c,g=this,e=d.attributes.cfg,i=d.attributes.cfg.xtype;if(!d.isLeaf()){return}c=d.attributes.text+"/"+i;if(this.tabPanel.getComponent(c)){this.tabPanel.setActiveTab(c);return}f={closable:true,itemId:c,title:h.attributes.text+" "+d.attributes.text};if(i==="panel"){delete e.xtype;Ext.apply(f,e)}else{f.items=[d.attributes.cfg]}a=this.tabPanel.add(f);this.tabPanel.setActiveTab(c)}});
\ No newline at end of file
diff --git a/static/plugin_dbui/locale/app-lang-fr.js b/static/plugin_dbui/locale/app-lang-fr.js
index 9b820a97579f6f17449d78962dde1bb18e4a9f99..8927e2a5514a8c70341fda5e029dce00bbea6bab 100644
--- a/static/plugin_dbui/locale/app-lang-fr.js
+++ b/static/plugin_dbui/locale/app-lang-fr.js
@@ -4,6 +4,13 @@
  *
  */
 
+if (App.BasePanelWithSelector) {
+    Ext.apply(App.BasePanelWithSelector.prototype, {
+        textGo: 'Go',
+        textReset: 'Annuler',
+    });
+}
+
 if (App.form.FormPanel) {
     Ext.apply(App.form.FormPanel.prototype, {
         textCreate      : 'Créer',
@@ -49,9 +56,8 @@ if (App.grid.RowEditorContextMenu) {
     });
 }
 
-if (App.panel.PanelWithSelector) {
-    Ext.apply(App.panel.PanelWithSelector.prototype, {
-        textGo: 'Go',
-        textReset: 'Annuler',
+if (App.PanelWithUrlSelector) {
+    Ext.apply(App.PanelWithUrlSelector.prototype, {
+        textLoad: 'chargement en cours...',
     });
 }
diff --git a/static/plugin_dbui/src/appbase.js b/static/plugin_dbui/src/appbase.js
index a7368e40e643243b1162473fc45f561198e8b243..2d1fd7bc0301dcd7866f73c7aae237b883e7a796 100644
--- a/static/plugin_dbui/src/appbase.js
+++ b/static/plugin_dbui/src/appbase.js
@@ -22,7 +22,7 @@ Ext.namespace('App');
 /**
  * @param {String} App.version version of the library
  */
-App.version = '0.4.3';
+App.version = '0.4.4';
 
 /**
  * Helper function mimicking the encode_field function running on the server
diff --git a/static/plugin_dbui/src/apppanelwithurlselector.js b/static/plugin_dbui/src/apppanelwithurlselector.js
index b643818558da774f2b2717db254e1e97cf7ed85e..3882cebcc64d6255d8420fe898279d18b3a03bc8 100644
--- a/static/plugin_dbui/src/apppanelwithurlselector.js
+++ b/static/plugin_dbui/src/apppanelwithurlselector.js
@@ -3,7 +3,11 @@
  * the selector allow to setup the url parameters and to launch the
  * request to the server.
  * 
- *  The type of this component is xpanelwithurlselector.
+ * The url is build as baseUrl or baseUrl/CtrlFieldValue if ctrlField is defined.
+ * The value of the other field are pass as Field1=Field1Value ,Field2=Field2Value
+ * in a POST transfert
+ *
+ * The type of this component is xpanelwithurlselector.
  *  
  * @extend: App.PanelWithSelector
  * 
@@ -13,10 +17,21 @@ Ext.namespace('App');
 App.PanelWithUrlSelector = Ext.extend(App.BasePanelWithSelector, {
     
     /**
-     * @param {String}
+     * @param {String} baseurl well form url, i.e http://blabla
      */
     baseUrl: null,
     
+    /**
+     * @param {String} ctrFiedl  name of the field defining the controller
+     * When define the url become http://blabla/ctrlFieldValue
+     */
+    ctrlField: null,
+    
+    /**
+     * Private attributes for internationalization
+     */
+    textLoad: 'Loading...',
+    
     /**
      * Require by the ExtJS model
      */    
@@ -38,17 +53,22 @@ App.PanelWithUrlSelector = Ext.extend(App.BasePanelWithSelector, {
             i,
             panel = this.getComponent('mainPanel'),
             params = {},
-            selector = this.getComponent('selectorPanel');
+            selector = this.getComponent('selectorPanel'),
+            url = this.baseUrl;
             
         fields = selector.findByType('field');
         for (i = 0; i < fields.length; i += 1) {
-            params[fields[i].getName()] = fields[i].getValue();
+            if(fields[i].getName() === this.ctrlField) {
+                url = url + '/' +  fields[i].getValue();
+            } else {
+                params[fields[i].getName()] = fields[i].getValue();    
+            }
         }
 
         panel.load({
-            url: this.baseUrl,
+            url: url,
             params: params,
-            text: 'Loading...',
+            text: this.textLoad,
             timeout: 30 
         });        
     },