delite/HasDropDown
delite/HasDropDown is a base class that provides drop-down menu functionality.
Widgets like Select, ComboBox, DropDownButton, DateTextBox etc. could use delite/HasDropDown
to implement their functionality.
However, note that it's geared towards desktop browsers. It doesn't adjust for phones, which should use an overlay rather than a dropdown, nor does it adjust for iOS tablets, which always enclose the dropdown in a tooltip.
This will be addressed somehow in the future.
Usage
First, make your widget extend delite/HasDropDown:
register("my-widget", [HTMLElement, HasDropDown], {
...
});
Then, either set the value of HasDropDown#dropDown to an existing widget:
register("my-widget", [HTMLElement, HasDropDown], {
dropDown: new MyMenu()
});
Or, override the HasDropDown#loadDropDown() and HasDropDown#isLoaded() methods to allow for lazy instantiation
of the drop-down (see "Dynamic & lazy-loading drop-downs", below).
Optional node properties
Note: All of these properties can only be set before Widget#buildRendering() is called.
_buttonNode
By default, delite/HasDropDown will use either focusNode or domNode as the element to click to display the drop-down.
If you want to use a specific element to click to display the drop-down instead, attach that element to buttonNode.
_arrowWrapperNode
When delite/HasDropDown is instantiated, a CSS class
d-up-arrow-button, d-down-arrow-button, d-right-arrow-button etc. is added to specify
which direction the pop-up appears by default relative to the widget.
By default, these classes are set on _buttonNode.
Attaching an element to _arrowWrapperNode will cause these classes to be applied to that element instead.
_popupStateNode
When a drop-down is opened, a CSS class d-drop-down-open attribute is added to indicate that the drop-down is open.
By default, these changes apply to focusNode, or _buttonNode if there is no focusNode.
Attaching an element to _popupStateNode will cause these changes to occur on that element instead.
_aroundNode
When the drop-down is opened, it is positioned based on the location of domNode.
Attaching an element to aroundNode will cause the drop-down to be positioned relative to that element instead.
Dynamic & lazy-loading drop-downs
By default, HasDropDown assumes that a delite widget has been created and assigned to HasDropDown.dropDown
before the widget starts up.
This works well for drop-downs that always contain the same content and are available immediately,
but it may reduce startup performance and it makes it impossible to create dynamically populated/asynchronous drop-downs.
In order to work around these limitations, more advanced drop-down widgets can implement
HasDropDown#loadDropDown() and HasDropDown#isLoaded() instead:
register("my-widget", [HTMLElement, HasDropDown], {
isLoaded: function () {
// Returns whether or not we are loaded - if our dropdown has an href,
// then we want to check that.
var dropDown = this.dropDown;
return !!dropDown && (!dropDown.href || dropDown.isLoaded);
},
loadDropDown: function(callback){
// Loads our dropdown
var dropDown = this.dropDown;
if (!dropDown) { return; }
if (!this.isLoaded()) {
var handler = dropDown.on("load", this, function () {
handler.remove();
callback();
});
dropDown.refresh();
}else{
callback();
}
}
});
});
