Changeset 8401
- Timestamp:
- 05/02/07 12:51:12 (21 months ago)
- Location:
- dijit/trunk
- Files:
-
- 1 added
- 5 modified
-
form/AutoCompleter.js (modified) (27 diffs)
-
form/Select.js (modified) (11 diffs)
-
form/templates/AutoCompleter.html (modified) (1 diff)
-
form/_DropDownTextBox.js (modified) (2 diffs)
-
tests/form/test_AutoCompleter_destroy.html (added)
-
tests/form/test_Select.html (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
dijit/trunk/form/AutoCompleter.js
r8355 r8401 11 11 [dijit.form._DropDownTextBox], 12 12 { 13 // summary: 14 // Auto-completing text box, and base class for Select widget. 15 // 16 // The drop down box's values are populated from an class called 17 // a data provider, which returns a list of values based on the characters 18 // that the user has typed into the input box. 19 // 20 // Some of the options to the AutoCompleter are actually arguments to the data 21 // provider. 22 23 // Fixes #2313, #2562, #2790, #2883, #2884. 24 25 // searchLimit: Integer 26 // Argument to data provider. 27 // Specifies cap on maximum number of search results. 28 // Default is Infinity. 29 searchLimit: Infinity, 30 31 // store: Object 32 // Reference to data provider object created for this AutoCompleter 33 // according to "dataProviderClass" argument. 34 store: null, 35 36 // autoComplete: Boolean 37 // If you type in a partial string, and then tab out of the <input> box, 38 // automatically copy the first entry displayed in the drop down list to 39 // the <input> field 40 autoComplete: true, 41 42 // searchDelay: Integer 43 // Delay in milliseconds between when user types something and we start 44 // searching based on that value 45 searchDelay: 100, 46 47 // url: String 48 // URL argument passed to data provider object (class name specified in "dataProviderClass") 49 // An example of the URL format for the default data provider is 50 // "autoCompleterData.js" 51 url: "", 52 53 // fadeTime: Integer 54 // Milliseconds duration of fadeout for drop down box 55 fadeTime: 200, 56 57 // maxListLength: Integer 58 // Limits list to X visible rows, scroll on rest 59 maxListLength: 8, 60 61 // dataProviderClass: String 62 // Name of data provider class (code that maps a search string to a list of values) 63 // The class must match the interface demonstrated by dojo.data.JsonItemStore 64 dataProviderClass: "dojo.data.JsonItemStore", 65 66 // searchField: String 67 // Searches pattern match against this field 68 searchField: "name", 69 70 // size: String 71 // Basic input tag size declaration. 72 size: "", 73 74 // maxlength: String 75 // Basic input tag maxlength declaration. 76 maxlength: "", 77 78 // ignoreCase: Boolean 79 // Is the AutoCompleter menu case sensitive? 80 ignoreCase: true, 81 82 // value: String 83 // The initial value of the AutoCompleter. 84 // This is the value that actually appears in the text area. 85 86 templatePath: dojo.moduleUrl("dijit.form", "templates/AutoCompleter.html"), 87 88 _setTextFieldValue:function(/*String*/ value){ 89 // summary: Select wants to call AutoCompleter's setValue to reach FormElement's setValue 90 // But Select does not want to display the value in the text field! 91 // this function fixes that problem by separating the code 92 this.textInputNode.value=value; 93 }, 94 setValue:function(/*String*/ value){ 95 // summary: Sets the value of the AutoCompleter 96 this._setTextFieldValue(value); 97 console.log(value); 98 // reuse dijit setValue code 99 dijit.form.AutoCompleter.superclass.setValue.apply(this, arguments); 100 }, 101 102 getState: function(){ 13 103 // summary: 14 // Auto-completing text box, and base class for Select widget. 15 // 16 // The drop down box's values are populated from an class called 17 // a data provider, which returns a list of values based on the characters 18 // that the user has typed into the input box. 19 // 20 // Some of the options to the AutoCompleter are actually arguments to the data 21 // provider. 22 23 // searchLimit: Integer 24 // Argument to data provider. 25 // Specifies cap on maximum number of search results. 26 // Default is Infinity. 27 searchLimit: Infinity, 28 29 // store: Object 30 // Reference to data provider object created for this AutoCompleter 31 // according to "dataProviderClass" argument. 32 store: null, 33 34 // autoComplete: Boolean 35 // If you type in a partial string, and then tab out of the <input> box, 36 // automatically copy the first entry displayed in the drop down list to 37 // the <input> field 38 autoComplete: true, 39 40 // searchDelay: Integer 41 // Delay in milliseconds between when user types something and we start 42 // searching based on that value 43 searchDelay: 100, 44 45 // url: String 46 // URL argument passed to data provider object (class name specified in "dataProviderClass") 47 // An example of the URL format for the default data provider is 48 // "autoCompleterData.js" 49 url: "", 50 51 // fadeTime: Integer 52 // Milliseconds duration of fadeout for drop down box 53 fadeTime: 200, 54 55 // maxListLength: Integer 56 // Limits list to X visible rows, scroll on rest 57 maxListLength: 8, 58 59 // mode: String 60 // Mode must be specified unless dataProviderClass is specified. 61 // "local" to inline search string, "remote" for JSON-returning live search 62 // or "html" for dumber live search. 63 mode: "local", 64 65 // selectedResult: Object 66 // (Read only) object specifying the value/label that the user selected 67 selectedResult: null, 68 69 // dataProviderClass: String 70 // Name of data provider class (code that maps a search string to a list of values) 71 // The class must match the interface demonstrated by dojo.data.JsonItemStore 72 dataProviderClass: "dojo.data.JsonItemStore", 73 74 // dropdownToggle: String 75 // Animation effect for showing/displaying drop down box 76 dropdownToggle: "fade", 77 78 // searchField: String 79 // Searches pattern match against this field 80 searchField: "name", 81 82 // labelField: String 83 // The text that actually appears 84 labelField: "name", 85 86 // labelType: String 87 // "html" or "text" 88 labelType: "text", 89 90 // size: String 91 // Basic input tag size declaration. 92 size: "", 93 94 // maxlength: String 95 // Basic input tag maxlength declaration. 96 maxlength: "", 97 98 // value: String 99 // The initial value of the AutoCompleter. 100 // This is the value that actually appears in the text area. 101 102 templatePath: dojo.moduleUrl("dijit.form", "templates/AutoCompleter.html"), 103 104 105 _prevValue:null, 106 _checkValueChanged: function(){ 107 this._arrowIdle(); 108 var value = this.comboBoxValue.value; 109 if(this._prevValue != value){ 110 this._prevValue = value; 111 // only change state and value if a new value is set 112 //dojo.widget.html.stabile.setState(this.id, this.getState(), true); 113 this.onValueChanged(value); 114 } 115 }, 116 setValue:function(/*String*/ value){ 117 // summary: Sets the value of the AutoCompleter 118 this.comboBoxValue.value = value; 119 if(this.textInputNode.value != value){ // prevent mucking up of selection 120 this.textInputNode.value = value; 121 this._checkValueChanged(); 122 } 123 }, 124 125 onValueChanged: function(/*String*/ value){ 126 // summary: callback when value changes, for user to attach to 127 }, 128 129 getValue: function(){ 130 // summary: Returns combo box value 131 this._checkValueChanged(); 132 return this.comboBoxValue.value; 133 }, 134 labelFunc: function(/*String*/ label){ 135 // summary: Event handler called when the label changes 136 // returns the label that the AutoCompleter should display 137 return label; 138 }, 139 140 getState: function(){ 141 // summary: 142 // Used for saving state of AutoCompleter when navigates to a new 143 // page, in case they then hit the browser's "Back" button. 104 // Used for saving state of AutoCompleter when navigates to a new 105 // page, in case they then hit the browser's "Back" button. 144 106 var state={}; 145 107 //state[this.keyField]=this.getValue(); … … 150 112 151 113 setState: function(/*Object*/ state){ 152 // summary:153 // Used for restoring state of AutoCompleter when has navigated to a new154 // page but then hits browser's "Back" button.155 //this.setValue(state[this.keyField]);114 // summary: 115 // Used for restoring state of AutoCompleter when has navigated to a new 116 // page but then hits browser's "Back" button. 117 //this.setValue(state[this.keyField]); 156 118 this.setValue(state[this.searchField]); 157 //this.setSelectedValue(state[this.searchField]);119 //this.setSelectedValue(state[this.searchField]); 158 120 }, 159 121 … … 169 131 170 132 _getCaretPos: function(/*DomNode*/ element){ 171 // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22133 // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22 172 134 if(typeof(element.selectionStart)=="number"){ 173 135 // FIXME: this is totally borked on Moz < 1.3. Any recourse? 174 136 return element.selectionStart; 175 137 }else if(dojo.isIE){ 176 // in the case of a mouse click in a popup being handled,177 // then the document.selection is not the textarea, but the popup178 // var r = document.selection.createRange();179 // hack to get IE 6 to play nice. What a POS browser.138 // in the case of a mouse click in a popup being handled, 139 // then the document.selection is not the textarea, but the popup 140 // var r = document.selection.createRange(); 141 // hack to get IE 6 to play nice. What a POS browser. 180 142 var tr = document.selection.createRange().duplicate(); 181 143 var ntr = element.createTextRange(); … … 183 145 ntr.move("character",0); 184 146 try{ 185 // If control doesnt have focus, you get an exception.186 // Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).187 // There appears to be no workaround for this - googled for quite a while.147 // If control doesnt have focus, you get an exception. 148 // Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes). 149 // There appears to be no workaround for this - googled for quite a while. 188 150 ntr.setEndPoint("EndToEnd", tr); 189 151 return String(ntr.text).replace(/\r/g,"").length; … … 202 164 _setSelectedRange: function(/*DomNode*/ element, /*Number*/ start, /*Number*/ end){ 203 165 if(!end){ end = element.value.length; } // NOTE: Strange - should be able to put caret at start of text? 204 // Mozilla205 // parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130166 // Mozilla 167 // parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130 206 168 if(element.setSelectionRange){ 207 169 element.focus(); … … 216 178 } 217 179 }else{ //otherwise try the event-creation hack (our own invention) 218 // do we need these?180 // do we need these? 219 181 element.value = element.value; 220 182 element.blur(); … … 233 195 234 196 _handleKeyEvents: function(/*Event*/ evt){ 235 // summary: handles keyboard events197 // summary: handles keyboard events 236 198 if(evt.ctrlKey || evt.altKey){ return; } 237 199 238 // reset these200 // reset these 239 201 this._prev_key_backspace = false; 240 202 this._prev_key_esc = false; … … 242 204 var k = dojo.keys; 243 205 var doSearch = true; 244 try{245 206 switch(evt.keyCode){ 246 207 case dojo.keys.DOWN_ARROW: … … 313 274 if(!this.textInputNode.value.length){ 314 275 this.setValue(""); 315 this._hideResultList();316 doSearch = false;276 //this._hideResultList(); 277 //doSearch = false; 317 278 } 318 279 //} … … 330 291 } 331 292 } 332 }333 catch(e){334 console.log("Error in AutoCompleter._handleKeyEvents, while pressing "+evt.keyCode+":"+e.message);335 }336 293 if(this.searchTimer){ 337 294 clearTimeout(this.searchTimer); 338 295 } 339 296 if(doSearch){ 340 // if we have gotten this far we dont want to keep our highlight297 // if we have gotten this far we dont want to keep our highlight 341 298 this._blurOptionNode(); 342 299 343 // need to wait a tad before start search so that the event bubbles through DOM and we have value visible300 // need to wait a tad before start search so that the event bubbles through DOM and we have value visible 344 301 this.searchTimer = setTimeout(dojo.hitch(this, this._startSearchFromInput), this.searchDelay); 345 302 } … … 347 304 348 305 compositionEnd: function(/*Event*/ evt){ 349 // summary: When inputting characters using an input method, such as Asian350 // languages, it will generate this event instead of onKeyDown event306 // summary: When inputting characters using an input method, such as Asian 307 // languages, it will generate this event instead of onKeyDown event 351 308 evt.key = evt.charCode = -1; 352 309 this._handleKeyEvents(evt); … … 354 311 355 312 _onKeyUp: function(/*Event*/ evt){ 356 // summary: callback on key up event313 // summary: callback on key up event 357 314 this.setValue(this.textInputNode.value); 358 315 }, 359 316 360 361 317 _focusOptionNode: function(/*DomNode*/ node){ 362 // summary: does the actual highlight318 // summary: does the actual highlight 363 319 if(this._highlighted_option != node){ 364 320 this._blurOptionNode(); … … 370 326 371 327 _blurOptionNode: function(){ 372 // sumary: removes highlight on highlighted328 // summary: removes highlight on highlighted 373 329 if(this._highlighted_option){ 374 330 this._removeClass(this._highlighted_option, "dojoMenuItemHover"); … … 432 388 } 433 389 } 434 var even = true;435 390 while(results.length){ 436 391 var tr = results.shift(); … … 438 393 var td=this._createOption(tr); 439 394 td.className = "dojoMenuItem"; 440 even = (!even);441 395 this.optionsListNode.appendChild(td); 442 396 } … … 447 401 this._showResultList(); 448 402 }, 403 449 404 _createOption:function(/*Object*/ tr){ 450 // summary: creates an option to appear on the popup menu405 // summary: creates an option to appear on the popup menu 451 406 var td = document.createElement("div"); 452 if(this.labelType=="text"){ 453 td.appendChild(document.createTextNode(tr[this.labelField])); 454 }else if(this.labelType=="html"){ 455 td.innerHTML=tr[this.labelField]; 456 } 457 td.setAttribute("resultName", tr[this.searchField]); 458 //td.setAttribute("resultValue", tr[this.keyField]); 407 td.appendChild(document.createTextNode(tr[this.searchField])); 408 409 td[this.searchField]=tr[this.searchField]; 459 410 return td; 460 411 }, 412 461 413 _onFocusInput: function(){ 462 414 this._hasFocus = true; 463 464 415 }, 465 416 466 417 _onBlurInput: function(){ 467 try{418 468 419 this._hasFocus = false; 469 420 this._handleBlurTimer(true, 500); 470 } 471 catch(e){ 472 console.log("_onBlurInput:"+e); 473 } 421 474 422 }, 475 423 476 424 _handleBlurTimer: function(/*Boolean*/clear, /*Number*/ millisec){ 477 // summary: collect all blur timers issues here478 479 try{425 // summary: collect all blur timers issues here 426 427 480 428 if(this.blurTimer && (clear || millisec)){ 481 429 clearTimeout(this.blurTimer); … … 485 433 this.blurTimer = setTimeout(dojo.hitch(this, "_checkBlurred"), millisec); 486 434 } 487 } 488 catch(e){ 489 console.log("_handleBlurTimer:"+e); 490 } 435 491 436 }, 492 437 493 438 _onMouseOver: function(/*Event*/ evt){ 494 // summary: needed in IE and Safari as inputTextNode loses focus when scrolling optionslist439 // summary: needed in IE and Safari as inputTextNode loses focus when scrolling optionslist 495 440 if(!this._mouseover_list){ 496 441 this._handleBlurTimer(true, 0); … … 500 445 501 446 _onMouseOut:function(/*Event*/ evt){ 502 // summary: needed in IE and Safari as inputTextNode loses focus when scrolling optionslist447 // summary: needed in IE and Safari as inputTextNode loses focus when scrolling optionslist 503 448 var relTarget = evt.relatedTarget; 504 try{ // fixes #1807449 505 450 if(!relTarget || relTarget.parentNode != this.optionsListNode){ 506 451 this._mouseover_list = false; … … 508 453 this.focus(); 509 454 } 510 }catch(e){ 511 console.log("Error in _onMouseOut: "+e.message); 512 } 455 513 456 }, 514 457 … … 516 459 _checkBlurred: function(){ 517 460 518 try{461 519 462 if(!this._hasFocus && !this._mouseover_list){ 520 463 this._hideResultList(); 521 this._checkValueChanged(); 522 } 523 } 524 catch(e){ 525 console.log("_checkBlurred"+e); 526 } 464 //this._checkValueChanged(); 465 } 466 527 467 }, 528 468 … … 533 473 evt = { target: (this._highlighted_option ? this._highlighted_option:this.optionsListNode.firstChild) }; 534 474 } 535 // TODO: bring back this code536 // dojo.html does not exist537 475 if(evt.target.parentNode!=this.optionsListNode){ 538 try{476 539 477 // handle autocompletion where the the user has hit ENTER or TAB 540 478 // if the input is empty do nothing 541 479 if(!this.textInputNode.value.length){ 542 this._checkValueChanged();480 //this._checkValueChanged(); 543 481 return; 544 482 } 545 483 tgt = this.optionsListNode.firstChild; 546 484 // user has input value not in option list 547 if(!tgt || !this._isInputEqualToResult(tgt.getAttribute("resultName"))){548 this. _checkValueChanged();485 /*if(!tgt || !this._isInputEqualToResult(tgt[this.searchField])){ 486 this.setValue(); 549 487 return; 550 } 551 } 552 catch(e){ 553 console.log("Error in ComboBox._selectOption: "+e.message); 554 } 555 // otherwise the user has accepted the autocompleted value 488 }*/ 489 490 // otherwise the user has accepted the autocompleted value 556 491 }else{ 557 492 tgt = evt.target; 558 493 } 559 while((tgt.nodeType!=1)||(!tgt .getAttribute("resultName"))){494 while((tgt.nodeType!=1)||(!tgt[this.searchField])){ 560 495 tgt = tgt.parentNode; 561 496 if(tgt == dojo.body()){ 562 this._checkValueChanged();497 //this._checkValueChanged(); 563 498 return false; 564 499 } … … 569 504 this._setSelectedRange(this.textInputNode, 0, null); 570 505 } 571 this._checkValueChanged();506 //this._checkValueChanged(); 572 507 this.focus(); 573 574 }, 575 _isInputEqualToResult: function(/*String*/ result){ 576 &nb