-
18 Mar 2010 12:35 PM #1
Plugin to allow auto sizing of the combo's list
Plugin to allow auto sizing of the combo's list
Hello all,
I needed something to auto size the combo's list to its content. I found the simplest solution here in the forum, overriding initList. However, we hate overriding component's methods, so I wrote a plugin that does the same thing.
Let me know if anybody uses it.
This plugin is a singleton, so don't use new when adding it to the plugins array:PHP Code:Ext.ns('wfs.extplugins');
/**
* Plugin for Ext.form.ComboBox that auto sizes the combo's list based on the text in the store when the view opens
* This plugin relies on each item in the having the .x-combo-list-item class. Therefore, if you override the
* template, make sure each item still has the .x-combo-list-item class.
* Warning, this plugin relies on the internals of combo box, lookout when upgrading.
*/
wfs.extplugins.ComboListAutoSizer = (function(){
// How much padding to add when measuring the list items, used to prevent text from being jammed against the edge
var LIST_PADDING = 10;
/**
* Auto sizes the list in a combo by measuring the text in the combo's records.
* @param {Ext.form.ComboBox}combo
*/
function autoSizeList(combo) {
var viewEl = combo.view && combo.view.getEl();
// This may get called before the view is rendered, ignore it in that case
if (!viewEl) {
return;
}
var metrics = Ext.util.TextMetrics.createInstance(viewEl.child('.x-combo-list-item'));
var maxWidth = combo.minListWidth;
combo.getStore().each(function(rec){
// Add some padding so the text is not jammed against the edge of the drop down
maxWidth = Math.max(maxWidth, metrics.getWidth(rec.get(combo.displayField)) + LIST_PADDING);
});
// There are two elements in the dropdown list that have their width set. See Ext.form.ComboBox.initList
combo.list.setWidth(maxWidth);
combo.innerList.setWidth(maxWidth - combo.list.getFrameWidth('lr'));
combo.list.alignTo(combo.wrap, combo.listAlign);
}
// Return the actual plugin object
return {
init: function(combo) {
combo.on('expand', autoSizeList, null, {single: true});
var store = combo.getStore();
store.on('load', autoSizeList);
store.on('update', autoSizeList);
}
};
})();
PHP Code:{
xtype: 'combo',
plugins: [wfs.extplugins.ComboListAutoSizer]
}
Last edited by Juanito; 3 Feb 2011 at 11:33 AM. Reason: Explain that it's a singleton
-
22 Mar 2010 2:42 PM #2
Great plugin, is exactly what I was looking!!!!
I already implemented it in the app I'm doing and works great!
It would be nice to have the same plugin for grid columns.
One more comment to your plugin, it would be excellent if it gets the minimum size of the combo if the min width of the list is not set or maybe always. It looks nicer!
-
20 Apr 2010 6:41 AM #3
Great plugin, had to make two changes though:
- The list has no items on first expand if the store is remote, so you need to check for the existence of an item row before instantiating TextMetrics on it
- The autoSizeList function can't be directly assigned as a handler to the store's "load" and "update" events because their signatures don't match
- Use combo's itemSelector config property if there is one
Updated code (relocated to the Ext.ux namespace):
PHP Code:Ext.namespace("Ext.ux");
Ext.ux.ComboListAutoSizer = (function() {
function autoSizeList(combo) {
var itemEl = combo.view && combo.view.getEl() && combo.view.getEl().child(combo.itemSelector || ".x-combo-list-item");
if (!itemEl) return;
var textMetrics = Ext.util.TextMetrics.createInstance(itemEl);
var autoWidth = Math.max(combo.minListWidth, combo.getWidth());
combo.getStore().each(function(record) {
autoWidth = Math.max(autoWidth, textMetrics.getWidth(record.get(combo.displayField)) + 10);
});
combo.list.setWidth(autoWidth);
combo.innerList.setWidth(autoWidth - combo.list.getFrameWidth("lr"));
combo.list.alignTo(combo.wrap, combo.listAlign);
}
// Public API
return {
init: function(combo) {
combo.on("expand", autoSizeList, null, {
single: true
});
var store = combo.getStore();
store.on("load", function() {
autoSizeList(combo);
});
store.on("update", function() {
autoSizeList(combo);
});
}
};
})();
Last edited by Stefan B; 20 Apr 2010 at 6:45 AM. Reason: Added the previous poster's request to the minimum width calculation
-
27 Apr 2010 2:39 PM #4
Sorry if my question is dumb, but I’ve spend over 2 hours trying to implement this plugin already.
I put code from Stefan B into file called Ext.ux.plugins.js and include in on my page.
When add plugins to my combobox as follows
I getPHP Code:plugins: [new Ext.ux.ComboListAutoSizer()],
What is wrong?Code:Ext.ux.ComboListAutoSizer is not a constructor
-
27 Apr 2010 8:03 PM #5
-
27 Apr 2010 9:06 PM #6
-
27 Apr 2010 11:08 PM #7
-
28 Apr 2010 2:03 PM #8
-
28 Apr 2010 2:08 PM #9
-
28 Apr 2010 2:35 PM #10
I've just went to original combos.html example file which comes with ExtJS and customized to:
combos.js
combos.htmlPHP Code:/*!
* Ext JS Library 3.2.0
* Copyright(c) 2006-2010 Ext JS, Inc.
* licensing@extjs.com
* http://www.extjs.com/license
*/
Ext.namespace("Ext.ux");
Ext.ux.ComboListAutoSizer = (function ()
{
function autoSizeList(combo)
{
var itemEl = combo.view && combo.view.getEl() && combo.view.getEl().child(combo.itemSelector || ".x-combo-list-item");
if (!itemEl) return;
var textMetrics = Ext.util.TextMetrics.createInstance(itemEl);
var autoWidth = Math.max(combo.minListWidth, combo.getWidth());
combo.getStore().each(function (record)
{
autoWidth = Math.max(autoWidth, textMetrics.getWidth(record.get(combo.displayField)) + 10);
});
combo.list.setWidth(autoWidth);
combo.innerList.setWidth(autoWidth - combo.list.getFrameWidth("lr"));
combo.list.alignTo(combo.wrap, combo.listAlign);
}
// Public API
return {
init: function (combo)
{
combo.on("expand", autoSizeList, null, {
single: true
});
var store = combo.getStore();
store.on("load", function ()
{
autoSizeList(combo);
});
store.on("update", function ()
{
autoSizeList(combo);
});
}
};
})();
Ext.onReady(function(){
Ext.QuickTips.init();
// simple array store
var store = new Ext.data.ArrayStore({
fields: ['abbr', 'state', 'nick'],
data : Ext.exampledata.states // from states.js
});
var combo = new Ext.form.ComboBox({
store: store,
displayField:'state',
typeAhead: true,
mode: 'local',
forceSelection: true,
triggerAction: 'all',
emptyText:'Select a state...',
selectOnFocus:true,
plugins: [new Ext.ux.ComboListAutoSizer],
applyTo: 'local-states'
});
});
When I've opened the file I've received exactly same error which I am describing above. Any idea whats wrong? Does anyone has working example of this plugin?PHP Code:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Combo Boxes</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<link rel="stylesheet" type="text/css" href="../../resources/css/xtheme-gray.css" />
<!-- GC -->
<!-- LIBS -->
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<!-- ENDLIBS -->
<script type="text/javascript" src="../../ext-all.js"></script>
<script type="text/javascript" src="states.js"></script>
<script type="text/javascript" src="combos.js"></script>
<link rel="stylesheet" type="text/css" href="combos.css" />
<!-- Common Styles for the examples -->
<link rel="stylesheet" type="text/css" href="../shared/examples.css" />
<style type="text/css">
p { width:650px; }
</style>
</head>
<body>
<script type="text/javascript" src="../shared/examples.js"></script><!-- EXAMPLES -->
<h1>Combo Boxes</h1>
<div>
<input type="text" id="local-states" size="20"/>
</div>
</body>
</html>


Reply With Quote


