// Takes a input form element and a hidden form element (to store the selected id in) along with an array of objects, to build a dropdown select control that allows the user to type part of the selection to filter the list.
//Ensure that if the hidden field exists and changes, that the hidden field's id matches the text in the input field. If not then the hidden id field was changed manually and externally and the text field should be updated.
if(this.$hidden){
this.$hidden.on('change',function(event){
varid=_this.$hidden.val();
var$li=_this.$list.children("[role!='node']");
for(vari=0;i<$li.length;i++){
var$next=$($li[i]);
if($next.data('model').id==id){
if(_this.$input.val()!=$next.text())
_this.$input.val($next.text());
}
}
});
}
//this.$list.appendTo($input.parent());
this.$list.appendTo(this.$listContainer);
this.$listContainer.appendTo($input.parent());
//Setup the list to highlight the item the user is hovering over, to select the item the user clicks, and to remove the hover styling when the list closes due to a selection being made.
//Setup the input field to handle opening the list when it receives focus, and close it when it loses focus.
this.$input
.on('focus',$.proxy(_this.focus,_this))
.on('blur',$.proxy(_this.blur,_this));
//Handle key events on the input field. Up/down arrows should change the selection in the list. Enter should select an item and close the list. Tab and escape should hide the list before moving to the next focusable element on the page.
//Filter the set of elements so that only those matching the text in the input field are marked as visible.
_this.filter();
}
//Add the initial set of data.
add(data);
};
EditableSelect.DEFAULTS={
textAttr:'text',//The attribute of the data elements to use for the name. This can also be a function that takes the data object and returns the text.
idAttr:'id',//The attribute of the data elements to use for the ID. This can also be a function that takes the data obejct and returns the ID.
// groupFunctions: The object containing three functions: 'groupParent', 'parentText', 'children'.
// groupParents(data) will take a data element and return the objects that best represents the parents of the children (for a multi layer tree, this would be the node just before the leaf nodes).
// parentText(parent) will be passed the group parent and the data object that generated it, and will return the text that represents the path to that parent.
// children(parent) will be passed the group parent (returned by groupParents()), and will return an array of children or leaf nodes for the tree.
groupFunctions:undefined,
filter:true,//Whether to filter the list as the user types.
effects:'fade',
duration:'200',
listClass:'editable-select-list',
selectionClass:'selected'//The class to use for the selected element in the dropdown list.
};
EditableSelect.prototype.select=function($li){
if($li.length==0){
if(this.$input.val()!=''){
this.$input.val("")
if(this.$hidden)this.$hidden.val(undefined);
this.filter();
//Note: Don't trigger the select event - for some reason it causes the dropdown to reopen and the control to retain focus when clicking out of the widget.
//Hide non-node elements (leaf nodes) that don't match.
varli=this.$list.children();
//Iterate over the list elements:
// hide all list items that are nodes;
// show all list items that are not nodes and whose text matches the input value;
// show all node list items associated with visible child list items (they occur after the parent, so the parent will be hidden first, then made visible).
// goDown: true/false - defaults to true - indicating whether the highlighting should go up or down if the requested item is a node. Nodes cannot be highlighted or selected.