Recipe 11.5 Resizing Menus to Fit Their Contents
11.5.1 Problem
You want to adjust the width of
a menu to accommodate the widest menu
item.
11.5.2 Solution
Create and invoke a
custom adjustWidth( )
method.
11.5.3 Discussion
Both combo boxes and list boxes default to a width of 100 pixels, and
they do not automatically resize to fit their contents when you
populate them. Therefore, the text of menu items wider than 100
pixels is cut off. Although the menu components offer no documented
means of adjusting the width to fit the contents, there are several
undocumented properties you can use to create a custom method that
sizes the menus appropriately. Menu components (list boxes and combo
boxes) are subclasses of FSelectableListClass.
Therefore, if you add a custom adjustWidth( )
method to FSelectableListClass, it is
accessible to both list boxes and combo boxes.
Furthermore, all objects derived from
FSelectableListClass have three undocumented
properties that are valuable in calculating the necessary width to
accommodate all the menu items:
- labels
-
An array of string values displayed in the menu when the menu is
populated from the Parameters panel at authoring time.
- dataprovider
-
A reference to a DataProvider object that is
created when the menu is populated at runtime by the
setDataProvider( ) method. It has an
items property that is an array of objects with
label properties (yielding the needed string
values).
- textstyle
-
A reference to the TextFormat object used to
format the menu items.
You can use these properties to determine the text width of each menu
item (using the TextFormat.getTextExtent( )
method).
Here is our custom FSelectableListClass.adjustWidth(
) method:
// Add the adjustWidth( ) method to FSelectableListClass.
FSelectableListClass.prototype.adjustWidth = function ( ) {
// maxW stores the largest text extent.
var maxW = 0;
// w stores the text extent of each label element.
var w;
// The local variable labels is an array of the string values for each menu item.
// Assign it the value of the labels property to begin with.
var labels = this.labels;
// If the menu was not populated at authoring time, set labels to an array of the
// values obtained from the data provider.
if (labels == undefined) {
labels = new Array( );
// Append the label property for each data provider to the labels array.
for (var i = 0; i < this.dataprovider.getLength( ); i++) {
labels.push(this.dataprovider.getItemAt(i).label);
}
}
// Loop through all the elements of the labels array.
for (i = 0; i < labels.length; i++) {
// Use textstyle.getTextExtent( ) to obtain the width of each label (it returns an
// object with width and height properties, and we extract width here).
w = this.textstyle.getTextExtent(labels[i]).width;
// Store the width of the widest label in maxW.
maxW = Math.max(w, maxW);
}
// Use setSize( ) to set the menu width to maxW + 25. The 25 is padding so that menu
// items are not cut off by scrollbars. Pass the current height to setSize( ) to
// leave the list box's height unchanged (height does not apply to combo boxes).
this.setSize(maxW + 25, this._height);
};
You can test the custom adjustWidth( ) method as
follows:
// Create a new list box.
_root.attachMovie("FListBoxSymbol", "myListBox_lb", 1);
// Create an array to use as the data provider.
menuItems = ["item a", "item b", "item c", "item d"];
// Populate the list box.
myListBox_lb.setDataProvider(menuItems);
// Call adjustWidth( ) to set the menu width to fit the contents.
myListBox_lb.adjustWidth( );
|