PDA

View Full Version : Ext.ux.grid.Search



tobiu
6 Jun 2009, 4:16 PM
hi together,

i made some minor fixes about the position of this ux inside the toolbar, to make it work with ext3.0. without these, the item appears on the right end of the toolbar. changes marked red.

original topic:http://extjs.com/forum/showthread.php?t=23615

note: this is not the latest version of the 2.x plugin!

@saki: feel free to implement these changes, if you are porting the latest version to 3.0.


kind regards, tobiu



/**
* Search plugin for Ext.grid.GridPanel, Ext.grid.EditorGrid ver. 2.x or subclasses of them
*
* @author Ing. Jozef Sakalos
* @copyright (c) 2008, by Ing. Jozef Sakalos
* @date 17. January 2008
* @version $Id: Ext.ux.grid.Search.js 728 2008-02-19 01:56:32Z jozo $
*
* @license Ext.ux.grid DragSelector is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/

Ext.namespace('Ext.ux', 'Ext.ux.grid');

/**
* @class Ext.ux.grid.Search
* @extends Ext.util.Observable
* @param {Object} config configuration object
* @constructor
*/
Ext.ux.grid.Search = function(config) {
Ext.apply(this, config);
Ext.ux.grid.Search.superclass.constructor.call(this);
}; // eo constructor

