2150 |
mathias |
1 |
if(!dojo._hasResource["dijit.form.FilteringSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
|
|
2 |
dojo._hasResource["dijit.form.FilteringSelect"] = true;
|
|
|
3 |
dojo.provide("dijit.form.FilteringSelect");
|
|
|
4 |
|
|
|
5 |
dojo.require("dijit.form.ComboBox");
|
|
|
6 |
|
|
|
7 |
dojo.declare(
|
|
|
8 |
"dijit.form.FilteringSelect",
|
|
|
9 |
[dijit.form.MappedTextBox, dijit.form.ComboBoxMixin],
|
|
|
10 |
{
|
|
|
11 |
/*
|
|
|
12 |
* summary
|
|
|
13 |
* Enhanced version of HTML's <select> tag.
|
|
|
14 |
*
|
|
|
15 |
* Similar features:
|
|
|
16 |
* - There is a drop down list of possible values.
|
|
|
17 |
* - You can only enter a value from the drop down list. (You can't enter an arbitrary value.)
|
|
|
18 |
* - The value submitted with the form is the hidden value (ex: CA),
|
|
|
19 |
* not the displayed value a.k.a. label (ex: California)
|
|
|
20 |
*
|
|
|
21 |
* Enhancements over plain HTML version:
|
|
|
22 |
* - If you type in some text then it will filter down the list of possible values in the drop down list.
|
|
|
23 |
* - List can be specified either as a static list or via a javascript function (that can get the list from a server)
|
|
|
24 |
*/
|
|
|
25 |
|
|
|
26 |
// searchAttr: String
|
|
|
27 |
// Searches pattern match against this field
|
|
|
28 |
|
|
|
29 |
// labelAttr: String
|
|
|
30 |
// Optional. The text that actually appears in the drop down.
|
|
|
31 |
// If not specified, the searchAttr text is used instead.
|
|
|
32 |
labelAttr: "",
|
|
|
33 |
|
|
|
34 |
// labelType: String
|
|
|
35 |
// "html" or "text"
|
|
|
36 |
labelType: "text",
|
|
|
37 |
|
|
|
38 |
_isvalid:true,
|
|
|
39 |
|
|
|
40 |
isValid:function(){
|
|
|
41 |
return this._isvalid;
|
|
|
42 |
},
|
|
|
43 |
|
|
|
44 |
_callbackSetLabel: function(/*Array*/ result, /*Object*/ dataObject, /*Boolean, optional*/ priorityChange){
|
|
|
45 |
// summary
|
|
|
46 |
// Callback function that dynamically sets the label of the ComboBox
|
|
|
47 |
|
|
|
48 |
// setValue does a synchronous lookup,
|
|
|
49 |
// so it calls _callbackSetLabel directly,
|
|
|
50 |
// and so does not pass dataObject
|
|
|
51 |
// dataObject==null means do not test the lastQuery, just continue
|
|
|
52 |
if(dataObject&&dataObject.query[this.searchAttr]!=this._lastQuery){return;}
|
|
|
53 |
if(!result.length){
|
|
|
54 |
//#3268: do nothing on bad input
|
|
|
55 |
//this._setValue("", "");
|
|
|
56 |
//#3285: change CSS to indicate error
|
|
|
57 |
if(!this._hasFocus){ this.valueNode.value=""; }
|
|
|
58 |
dijit.form.TextBox.superclass.setValue.call(this, undefined, !this._hasFocus);
|
|
|
59 |
this._isvalid=false;
|
|
|
60 |
this.validate(this._hasFocus);
|
|
|
61 |
}else{
|
|
|
62 |
this._setValueFromItem(result[0], priorityChange);
|
|
|
63 |
}
|
|
|
64 |
},
|
|
|
65 |
|
|
|
66 |
_openResultList: function(/*Object*/ results, /*Object*/ dataObject){
|
|
|
67 |
// #3285: tap into search callback to see if user's query resembles a match
|
|
|
68 |
if(dataObject.query[this.searchAttr]!=this._lastQuery){return;}
|
|
|
69 |
this._isvalid=results.length!=0;
|
|
|
70 |
this.validate(true);
|
|
|
71 |
dijit.form.ComboBoxMixin.prototype._openResultList.apply(this, arguments);
|
|
|
72 |
},
|
|
|
73 |
|
|
|
74 |
getValue:function(){
|
|
|
75 |
// don't get the textbox value but rather the previously set hidden value
|
|
|
76 |
return this.valueNode.value;
|
|
|
77 |
},
|
|
|
78 |
|
|
|
79 |
_getValueField:function(){
|
|
|
80 |
// used for option tag selects
|
|
|
81 |
return "value";
|
|
|
82 |
},
|
|
|
83 |
|
|
|
84 |
_setValue:function(/*String*/ value, /*String*/ displayedValue, /*Boolean, optional*/ priorityChange){
|
|
|
85 |
this.valueNode.value = value;
|
|
|
86 |
dijit.form.FilteringSelect.superclass.setValue.call(this, value, priorityChange, displayedValue);
|
|
|
87 |
this._lastDisplayedValue = displayedValue;
|
|
|
88 |
},
|
|
|
89 |
|
|
|
90 |
setValue: function(/*String*/ value, /*Boolean, optional*/ priorityChange){
|
|
|
91 |
// summary
|
|
|
92 |
// Sets the value of the select.
|
|
|
93 |
// Also sets the label to the corresponding value by reverse lookup.
|
|
|
94 |
|
|
|
95 |
//#3347: fetchItemByIdentity if no keyAttr specified
|
|
|
96 |
var self=this;
|
|
|
97 |
var handleFetchByIdentity = function(item, priorityChange){
|
|
|
98 |
if(item){
|
|
|
99 |
if(self.store.isItemLoaded(item)){
|
|
|
100 |
self._callbackSetLabel([item], undefined, priorityChange);
|
|
|
101 |
}else{
|
|
|
102 |
self.store.loadItem({item:item, onItem: function(result, dataObject){self._callbackSetLabel(result, dataObject, priorityChange)}});
|
|
|
103 |
}
|
|
|
104 |
}else{
|
|
|
105 |
self._isvalid=false;
|
|
|
106 |
// prevent errors from Tooltip not being created yet
|
|
|
107 |
self.validate(false);
|
|
|
108 |
}
|
|
|
109 |
}
|
|
|
110 |
this.store.fetchItemByIdentity({identity: value, onItem: function(item){handleFetchByIdentity(item, priorityChange)}});
|
|
|
111 |
},
|
|
|
112 |
|
|
|
113 |
_setValueFromItem: function(/*item*/ item, /*Boolean, optional*/ priorityChange){
|
|
|
114 |
// summary
|
|
|
115 |
// Set the displayed valued in the input box, based on a selected item.
|
|
|
116 |
// Users shouldn't call this function; they should be calling setDisplayedValue() instead
|
|
|
117 |
this._isvalid=true;
|
|
|
118 |
this._setValue(this.store.getIdentity(item), this.labelFunc(item, this.store), priorityChange);
|
|
|
119 |
},
|
|
|
120 |
|
|
|
121 |
labelFunc: function(/*item*/ item, /*dojo.data.store*/ store){
|
|
|
122 |
// summary: Event handler called when the label changes
|
|
|
123 |
// returns the label that the ComboBox should display
|
|
|
124 |
return store.getValue(item, this.searchAttr);
|
|
|
125 |
},
|
|
|
126 |
|
|
|
127 |
onkeyup: function(/*Event*/ evt){
|
|
|
128 |
// summary: internal function
|
|
|
129 |
// FilteringSelect needs to wait for the complete label before committing to a reverse lookup
|
|
|
130 |
//this.setDisplayedValue(this.textbox.value);
|
|
|
131 |
},
|
|
|
132 |
|
|
|
133 |
_doSelect: function(/*Event*/ tgt){
|
|
|
134 |
// summary:
|
|
|
135 |
// ComboBox's menu callback function
|
|
|
136 |
// FilteringSelect overrides this to set both the visible and hidden value from the information stored in the menu
|
|
|
137 |
this.item = tgt.item;
|
|
|
138 |
this._setValueFromItem(tgt.item, true);
|
|
|
139 |
},
|
|
|
140 |
|
|
|
141 |
setDisplayedValue:function(/*String*/ label){
|
|
|
142 |
// summary:
|
|
|
143 |
// Set textbox to display label
|
|
|
144 |
// Also performs reverse lookup to set the hidden value
|
|
|
145 |
// Used in InlineEditBox
|
|
|
146 |
|
|
|
147 |
if(this.store){
|
|
|
148 |
var query={};
|
|
|
149 |
this._lastQuery=query[this.searchAttr]=label;
|
|
|
150 |
// if the label is not valid, the callback will never set it,
|
|
|
151 |
// so the last valid value will get the warning textbox
|
|
|
152 |
// set the textbox value now so that the impending warning will make sense to the user
|
|
|
153 |
this.textbox.value=label;
|
|
|
154 |
this._lastDisplayedValue=label;
|
|
|
155 |
this.store.fetch({query:query, queryOptions:{ignoreCase:this.ignoreCase, deep:true}, onComplete: dojo.hitch(this, this._callbackSetLabel)});
|
|
|
156 |
}
|
|
|
157 |
},
|
|
|
158 |
|
|
|
159 |
_getMenuLabelFromItem:function(/*Item*/ item){
|
|
|
160 |
// internal function to help ComboBoxMenu figure out what to display
|
|
|
161 |
if(this.labelAttr){return {html:this.labelType=="html", label:this.store.getValue(item, this.labelAttr)};}
|
|
|
162 |
else{
|
|
|
163 |
// because this function is called by ComboBoxMenu, this.inherited tries to find the superclass of ComboBoxMenu
|
|
|
164 |
return dijit.form.ComboBoxMixin.prototype._getMenuLabelFromItem.apply(this, arguments);
|
|
|
165 |
}
|
|
|
166 |
},
|
|
|
167 |
|
|
|
168 |
postMixInProperties: function(){
|
|
|
169 |
dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);
|
|
|
170 |
dijit.form.MappedTextBox.prototype.postMixInProperties.apply(this, arguments);
|
|
|
171 |
}
|
|
|
172 |
}
|
|
|
173 |
);
|
|
|
174 |
|
|
|
175 |
}
|