/ZendFramework/externals/dojo/dijit/form/FilteringSelect.js

https://bitbucket.org/Dal-Papa/is-340-publish-base · JavaScript · 209 lines · 113 code · 24 blank · 72 comment · 25 complexity · 63480113a26e1f3979fd56105ab39957 MD5 · raw file

  1. dojo.provide("dijit.form.FilteringSelect");
  2. dojo.require("dijit.form.ComboBox");
  3. dojo.declare(
  4. "dijit.form.FilteringSelect",
  5. [dijit.form.MappedTextBox, dijit.form.ComboBoxMixin],
  6. {
  7. // summary:
  8. // An enhanced version of the HTML SELECT tag, populated dynamically
  9. //
  10. // description:
  11. // An enhanced version of the HTML SELECT tag, populated dynamically. It works
  12. // very nicely with very large data sets because it can load and page data as needed.
  13. // It also resembles ComboBox, but does not allow values outside of the provided ones.
  14. // If OPTION tags are used as the data provider via markup, then the
  15. // OPTION tag's child text node is used as the displayed value when selected
  16. // while the OPTION tag's value attribute is used as the widget value on form submit.
  17. // To set the default value when using OPTION tags, specify the selected
  18. // attribute on 1 of the child OPTION tags.
  19. //
  20. // Similar features:
  21. // - There is a drop down list of possible values.
  22. // - You can only enter a value from the drop down list. (You can't
  23. // enter an arbitrary value.)
  24. // - The value submitted with the form is the hidden value (ex: CA),
  25. // not the displayed value a.k.a. label (ex: California)
  26. //
  27. // Enhancements over plain HTML version:
  28. // - If you type in some text then it will filter down the list of
  29. // possible values in the drop down list.
  30. // - List can be specified either as a static list or via a javascript
  31. // function (that can get the list from a server)
  32. _isvalid: true,
  33. // required: Boolean
  34. // True (default) if user is required to enter a value into this field.
  35. required: true,
  36. _lastDisplayedValue: "",
  37. isValid: function(){
  38. // Overrides ValidationTextBox.isValid()
  39. return this._isvalid || (!this.required && this.get('displayedValue') == ""); // #5974
  40. },
  41. _refreshState: function(){
  42. if(!this.searchTimer){ // state will be refreshed after results are returned
  43. this.inherited(arguments);
  44. }
  45. },
  46. _callbackSetLabel: function( /*Array*/ result,
  47. /*Object*/ dataObject,
  48. /*Boolean?*/ priorityChange){
  49. // summary:
  50. // Callback function that dynamically sets the label of the
  51. // ComboBox
  52. // setValue does a synchronous lookup,
  53. // so it calls _callbackSetLabel directly,
  54. // and so does not pass dataObject
  55. // still need to test against _lastQuery in case it came too late
  56. if((dataObject && dataObject.query[this.searchAttr] != this._lastQuery) || (!dataObject && result.length && this.store.getIdentity(result[0]) != this._lastQuery)){
  57. return;
  58. }
  59. if(!result.length){
  60. //#3268: do nothing on bad input
  61. //#3285: change CSS to indicate error
  62. this.valueNode.value = "";
  63. dijit.form.TextBox.superclass._setValueAttr.call(this, "", priorityChange || (priorityChange === undefined && !this._focused));
  64. this._isvalid = false;
  65. this.validate(this._focused);
  66. this.item = null;
  67. }else{
  68. this.set('item', result[0], priorityChange);
  69. }
  70. },
  71. _openResultList: function(/*Object*/ results, /*Object*/ dataObject){
  72. // Overrides ComboBox._openResultList()
  73. // #3285: tap into search callback to see if user's query resembles a match
  74. if(dataObject.query[this.searchAttr] != this._lastQuery){
  75. return;
  76. }
  77. if(this.item === undefined){ // item == undefined for keyboard search
  78. this._isvalid = results.length != 0 || this._maxOptions != 0; // result.length==0 && maxOptions != 0 implies the nextChoices item selected but then the datastore returned 0 more entries
  79. this.validate(true);
  80. }
  81. dijit.form.ComboBoxMixin.prototype._openResultList.apply(this, arguments);
  82. },
  83. _getValueAttr: function(){
  84. // summary:
  85. // Hook for attr('value') to work.
  86. // don't get the textbox value but rather the previously set hidden value.
  87. // Use this.valueNode.value which isn't always set for other MappedTextBox widgets until blur
  88. return this.valueNode.value;
  89. },
  90. _getValueField: function(){
  91. // Overrides ComboBox._getValueField()
  92. return "value";
  93. },
  94. _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange){
  95. // summary:
  96. // Hook so attr('value', value) works.
  97. // description:
  98. // Sets the value of the select.
  99. // Also sets the label to the corresponding value by reverse lookup.
  100. if(!this._onChangeActive){ priorityChange = null; }
  101. this._lastQuery = value;
  102. if(value === null || value === ''){
  103. this._setDisplayedValueAttr('', priorityChange);
  104. return;
  105. }
  106. //#3347: fetchItemByIdentity if no keyAttr specified
  107. var self = this;
  108. this.store.fetchItemByIdentity({
  109. identity: value,
  110. onItem: function(item){
  111. self._callbackSetLabel(item? [item] : [], undefined, priorityChange);
  112. }
  113. });
  114. },
  115. _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
  116. // summary:
  117. // Set the displayed valued in the input box, and the hidden value
  118. // that gets submitted, based on a dojo.data store item.
  119. // description:
  120. // Users shouldn't call this function; they should be calling
  121. // attr('item', value)
  122. // tags:
  123. // private
  124. this._isvalid = true;
  125. this.inherited(arguments);
  126. this.valueNode.value = this.value;
  127. this._lastDisplayedValue = this.textbox.value;
  128. },
  129. _getDisplayQueryString: function(/*String*/ text){
  130. return text.replace(/([\\\*\?])/g, "\\$1");
  131. },
  132. _setDisplayedValueAttr: function(/*String*/ label, /*Boolean?*/ priorityChange){
  133. // summary:
  134. // Hook so attr('displayedValue', label) works.
  135. // description:
  136. // Sets textbox to display label. Also performs reverse lookup
  137. // to set the hidden value.
  138. // When this is called during initialization it'll ping the datastore
  139. // for reverse lookup, and when that completes (after an XHR request)
  140. // will call setValueAttr()... but that shouldn't trigger an onChange()
  141. // event, even when it happens after creation has finished
  142. if(!this._created){
  143. priorityChange = false;
  144. }
  145. if(this.store){
  146. this._hideResultList();
  147. var query = dojo.clone(this.query); // #6196: populate query with user-specifics
  148. // escape meta characters of dojo.data.util.filter.patternToRegExp().
  149. this._lastQuery = query[this.searchAttr] = this._getDisplayQueryString(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 set the
  152. // textbox value now so that the impending warning will make
  153. // sense to the user
  154. this.textbox.value = label;
  155. this._lastDisplayedValue = label;
  156. var _this = this;
  157. var fetch = {
  158. query: query,
  159. queryOptions: {
  160. ignoreCase: this.ignoreCase,
  161. deep: true
  162. },
  163. onComplete: function(result, dataObject){
  164. _this._fetchHandle = null;
  165. dojo.hitch(_this, "_callbackSetLabel")(result, dataObject, priorityChange);
  166. },
  167. onError: function(errText){
  168. _this._fetchHandle = null;
  169. console.error('dijit.form.FilteringSelect: ' + errText);
  170. dojo.hitch(_this, "_callbackSetLabel")([], undefined, false);
  171. }
  172. };
  173. dojo.mixin(fetch, this.fetchProperties);
  174. this._fetchHandle = this.store.fetch(fetch);
  175. }
  176. },
  177. postMixInProperties: function(){
  178. this.inherited(arguments);
  179. this._isvalid = !this.required;
  180. },
  181. undo: function(){
  182. this.set('displayedValue', this._lastDisplayedValue);
  183. }
  184. }
  185. );