Ext.extend(Ext.ux.grid.Search, Ext.util.Observable, {
/**
* @cfg {String} searchText Text to display on menu button
*/
searchText:'Search'
/**
* @cfg {String} searchTipText Text to display as input tooltip. Set to '' for no tooltip
*/
,searchTipText:'Type a text to search and press Enter'
/**
* @cfg {String} selectAllText Text to display on menu item that selects all fields
*/
,selectAllText:'Select All'
/**
* @cfg {String} position Where to display the search controls. Valid values are top and bottom (defaults to bottom)
* Corresponding toolbar has to exist at least with mimimum configuration tbar:[] for position:top or bbar:[]
* for position bottom. Plugin does NOT create any toolbar.
*/
,position:'bottom'
/**
* @cfg {String} iconCls Icon class for menu button (defaults to icon-magnifier)
*/
,iconCls:'icon-magnifier'
/**
* @cfg {String/Array} checkIndexes Which indexes to check by default. Can be either 'all' for all indexes
* or array of dataIndex names, e.g. ['persFirstName', 'persLastName']
*/
,checkIndexes:'all'
/**
* @cfg {Array} disableIndexes Array of index names to disable (not show in the menu), e.g. ['persTitle', 'persTitle2']
*/
,disableIndexes:[]

/**
* @cfg {String} dateFormat how to format date values. If undefined (the default)
* date is formatted as configured in colummn model
*/
,dateFormat:undefined
/**
* @cfg {Boolean} showSelectAll Select All item is shown in menu if true (defaults to true)
*/
,showSelectAll:true
/**
* @cfg {String} mode Use 'remote' for remote stores or 'local' for local stores. If mode is local
* no data requests are sent to server the grid's store is filtered instead (defaults to 'remote')
*/
,mode:'remote'
/**
* @cfg {Number} width Width of input field in pixels (defaults to 100)
*/
,width:100
/**
* @cfg {String} xtype xtype is usually not used to instantiate this plugin but you have a chance to identify it
*/
,xtype:'gridsearch'
/**
* @cfg {Object} paramNames Params name map (defaults to {fields:'fields', query:'query'}
*/
,paramNames: {
fields:'fields'
,query:'query'
}
/**
* @cfg {int} position
* The starting position inside the toolbar
*/
,tbPosition: 15
/**
* @cfg {String} align 'left' or 'right' (defaults to 'left')
*/
/**
* @cfg {Number} minLength force user to type this many character before he can make a search
*/

// {{{
/**
* private
* @param {Ext.grid.GridPanel/Ext.grid.EditorGrid} grid reference to grid this plugin is used for
*/
,init:function(grid) {
this.grid = grid;

// do our processing after grid render and reconfigure
grid.onRender = grid.onRender.createSequence(this.onRender, this);
grid.reconfigure = grid.reconfigure.createSequence(this.reconfigure, this);
} // eo function init
// }}}
// {{{
/**
* private add plugin controls to <b>existing</b> toolbar and calls reconfigure
*/
,onRender:function() {
var grid = this.grid;
var tb = 'bottom' == this.position ? grid.bottomToolbar : grid.topToolbar;

// add menu
this.menu = new Ext.menu.Menu();

// handle position
if('right' === this.align) {
tb.insert(this.tbPosition, '->');
}
else {
tb.insert(this.tbPosition, '-');
}
this.tbPosition++;

// add menu button
tb.insert(this.tbPosition, {
text:this.searchText
,menu:this.menu
,iconCls:this.iconCls
});
this.tbPosition++;

// add input field (TwinTriggerField in fact)
this.field = new Ext.form.TwinTriggerField({
width:this.width
,selectOnFocus:undefined === this.selectOnFocus ? true : this.selectOnFocus
,trigger1Class:'x-form-clear-trigger'
,trigger2Class:'x-form-search-trigger'
,onTrigger1Click:this.onTriggerClear.createDelegate(this)
,onTrigger2Click:this.onTriggerSearch.createDelegate(this)
,minLength:this.minLength
});

// install event handlers on input field
this.field.on('render', function() {
this.field.el.dom.qtip = this.searchTipText;

// install key map
var map = new Ext.KeyMap(this.field.el, [{
key:Ext.EventObject.ENTER
,scope:this
,fn:this.onTriggerSearch
},{
key:Ext.EventObject.ESC
,scope:this
,fn:this.onTriggerClear
}]);
map.stopEvent = true;
}, this, {single:true});

tb.insert(this.tbPosition, this.field);

// reconfigure
this.reconfigure();
} // eo function onRender
// }}}
// {{{
/**
* private Clear Trigger click handler
*/
,onTriggerClear:function() {
this.field.setValue('');
this.field.focus();
this.onTriggerSearch();
} // eo function onTriggerClear
// }}}
// {{{
/**
* private Search Trigger click handler (executes the search, local or remote)
*/
,onTriggerSearch:function() {
if(!this.field.isValid()) {
return;
}
var val = this.field.getValue();
var store = this.grid.store;

// grid's store filter
if('local' === this.mode) {
store.clearFilter();
if(val) {
store.filterBy(function(r) {
var retval = false;
this.menu.items.each(function(item) {
if(!item.checked || retval) {
return;
}
var rv = r.get(item.dataIndex);
rv = rv instanceof Date ? rv.format(this.dateFormat || r.fields.get(item.dataIndex).dateFormat) : rv;
var re = new RegExp(val, 'gi');
retval = re.test(rv);
}, this);
if(retval) {
return true;
}
return retval;
}, this);
}
else {
}
}
// ask server to filter records
else {
// clear start (necessary if we have paging)
if(store.lastOptions && store.lastOptions.params) {
store.lastOptions.params[store.paramNames.start] = 0;
}

// get fields to search array
var fields = [];
this.menu.items.each(function(item) {
if(item.checked) {
fields.push(item.dataIndex);
}
});

// add fields and query to baseParams of store
delete(store.baseParams[this.paramNames.fields]);
delete(store.baseParams[this.paramNames.query]);
if (store.lastOptions && store.lastOptions.params) {
delete(store.lastOptions.params[this.paramNames.fields]);
delete(store.lastOptions.params[this.paramNames.query]);
}
if(fields.length) {
store.baseParams[this.paramNames.fields] = Ext.encode(fields);
store.baseParams[this.paramNames.query] = val;
}

// reload store
store.reload();
}

} // eo function onTriggerSearch
// }}}
// {{{
/**
* @param {Boolean} true to disable search (TwinTriggerField), false to enable
*/
,setDisabled:function() {
this.field.setDisabled.apply(this.field, arguments);
} // eo function setDisabled
// }}}
// {{{
/**
* Enable search (TwinTriggerField)
*/
,enable:function() {
this.setDisabled(false);
} // eo function enable
// }}}
// {{{
/**
* Enable search (TwinTriggerField)
*/
,disable:function() {
this.setDisabled(true);
} // eo function disable
// }}}
// {{{
/**
* private (re)configures the plugin, creates menu items from column model
*/
,reconfigure:function() {

// {{{
// remove old items
var menu = this.menu;
menu.removeAll();

// add Select All item plus separator
if(this.showSelectAll) {
menu.add(new Ext.menu.CheckItem({
text:this.selectAllText
,checked:!(this.checkIndexes instanceof Array)
,hideOnClick:false
,handler:function(item) {
var checked = ! item.checked;
item.parentMenu.items.each(function(i) {
if(item !== i && i.setChecked) {
i.setChecked(checked);
}
});
}
}),'-');
}

// }}}
// {{{
// add new items
var cm = this.grid.colModel;
Ext.each(cm.config, function(config) {
var disable = false;
if(config.header && config.dataIndex) {
Ext.each(this.disableIndexes, function(item) {
disable = disable ? disable : item === config.dataIndex;
});
if(!disable) {
menu.add(new Ext.menu.CheckItem({
text:config.header
,hideOnClick:false
,checked:'all' === this.checkIndexes
,dataIndex:config.dataIndex
}));
}
}
}, this);
// }}}
// {{{
// check items
if(this.checkIndexes instanceof Array) {
Ext.each(this.checkIndexes, function(di) {
var item = menu.items.find(function(itm) {
return itm.dataIndex === di;
});
if(item) {
item.setChecked(true, true);
}
}, this);
}
// }}}

} // eo function reconfigure
// }}}

}); // eo extend

