Changeset 8401

Show
Ignore:
Timestamp:
05/02/07 12:51:12 (21 months ago)
Author:
doughays
Message:

Fixes #2313, #2562, #2883, #2884 (proxy commit of changes made by haysmark).
try/catch blocks removed.
New queryIgnoreCase added.
labelFunc now takes a dojo.data item instead of a string.
hidden input tag removed from autocompleter template.

Location:
dijit/trunk
Files:
1 added
5 modified

Legend:

Unmodified
Added
Removed
  • dijit/trunk/form/AutoCompleter.js

    r8355 r8401  
    1111        [dijit.form._DropDownTextBox], 
    1212{ 
     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(){ 
    13103                // 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. 
    144106                var state={}; 
    145107                        //state[this.keyField]=this.getValue(); 
     
    150112 
    151113        setState: function(/*Object*/ state){ 
    152                         // summary: 
    153                         //      Used for restoring state of AutoCompleter when has navigated to a new 
    154                         //      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]); 
    156118                this.setValue(state[this.searchField]); 
    157                         //this.setSelectedValue(state[this.searchField]); 
     119                //this.setSelectedValue(state[this.searchField]); 
    158120        }, 
    159121 
     
    169131 
    170132        _getCaretPos: function(/*DomNode*/ element){ 
    171                         // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22 
     133                // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22 
    172134                if(typeof(element.selectionStart)=="number"){ 
    173135                                // FIXME: this is totally borked on Moz < 1.3. Any recourse? 
    174136                        return element.selectionStart; 
    175137                }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 popup 
    178                                 // 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. 
    180142                        var tr = document.selection.createRange().duplicate(); 
    181143                        var ntr = element.createTextRange(); 
     
    183145                        ntr.move("character",0); 
    184146                        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. 
    188150                                ntr.setEndPoint("EndToEnd", tr); 
    189151                                return String(ntr.text).replace(/\r/g,"").length; 
     
    202164        _setSelectedRange: function(/*DomNode*/ element, /*Number*/ start, /*Number*/ end){ 
    203165                if(!end){ end = element.value.length; }  // NOTE: Strange - should be able to put caret at start of text? 
    204                         // Mozilla 
    205                         // parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130 
     166                // Mozilla 
     167                // parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130 
    206168                if(element.setSelectionRange){ 
    207169                        element.focus(); 
     
    216178                        } 
    217179                }else{ //otherwise try the event-creation hack (our own invention) 
    218                                 // do we need these? 
     180                        // do we need these? 
    219181                        element.value = element.value; 
    220182                        element.blur(); 
     
    233195 
    234196        _handleKeyEvents: function(/*Event*/ evt){ 
    235                         // summary: handles keyboard events 
     197                // summary: handles keyboard events 
    236198                if(evt.ctrlKey || evt.altKey){ return; } 
    237199 
    238                         // reset these 
     200                // reset these 
    239201                this._prev_key_backspace = false; 
    240202                this._prev_key_esc = false; 
     
    242204                var k = dojo.keys; 
    243205                var doSearch = true; 
    244                 try{ 
    245206                        switch(evt.keyCode){ 
    246207                                case dojo.keys.DOWN_ARROW: 
     
    313274                                                if(!this.textInputNode.value.length){ 
    314275                                                        this.setValue(""); 
    315                                                         this._hideResultList(); 
    316                                                         doSearch = false; 
     276                                                        //this._hideResultList(); 
     277                                                        //doSearch = false; 
    317278                                                } 
    318279                                        //} 
     
    330291                                        } 
    331292                        } 
    332                 } 
    333                 catch(e){ 
    334                         console.log("Error in AutoCompleter._handleKeyEvents, while pressing "+evt.keyCode+":"+e.message); 
    335                 } 
    336293                if(this.searchTimer){ 
    337294                        clearTimeout(this.searchTimer); 
    338295                } 
    339296                if(doSearch){ 
    340                                 // if we have gotten this far we dont want to keep our highlight 
     297                        // if we have gotten this far we dont want to keep our highlight 
    341298                        this._blurOptionNode(); 
    342299 
    343                                 // need to wait a tad before start search so that the event bubbles through DOM and we have value visible 
     300                        // need to wait a tad before start search so that the event bubbles through DOM and we have value visible 
    344301                        this.searchTimer = setTimeout(dojo.hitch(this, this._startSearchFromInput), this.searchDelay); 
    345302                } 
     
    347304 
    348305        compositionEnd: function(/*Event*/ evt){ 
    349                         // summary: When inputting characters using an input method, such as Asian 
    350                         // languages, it will generate this event instead of onKeyDown event 
     306                // summary: When inputting characters using an input method, such as Asian 
     307                // languages, it will generate this event instead of onKeyDown event 
    351308                evt.key = evt.charCode = -1; 
    352309                this._handleKeyEvents(evt); 
     
    354311 
    355312        _onKeyUp: function(/*Event*/ evt){ 
    356                         // summary: callback on key up event 
     313                // summary: callback on key up event 
    357314                this.setValue(this.textInputNode.value); 
    358315        }, 
    359316 
    360  
    361317        _focusOptionNode: function(/*DomNode*/ node){ 
    362                         // summary: does the actual highlight 
     318                // summary: does the actual highlight 
    363319                if(this._highlighted_option != node){ 
    364320                        this._blurOptionNode(); 
     
    370326 
    371327        _blurOptionNode: function(){ 
    372                         // sumary: removes highlight on highlighted 
     328                // summary: removes highlight on highlighted 
    373329                if(this._highlighted_option){ 
    374330                        this._removeClass(this._highlighted_option, "dojoMenuItemHover"); 
     
    432388                                } 
    433389                } 
    434                 var even = true; 
    435390                while(results.length){ 
    436391                        var tr = results.shift(); 
     
    438393                                var td=this._createOption(tr); 
    439394                                td.className = "dojoMenuItem"; 
    440                                 even = (!even); 
    441395                                this.optionsListNode.appendChild(td); 
    442396                        } 
     
    447401                this._showResultList(); 
    448402        }, 
     403 
    449404        _createOption:function(/*Object*/ tr){ 
    450                         // summary: creates an option to appear on the popup menu 
     405                // summary: creates an option to appear on the popup menu 
    451406                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]; 
    459410                return td; 
    460411        }, 
     412 
    461413        _onFocusInput: function(){ 
    462414                this._hasFocus = true; 
    463  
    464415        }, 
    465416 
    466417        _onBlurInput: function(){ 
    467                 try{ 
     418                 
    468419                        this._hasFocus = false; 
    469420                        this._handleBlurTimer(true, 500); 
    470                 } 
    471                 catch(e){ 
    472                         console.log("_onBlurInput:"+e); 
    473                 } 
     421                 
    474422        }, 
    475423 
    476424        _handleBlurTimer: function(/*Boolean*/clear, /*Number*/ millisec){ 
    477                         // summary: collect all blur timers issues here 
    478                          
    479                 try{ 
     425                // summary: collect all blur timers issues here 
     426                         
     427                 
    480428                        if(this.blurTimer && (clear || millisec)){ 
    481429                                clearTimeout(this.blurTimer); 
     
    485433                                this.blurTimer = setTimeout(dojo.hitch(this, "_checkBlurred"), millisec); 
    486434                        } 
    487                 } 
    488                 catch(e){ 
    489                         console.log("_handleBlurTimer:"+e); 
    490                 } 
     435                 
    491436        }, 
    492437 
    493438        _onMouseOver: function(/*Event*/ evt){ 
    494                         // summary: needed in IE and Safari as inputTextNode loses focus when scrolling optionslist 
     439                // summary: needed in IE and Safari as inputTextNode loses focus when scrolling optionslist 
    495440                if(!this._mouseover_list){ 
    496441                        this._handleBlurTimer(true, 0); 
     
    500445 
    501446        _onMouseOut:function(/*Event*/ evt){ 
    502                         // summary: needed in IE and Safari as inputTextNode loses focus when scrolling optionslist 
     447                // summary: needed in IE and Safari as inputTextNode loses focus when scrolling optionslist 
    503448                var relTarget = evt.relatedTarget; 
    504                 try{ // fixes #1807 
     449                 
    505450                        if(!relTarget || relTarget.parentNode != this.optionsListNode){ 
    506451                                this._mouseover_list = false; 
     
    508453                                this.focus(); 
    509454                        } 
    510                 }catch(e){ 
    511                         console.log("Error in _onMouseOut: "+e.message); 
    512                 } 
     455                 
    513456        }, 
    514457 
     
    516459        _checkBlurred: function(){ 
    517460                         
    518                 try{ 
     461                 
    519462                        if(!this._hasFocus && !this._mouseover_list){ 
    520463                                this._hideResultList(); 
    521                                 this._checkValueChanged(); 
    522                         } 
    523                 } 
    524                 catch(e){ 
    525                         console.log("_checkBlurred"+e); 
    526                 } 
     464                                //this._checkValueChanged(); 
     465                        } 
     466                 
    527467        }, 
    528468 
     
    533473                        evt = { target: (this._highlighted_option ? this._highlighted_option:this.optionsListNode.firstChild) }; 
    534474                } 
    535                 // TODO: bring back this code 
    536                 // dojo.html does not exist      
    537475                if(evt.target.parentNode!=this.optionsListNode){ 
    538                         try{ 
     476                         
    539477                                // handle autocompletion where the the user has hit ENTER or TAB 
    540478                                // if the input is empty do nothing 
    541479                                if(!this.textInputNode.value.length){ 
    542                                         this._checkValueChanged(); 
     480                                        //this._checkValueChanged(); 
    543481                                        return; 
    544482                                } 
    545483                                tgt = this.optionsListNode.firstChild; 
    546484                                // 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(); 
    549487                                        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 
    556491                }else{ 
    557492                        tgt = evt.target; 
    558493                } 
    559                 while((tgt.nodeType!=1)||(!tgt.getAttribute("resultName"))){ 
     494                while((tgt.nodeType!=1)||(!tgt[this.searchField])){ 
    560495                        tgt = tgt.parentNode; 
    561496                        if(tgt == dojo.body()){ 
    562                                 this._checkValueChanged(); 
     497                                //this._checkValueChanged(); 
    563498                                return false; 
    564499                        } 
     
    569504                        this._setSelectedRange(this.textInputNode, 0, null); 
    570505                } 
    571                 this._checkValueChanged(); 
     506                //this._checkValueChanged(); 
    572507                this.focus(); 
    573  
    574         }, 
    575         _isInputEqualToResult: function(/*String*/ result){ 
    576 &nb