- Author:
- David Nickerson <nickerso@users.sourceforge.net>
- Date:
- 2009-07-07 22:22:32+12:00
- Desc:
- renaming files in order to move to a single reference description for the entire tutorial
- Permanent Source URI:
- https://models.physiomeproject.org/workspace/a1/rawfile/0c824288680f5949ea1972a76176826599ef6d26/dojo-presentation/js/dojo/dijit/form/FilteringSelect.js
dojo.provide("dijit.form.FilteringSelect");
dojo.require("dijit.form.ComboBox");
dojo.declare(
"dijit.form.FilteringSelect",
[dijit.form.MappedTextBox, dijit.form.ComboBoxMixin],
{
// summary
// An enhanced version of the HTML SELECT tag, populated dynamically
//
// description
// An enhanced version of the HTML SELECT tag, populated dynamically. It works
// very nicely with very large data sets because it can load and page data as needed.
// It also resembles ComboBox, but does not allow values outside of the provided ones.
//
// Similar features:
// - There is a drop down list of possible values.
// - You can only enter a value from the drop down list. (You can't
// enter an arbitrary value.)
// - The value submitted with the form is the hidden value (ex: CA),
// not the displayed value a.k.a. label (ex: California)
//
// Enhancements over plain HTML version:
// - If you type in some text then it will filter down the list of
// possible values in the drop down list.
// - List can be specified either as a static list or via a javascript
// function (that can get the list from a server)
//
_isvalid:true,
required:true,
_lastDisplayedValue: "",
isValid:function(){
return this._isvalid || (!this.required && this.getDisplayedValue() == ""); // #5974
},
_callbackSetLabel: function( /*Array*/ result,
/*Object*/ dataObject,
/*Boolean?*/ priorityChange){
// summary:
// Callback function that dynamically sets the label of the
// ComboBox
// setValue does a synchronous lookup,
// so it calls _callbackSetLabel directly,
// and so does not pass dataObject
// still need to test against _lastQuery in case it came too late
if((dataObject && dataObject.query[this.searchAttr] != this._lastQuery)||(!dataObject&&this.store.getIdentity(result[0])!= this._lastQuery)){
return;
}
if(!result.length){
//#3268: do nothing on bad input
//this._setValue("", "");
//#3285: change CSS to indicate error
if(!this._focused){ this.valueNode.value=""; }
dijit.form.TextBox.superclass.setValue.call(this, "", !this._focused);
this._isvalid=false;
this.validate(this._focused);
this.item=null;
}else{
this._setValueFromItem(result[0], priorityChange);
}
},
_openResultList: function(/*Object*/ results, /*Object*/ dataObject){
// #3285: tap into search callback to see if user's query resembles a match
if(dataObject.query[this.searchAttr] != this._lastQuery){
return;
}
this._isvalid = results.length != 0; // FIXME: should this be greater-than?
this.validate(true);
dijit.form.ComboBoxMixin.prototype._openResultList.apply(this, arguments);
},
getValue:function(){
// don't get the textbox value but rather the previously set hidden value
return this.valueNode.value;
},
_getValueField:function(){
// used for option tag selects
return "value";
},
_setValue:function( /*String*/ value,
/*String*/ displayedValue,
/*Boolean?*/ priorityChange){
this.valueNode.value = value;
dijit.form.FilteringSelect.superclass.setValue.call(this, value, priorityChange, displayedValue);
this._lastDisplayedValue = displayedValue;
},
setValue: function(/*String*/ value, /*Boolean?*/ priorityChange){
// summary
// Sets the value of the select.
// Also sets the label to the corresponding value by reverse lookup.
this._lastQuery=value;
if(!value){
this.setDisplayedValue("",priorityChange);
return;
}
//#3347: fetchItemByIdentity if no keyAttr specified
var self=this;
var handleFetchByIdentity = function(item, priorityChange){
if(item){
if(self.store.isItemLoaded(item)){
self._callbackSetLabel([item], undefined, priorityChange);
}else{
self.store.loadItem({
item: item,
onItem: function(result, dataObject){
self._callbackSetLabel(result, dataObject, priorityChange);
}
});
}
}else{
self._isvalid=false;
// prevent errors from Tooltip not being created yet
self.validate(false);
}
}
this.store.fetchItemByIdentity({
identity: value,
onItem: function(item){
handleFetchByIdentity(item, priorityChange);
}
});
},
_setValueFromItem: function(/*item*/ item, /*Boolean?*/ priorityChange){
// summary:
// Set the displayed valued in the input box, based on a
// selected item.
// description:
// Users shouldn't call this function; they should be calling
// setDisplayedValue() instead
this._isvalid=true;
this.item = item; // Fix #6381
this._setValue( this.store.getIdentity(item),
this.labelFunc(item, this.store),
priorityChange);
},
labelFunc: function(/*item*/ item, /*dojo.data.store*/ store){
// summary: Event handler called when the label changes
// return: the label that the ComboBox should display
return store.getValue(item, this.searchAttr);
},
_doSelect: function(/*Event*/ tgt){
// summary:
// ComboBox's menu callback function
// description:
// FilteringSelect overrides this to set both the visible and
// hidden value from the information stored in the menu
this._setValueFromItem(tgt.item, true);
},
setDisplayedValue:function(/*String*/ label, /*Boolean?*/ priorityChange){
// summary:
// Set textbox to display label. Also performs reverse lookup
// to set the hidden value. Used in InlineEditBox
if(this.store){
var query = dojo.clone(this.query); // #6196: populate query with user-specifics
// escape meta characters of dojo.data.util.filter.patternToRegExp().
this._lastQuery = query[this.searchAttr] = label.replace(/([\\\*\?])/g, "\\$1");
// if the label is not valid, the callback will never set it,
// so the last valid value will get the warning textbox set the
// textbox value now so that the impending warning will make
// sense to the user
this.textbox.value = label;
this._lastDisplayedValue = label;
var _this = this;
this.store.fetch({
query: query,
queryOptions: {
ignoreCase: this.ignoreCase,
deep: true
},
onComplete: function(result, dataObject){
dojo.hitch(_this, "_callbackSetLabel")(result, dataObject, priorityChange);
},
onError: function(errText){
console.error('dijit.form.FilteringSelect: ' + errText);
dojo.hitch(_this, "_setValue")("", label, false);
}
});
}
},
postMixInProperties: function(){
// FIXME: shouldn't this just be a call to inherited?
dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);
dijit.form.MappedTextBox.prototype.postMixInProperties.apply(this, arguments);
},
postCreate: function(){
dijit.form.ComboBoxMixin.prototype._postCreate.apply(this, arguments);
dijit.form.MappedTextBox.prototype.postCreate.apply(this, arguments);
},
setAttribute: function(/*String*/ attr, /*anything*/ value){
dijit.form.MappedTextBox.prototype.setAttribute.apply(this, arguments);
dijit.form.ComboBoxMixin.prototype._setAttribute.apply(this, arguments);
},
undo: function(){
this.setDisplayedValue(this._lastDisplayedValue);
},
_valueChanged: function(){
return this.getDisplayedValue()!=this._lastDisplayedValue;
}
}
);