// eof

828
19 Jun 2009, 3:21 AM
You are not getting the error: 'tip has no properties' with the plugin in Ext 3.x?

tobiu
21 Jun 2009, 8:05 AM
hi 828,

nope, never got that error.
i have only tested this ux with firefox 3.0.11 though.

since your error includes "tip", make sure you are using


Ext.QuickTips.init();


and check your app for ext2.x ux and overrides, that can cause troubel with the 3.0-version.

kind regards, tobiu

828
22 Jun 2009, 5:30 AM
tobiu,

Thank you very much - that was the issue.
Ext.QuickTips.init();

mpelzsherman
23 Jun 2009, 11:27 AM
Hi -

I tried these changes but they aren't working for me in Firefox 3.0.11.

The search field still doesn't show up.

http://twitpic.com/87i1c

tobiu
24 Jun 2009, 12:27 AM
you do have the "search"-text of the field at the right edge of your bbar and then the overflow-button ">>" that indicates, your toolbar is too small.

if you would like to have the searchfield left to the "display accounds" - text, try playing with the new config



tbPosition: 15


like putting it to 11 or so.

kind regards, tobiu

talha06
4 Mar 2010, 11:49 AM
I want to learn that how can I add a search icon next to the search text. I didn't see a property so set 'icon'. How can I manage iconCls? Can someone help me?

Thanx in advance..

tobiu
4 Mar 2010, 12:51 PM
hi talha06,

i don't understand the problem. you have an iconCls-config for that.
just define which css you want and define it like:



.icon-magnifier{
background-image:url(../images/icons/magnifier.png) !important;
}



kind regards,
tobiu

talha06
4 Mar 2010, 3:34 PM
hi talha06,

i don't understand the problem. you have an iconCls-config for that.
just define which css you want and define it like:



.icon-magnifier{
background-image:url(../images/icons/magnifier.png) !important;
}
kind regards,
tobiuHi Tobiu,
thank you so much, this is exactly what I wanted to learn.. Now I can see image next to the the 'Search' button..
Thanx again,
With regards,
Talha

javaman
5 Mar 2010, 11:51 PM
very good

I added the minChars config to add a keyUp event, code above ( I just copied of the original plugin)
I tested on ext 3.1.0 and got no error



/**
* Search plugin for Ext.grid.GridPanel, Ext.grid.EditorGrid ver. 2.x or subclasses of them
*
* @author Ing. Jozef Sakalos
* @copyright (c) 2008, by Ing. Jozef Sakalos
* @date 17. January 2008
* @version $Id: Ext.ux.grid.Search.js 728 2008-02-19 01:56:32Z jozo $
*
* @license Ext.ux.grid DragSelector is licensed under the terms of
* the Open Source LGPL 3.0 license. Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
* License details: http://www.gnu.org/licenses/lgpl.html
*/

Ext.namespace('Ext.ux', 'Ext.ux.grid');

/**
* @class Ext.ux.grid.Search
* @extends Ext.util.Observable
* @param {Object} config configuration object
* @constructor
*/
Ext.ux.grid.Search = function(config) {
Ext.apply(this, config);
Ext.ux.grid.Search.superclass.constructor.call(this);
}; // eo constructor

Ext.extend(Ext.ux.grid.Search, Ext.util.Observable, {
/**
* @cfg {String} searchText Text to display on menu button
*/
searchText:'Search'
/**
* @cfg {String} searchTipText Text to display as input tooltip. Set to '' for no tooltip
*/
,searchTipText:'Type a text to search and press Enter'
/**
* @cfg {String} selectAllText Text to display on menu item that selects all fields
*/
,selectAllText:'Select All'
/**
* @cfg {String} position Where to display the search controls. Valid values are top and bottom (defaults to bottom)
* Corresponding toolbar has to exist at least with mimimum configuration tbar:[] for position:top or bbar:[]
* for position bottom. Plugin does NOT create any toolbar.
*/
,position:'bottom'
/**
* @cfg {String} iconCls Icon class for menu button (defaults to icon-magnifier)
*/
,iconCls:'icon-magnifier'
/**
* @cfg {String/Array} checkIndexes Which indexes to check by default. Can be either 'all' for all indexes
* or array of dataIndex names, e.g. ['persFirstName', 'persLastName']
*/
,checkIndexes:'all'
/**
* @cfg {Array} disableIndexes Array of index names to disable (not show in the menu), e.g. ['persTitle', 'persTitle2']
*/
,disableIndexes:[]

/**
* @cfg {Number} minChars Minimum characters to type before the request is made. If undefined (the default)
* the trigger field shows magnifier icon and you need to click it or press enter for search to start. If it
* is defined and greater than 0 then maginfier is not shown and search starts after minChars are typed.
* (defaults to undefined)
*/

/**
* @cfg {String} dateFormat how to format date values. If undefined (the default)
* date is formatted as configured in colummn model
*/
,dateFormat:undefined
/**
* @cfg {Boolean} showSelectAll Select All item is shown in menu if true (defaults to true)
*/
,showSelectAll:true
/**
* @cfg {String} mode Use 'remote' for remote stores or 'local' for local stores. If mode is local
* no data requests are sent to server the grid's store is filtered instead (defaults to 'remote')
*/
,mode:'remote'
/**
* @cfg {Number} width Width of input field in pixels (defaults to 100)
*/
,width:100
/**
* @cfg {String} xtype xtype is usually not used to instantiate this plugin but you have a chance to identify it
*/
,xtype:'gridsearch'
/**
* @cfg {Object} paramNames Params name map (defaults to {fields:'fields', query:'query'}
*/
,paramNames: {
fields:'fields'
,query:'query'
}
/**
* @cfg {int} position
* The starting position inside the toolbar
*/
,tbPosition: 15
/**
* @cfg {String} align 'left' or 'right' (defaults to 'left')
*/
/**
* @cfg {Number} minLength force user to type this many character before he can make a search
*/

// {{{
/**
* private
* @param {Ext.grid.GridPanel/Ext.grid.EditorGrid} grid reference to grid this plugin is used for
*/
,init:function(grid) {
this.grid = grid;

// do our processing after grid render and reconfigure
grid.onRender = grid.onRender.createSequence(this.onRender, this);
grid.reconfigure = grid.reconfigure.createSequence(this.reconfigure, this);
} // eo function init
// }}}
// {{{
/**
* private add plugin controls to <b>existing</b> toolbar and calls reconfigure
*/
,onRender:function() {
var grid = this.grid;
var tb = 'bottom' == this.position ? grid.bottomToolbar : grid.topToolbar;

// add menu
this.menu = new Ext.menu.Menu();

// handle position
if('right' === this.align) {
tb.insert(this.tbPosition, '->');
}
else {
tb.insert(this.tbPosition, '-');
}
this.tbPosition++;

// add menu button
tb.insert(this.tbPosition, {
text:this.searchText
,menu:this.menu
,iconCls:this.iconCls
});
this.tbPosition++;

// add input field (TwinTriggerField in fact)
this.field = new Ext.form.TwinTriggerField({
width:this.width
,selectOnFocus:undefined === this.selectOnFocus ? true : this.selectOnFocus
,trigger1Class:'x-form-clear-trigger'
,trigger2Class:'x-form-search-trigger'
,onTrigger1Click:this.onTriggerClear.createDelegate(this)
,onTrigger2Click:this.onTriggerSearch.createDelegate(this)
,minLength:this.minLength
});

// install event handlers on input field
this.field.on('render', function() {
this.field.el.dom.qtip = this.searchTipText;

if(this.minChars) {
this.field.el.on({scope:this, buffer:300, keyup:this.onKeyUp});
}

// install key map
var map = new Ext.KeyMap(this.field.el, [{
key:Ext.EventObject.ENTER
,scope:this
,fn:this.onTriggerSearch
},{
key:Ext.EventObject.ESC
,scope:this
,fn:this.onTriggerClear
}]);
map.stopEvent = true;
}, this, {single:true});

tb.insert(this.tbPosition, this.field);

// reconfigure
this.reconfigure();
} // eo function onRender
// }}}
// {{{
/**
* private Clear Trigger click handler
*/
,onTriggerClear:function() {
this.field.setValue('');
this.field.focus();
this.onTriggerSearch();
} // eo function onTriggerClear
// }}}
// {{{
/**
* private Search Trigger click handler (executes the search, local or remote)
*/
,onTriggerSearch:function() {
if(!this.field.isValid()) {
return;
}
var val = this.field.getValue();
var store = this.grid.store;

// grid's store filter
if('local' === this.mode) {
store.clearFilter();
if(val) {
store.filterBy(function(r) {
var retval = false;
this.menu.items.each(function(item) {
if(!item.checked || retval) {
return;
}
var rv = r.get(item.dataIndex);
rv = rv instanceof Date ? rv.format(this.dateFormat || r.fields.get(item.dataIndex).dateFormat) : rv;
var re = new RegExp(val, 'gi');
retval = re.test(rv);
}, this);
if(retval) {
return true;
}
return retval;
}, this);
}
else {
}
}
// ask server to filter records
else {
// clear start (necessary if we have paging)
if(store.lastOptions && store.lastOptions.params) {
store.lastOptions.params[store.paramNames.start] = 0;
}

// get fields to search array
var fields = [];
this.menu.items.each(function(item) {
if(item.checked) {
fields.push(item.dataIndex);
}
});

// add fields and query to baseParams of store
delete(store.baseParams[this.paramNames.fields]);
delete(store.baseParams[this.paramNames.query]);
if (store.lastOptions && store.lastOptions.params) {
delete(store.lastOptions.params[this.paramNames.fields]);
delete(store.lastOptions.params[this.paramNames.query]);
}
if(fields.length) {
store.baseParams[this.paramNames.fields] = Ext.encode(fields);
store.baseParams[this.paramNames.query] = val;
}

// reload store
store.reload();
}

} // eo function onTriggerSearch
// }}}
// {{{

/**
* field el keypup event handler. Triggers the search
* @private
*/
,onKeyUp:function(e, t, o) {

if(e.isNavKeyPress()) {
return;
}

var length = this.field.getValue().toString().length;
if(0 === length || this.minChars <= length) {
this.onTriggerSearch();
}
} // eo function onKeyUp
// }}}
// {{{
/**
* @param {Boolean} true to disable search (TwinTriggerField), false to enable
*/
,setDisabled:function() {
this.field.setDisabled.apply(this.field, arguments);
} // eo function setDisabled
// }}}
// {{{
/**
* Enable search (TwinTriggerField)
*/
,enable:function() {
this.setDisabled(false);
} // eo function enable
// }}}
// {{{
/**
* Enable search (TwinTriggerField)
*/
,disable:function() {
this.setDisabled(true);
} // eo function disable
// }}}
// {{{
/**
* private (re)configures the plugin, creates menu items from column model
*/
,reconfigure:function() {

// {{{
// remove old items
var menu = this.menu;
menu.removeAll();

// add Select All item plus separator
if(this.showSelectAll) {
menu.add(new Ext.menu.CheckItem({
text:this.selectAllText
,checked:!(this.checkIndexes instanceof Array)
,hideOnClick:false
,handler:function(item) {
var checked = ! item.checked;
item.parentMenu.items.each(function(i) {
if(item !== i && i.setChecked) {
i.setChecked(checked);
}
});
}
}),'-');
}

// }}}
// {{{
// add new items
var cm = this.grid.colModel;
Ext.each(cm.config, function(config) {
var disable = false;
if(config.header && config.dataIndex) {
Ext.each(this.disableIndexes, function(item) {
disable = disable ? disable : item === config.dataIndex;
});
if(!disable) {
menu.add(new Ext.menu.CheckItem({
text:config.header
,hideOnClick:false
,checked:'all' === this.checkIndexes
,dataIndex:config.dataIndex
}));
}
}
}, this);
// }}}
// {{{
// check items
if(this.checkIndexes instanceof Array) {
Ext.each(this.checkIndexes, function(di) {
var item = menu.items.find(function(itm) {
return itm.dataIndex === di;
});
if(item) {
item.setChecked(true, true);
}
}, this);
}
// }}}

} // eo function reconfigure
// }}}

});

wemerson.januario
27 May 2010, 6:28 AM
nice. tested with extjs 3.2.1. version. OK

medusadelft
26 Jun 2010, 12:11 PM
Thanks for this, it's a nice plugin!
Does anyone know how I can set an Id for this plugin, so I can get this plugin to disable it. I noticed there is a setDisabled function, but I can't get it (with Ext.get of Ext.getCmp) when I give it an Id.

Thanks in advance!
Maurice

gabrieaj
9 Jun 2011, 5:21 AM
Hi,

I am trying to make this plugin work with one of our application which uses extjs 2.0.
Client does not want to upgrade to new versions of extjs.
It gives me error on "tb.insert is not a function".

Please could some one help me on this.

Thanks & Regards,
Ajay.

tobiu
9 Jun 2011, 7:21 AM
take a look at the ext2 ux forums,

i just migrated sakis plugin from ext 2 to ext 3, so you definitely should be able to find it there :)


best regards
tobiu

gabrieaj
9 Jun 2011, 9:53 PM
Thanks a lot for your help.

Thanks & Regards,
Ajay

venkateshns
16 Aug 2011, 3:46 AM
Will the same plugin approach applicable for EXTJS 4.0.2 ?

pouniok
21 Aug 2012, 11:27 PM
Hi,



I was wondering if someone tried this plugin with toolbar enableOverflow set to true ?

When my screen is too small, the search field is hidden, but when I click on the overflow button, I don't see it in the overflow menu.

I found that ToolbarLayout handle only buttons, splitbuttons and button groups components (in Ext.layout.ToolbarLayout.addComponentToMenu). So I added a few lines to handle classic components but I just can't make it work for now.

Then, I found that in my Ext 3.4 ext-all.js file, the declaration : Ext.reg('twintrigger', Ext.form.TwinTriggerField); was missing, and xtype is required by menu to add menu items. But it doesn't helped.



The must would have been to have a config option in toolbar components to say if they can be hidden or not when overflow is reached, so I could have set the search plugin to be the last thing to be hidden in the toolbar.


I will be glad for any help

Thanks,
Pouniok.

-------------------------------------
EDIT
-------------------------------------

I make it worked with these fixes :

Added an option "noOverflow" to the plugin button and field


tb.add({
text:this.searchText
,menu:this.menu
,noOverflow:true
,iconCls:this.iconCls
});

this.field = new Ext.form.TwinTriggerField({
width:this.width
,noOverflow:true
...
});


Then, overrieded the ToolbarLayout.fitToSize code


Ext.override(Ext.layout.ToolbarLayout, {
fitToSize : function(target) {
if (this.container.enableOverflow === false) {
return;
}

var width = target.dom.clientWidth,
tableWidth = target.dom.firstChild.offsetWidth,
clipWidth = width - this.triggerWidth,
lastWidth = this.lastWidth || 0,

hiddenItems = this.hiddenItems,
hasHiddens = hiddenItems.length != 0,
isLarger = width >= lastWidth;

this.lastWidth = width;

if (tableWidth > width || (hasHiddens && isLarger)) {
var items = this.container.items.items,
len = items.length,
loopWidth = 0,
minWidth = 0,
item;


for (var i = 0; i < len; i++) {
item = items[i];

if (item.noOverflow == true) {
minWidth += this.getItemWidth(item);
}
}
loopWidth = minWidth;


for (var i = 0; i < len; i++) {
item = items[i];

if (!item.isFill && !item.noOverflow) {
loopWidth += this.getItemWidth(item);
if (loopWidth > clipWidth) {
if (!(item.hidden || item.xtbHidden)) {
this.hideItem(item);
}
} else if (item.xtbHidden) {
this.unhideItem(item);
}
}
}
}

//test for number of hidden items again here because they may have changed above
hasHiddens = hiddenItems.length != 0;

if (hasHiddens) {
this.initMore();

if (!this.lastOverflow) {
this.container.fireEvent('overflowchange', this.container, true);
this.lastOverflow = true;
}
} else if (this.more) {
this.clearMenu();
this.more.destroy();
delete this.more;

if (this.lastOverflow) {
this.container.fireEvent('overflowchange', this.container, false);
this.lastOverflow = false;
}
}
}
});