Changeset 13456

Show
Ignore:
Timestamp:
04/29/08 13:02:26 (9 months ago)
Author:
toonetown
Message:

fixes #5639, refs #6416: added filtering to the timepicker and up/down arrow support for the time picker as well. also some minor theme fixes !strict

Location:
dijit/trunk
Files:
6 modified

Legend:

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

    r13124 r13456  
    9191                                this._picker = new PopupProto({ 
    9292                                        onValueSelected: function(value){ 
    93  
    94                                                 textBox.focus(); // focus the textbox before the popup closes to avoid reopening the popup 
     93                                                if(textBox._tabbingAway){ 
     94                                                        delete textBox._tabbingAway; 
     95                                                }else{ 
     96                                                        textBox.focus(); // focus the textbox before the popup closes to avoid reopening the popup 
     97                                                } 
    9598                                                setTimeout(dojo.hitch(textBox, "_close"), 1); // allow focus time to take 
    9699 
     
    161164 
    162165                _onKeyPress: function(/*Event*/e){ 
    163                         if(dijit.form._DateTimeTextBox.superclass._onKeyPress.apply(this, arguments)){ 
    164                                 if(this._opened && e.keyCode == dojo.keys.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){ 
    165                                         this._close(); 
    166                                         dojo.stopEvent(e); 
     166                        var p = this._picker, dk = dojo.keys; 
     167                        // Handle the key in the picker, if it has a handler.  If the handler 
     168                        // returns false, then don't handle any other keys. 
     169                        if(p && this._opened && p.handleKey){ 
     170                                if(p.handleKey(e) === false){ return; } 
     171                        } 
     172                        if(this._opened && e.keyCode == dk.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){ 
     173                                this._close(); 
     174                                dojo.stopEvent(e); 
     175                        }else if(!this._opened && e.keyCode == dk.DOWN_ARROW){ 
     176                                this._open(); 
     177                                dojo.stopEvent(e); 
     178                        }else if(dijit.form._DateTimeTextBox.superclass._onKeyPress.apply(this, arguments)){ 
     179                                if(e.keyCode == dk.TAB){ 
     180                                        this._tabbingAway = true; 
     181                                }else if(this._opened && (e.keyChar || e.keyCode == dk.BACKSPACE || e.keyCode == dk.DELETE)){ 
     182                                        // Replace the element - but do it after a delay to allow for  
     183                                        // filtering to occur 
     184                                        setTimeout(dojo.hitch(this, function(){ 
     185                                                dijit.placeOnScreenAroundElement(p.domNode.parentNode, this.domNode, {'BL':'TL', 'TL':'BL'}, p.orient ? dojo.hitch(p, "orient") : null); 
     186                                        }), 1); 
    167187                                } 
    168188                        } 
  • dijit/trunk/tests/form/test_TimeTextBox.html

    r13450 r13456  
    121121        </div> 
    122122 
     123        <div class="dojoTitlePaneLabel"> 
     124                <label for="q6">Initially empty time text box</label> 
     125                <span class="noticeMessage">TimeTextBox class, 
     126                        Attributes: {formatLength:'medium'}</span> 
     127        </div> 
     128        <div class="testExample"> 
     129                <input id="q6" type="text" name="time6" class="medium" 
     130                        dojoType="dijit.form.TimeTextBox" 
     131                        constraints="{formatLength:'medium'}" 
     132                        required="true" 
     133                        onChange="dojo.byId('oc6').value=arguments[0]" 
     134                        invalidMessage="Invalid time." /> 
     135                onChange:<input id="oc6" size="34" disabled value="not fired yet!" autocomplete="off"> 
     136        </div> 
     137 
    123138        <script> 
    124139                function displayData() { 
  • dijit/trunk/themes/nihilo/TimePicker.css

    r13266 r13456  
    2525} 
    2626 
    27 .nihilo .dijitTimePickerItemHover { 
     27.nihilo .dijitTimePickerItemHover, 
     28.nihilo .dijitTimePickerItemSelected { 
    2829        position: relative; 
    2930        z-index: 10; 
     
    3132 
    3233.nihilo .dijitTimePickerTick .dijitTimePickerItemInner { 
    33         font-size:0.25em; 
     34        font-size:0.4em; 
    3435} 
    3536 
    36 .nihilo .dijitTimePickerItemHover .dijitTimePickerItemInner { 
     37.nihilo .dijitTimePickerItemHover .dijitTimePickerItemInner, 
     38.nihilo .dijitTimePickerItemSelected .dijitTimePickerItemInner { 
    3739        font-size:1em; 
    3840} 
     
    4244} 
    4345 
    44 .nihilo .dijitTimePickerTickHover { 
    45         margin-top:-0.375em; 
    46         margin-bottom:-0.375em; 
     46.nihilo .dijitTimePickerTickHover, 
     47.nihilo .dijitTimePickerTickSelected { 
     48        margin-top:-0.3em; 
     49        margin-bottom:-0.3em; 
    4750        border-bottom: none; 
    4851} 
  • dijit/trunk/themes/soria/TimePicker.css

    r13266 r13456  
    2525} 
    2626 
    27 .soria .dijitTimePickerItemHover { 
     27.soria .dijitTimePickerItemHover, 
     28.soria .dijitTimePickerItemSelected { 
    2829        position: relative; 
    2930        z-index: 10; 
     
    3132 
    3233.soria .dijitTimePickerTick .dijitTimePickerItemInner { 
    33         font-size:0.25em; 
     34        font-size:0.4em; 
    3435} 
    3536 
    36 .soria .dijitTimePickerItemHover .dijitTimePickerItemInner { 
     37.soria .dijitTimePickerItemHover .dijitTimePickerItemInner, 
     38.soria .dijitTimePickerItemSelected .dijitTimePickerItemInner { 
    3739        font-size:1em; 
    3840} 
     
    4244} 
    4345 
    44 .soria .dijitTimePickerTickHover { 
    45         margin-top:-0.375em; 
    46         margin-bottom:-0.375em; 
     46.soria .dijitTimePickerTickHover, 
     47.soria .dijitTimePickerTickSelected { 
     48        margin-top:-0.3em; 
     49        margin-bottom:-0.3em; 
    4750        border-bottom: none; 
    4851} 
  • dijit/trunk/themes/tundra/TimePicker.css

    r13266 r13456  
    2525} 
    2626 
    27 .tundra .dijitTimePickerItemHover { 
     27.tundra .dijitTimePickerItemHover, 
     28.tundra .dijitTimePickerItemSelected { 
    2829        position: relative; 
    2930        z-index: 10; 
     
    3132 
    3233.tundra .dijitTimePickerTick .dijitTimePickerItemInner { 
    33         font-size:0.25em; 
     34        font-size:0.4em; 
    3435} 
    3536 
    36 .tundra .dijitTimePickerItemHover .dijitTimePickerItemInner { 
     37.tundra .dijitTimePickerItemHover .dijitTimePickerItemInner, 
     38.tundra .dijitTimePickerItemSelected .dijitTimePickerItemInner { 
    3739        font-size:1em; 
    3840} 
     
    4244} 
    4345 
    44 .tundra .dijitTimePickerTickHover { 
    45         margin-top:-0.375em; 
    46         margin-bottom:-0.375em; 
     46.tundra .dijitTimePickerTickHover, 
     47.tundra .dijitTimePickerTickSelected { 
     48        margin-top:-0.3em; 
     49        margin-bottom:-0.3em; 
    4750        border-bottom: none; 
    4851} 
  • dijit/trunk/_TimePicker.js

    r13450 r13456  
    8080 
    8181                serialize: dojo.date.stamp.toISOString, 
    82  
     82                 
     83                // _filterString: string 
     84                //              The string to filter by 
     85                _filterString: "", 
     86                 
    8387//TODOC: what is priority? 
    8488                setValue:function(/*Date*/ date, /*Boolean*/ priority){ 
     
    9296                }, 
    9397 
     98                onOpen: function(best){ 
     99                        if(this._beenOpened && this.domNode.parentNode){ 
     100                                // We've been opened before - so set our filter to to the 
     101                                // currently-displayed value (or empty string if it's already 
     102                                // valid) 
     103                                var p = dijit.byId(this.domNode.parentNode.dijitPopupParent); 
     104                                if(p){ 
     105                                        var val = p.getDisplayedValue(); 
     106                                        if(val && !p.parse(val, p.constraints)){ 
     107                                                this._filterString = val; 
     108                                        }else{ 
     109                                                this._filterString = ""; 
     110                                        } 
     111                                        this._showText(); 
     112                                } 
     113                        } 
     114                        this._beenOpened = true; 
     115                }, 
     116 
    94117                isDisabledDate: function(/*Date*/dateObject, /*String?*/locale){ 
    95118                        // summary: 
    96119                        //      May be overridden to disable certain dates in the TimePicker e.g. `isDisabledDate=dojo.date.locale.isWeekend` 
    97120                        return false; // Boolean 
     121                }, 
     122 
     123                _getFilteredNodes: function(/*number*/start, /*number*/maxNum, /*Boolean*/before){ 
     124                        // summary: 
     125                        //  Returns an array of nodes with the filter applied.  At most maxNum nodes 
     126                        //  will be returned - but fewer may be returned as well.  If the 
     127                        //  before parameter is set to true, then it will return the elements 
     128                        //  before the given index 
     129                        var nodes = [], n, i = start, max = this._maxIncrement + Math.abs(i), 
     130                                chk = before?-1:1, dec = before?1:0, inc = before?0:1; 
     131                        do{ 
     132                                i = i - dec; 
     133                                n = this._createOption(i); 
     134                                if(n){nodes.push(n);} 
     135                                i = i + inc; 
     136                        }while(nodes.length < maxNum && (i*chk) < max); 
     137                        if(before){ nodes.reverse(); } 
     138                        return nodes;  
    98139                }, 
    99140 
     
    126167                        // example: 01:00:00/00:15:00 -> display the time every 4 divs 
    127168                        this._visibleIncrement = visibleIncrementSeconds / clickableIncrementSeconds; 
    128                         for(var i = -(this._totalIncrements >> 1); i < (this._totalIncrements >> 1); i += this._clickableIncrement){ 
    129                                 this.timeMenu.appendChild(this._createOption(i)); 
    130                         } 
     169                        // divide the number of seconds in a day by the clickable increment in seconds to get the 
     170                        // absolute max number of increments. 
     171                        this._maxIncrement = (60 * 60 * 24) / clickableIncrementSeconds; 
     172 
     173                        // find the nodes we should display based on our filter 
     174                        var before = this._getFilteredNodes(0, this._totalIncrements >> 1, true); 
     175                        var after = this._getFilteredNodes(0, this._totalIncrements >> 1, false); 
     176                        if(before.length < this._totalIncrements >> 1){ 
     177                                before = before.slice(before.length / 2); 
     178                                after = after.slice(0, after.length / 2); 
     179                        } 
     180                        dojo.forEach(before.concat(after), function(n){this.timeMenu.appendChild(n);}, this); 
    131181                         
    132182                        // TODO: 
     
    156206                        typematic(this.upArrow,this,this._onArrowUp, 0.8, 500); 
    157207                        typematic(this.downArrow,this,this._onArrowDown, 0.8, 500); 
    158                         //dijit.typematic.addListener(this.upArrow,this.timeMenu, {keyCode:dojo.keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_onArrowUp", 0.8, 500); 
    159                         //dijit.typematic.addListener(this.downArrow, this.timeMenu, {keyCode:dojo.keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_onArrowDown", 0.8,500); 
    160208                         
    161209                        // Connect some callback functions to the hover event of the arrows 
     
    181229                _createOption:function(/*Number*/ index){ 
    182230                        // summary: creates a clickable time option 
    183                         var div = dojo.doc.createElement("div"); 
    184                         var date = (div.date = new Date(this._refDate)); 
    185                         div.index = index; 
     231                        var date = new Date(this._refDate); 
    186232                        var incrementDate = this._clickableIncrementDate; 
    187233                        date.setHours(date.getHours() + incrementDate.getHours() * index, 
    188234                                date.getMinutes() + incrementDate.getMinutes() * index, 
    189235                                date.getSeconds() + incrementDate.getSeconds() * index); 
    190  
     236                        var dateString = dojo.date.locale.format(date, this.constraints); 
     237                        if(this._filterString && dateString.toLowerCase().indexOf(this._filterString) !== 0){ 
     238                                // Doesn't match the filter - return null 
     239                                return null; 
     240                        } 
     241 
     242                        var div = dojo.doc.createElement("div"); 
     243                        div.date = date; 
     244                        div.index = index; 
    191245                        var innerDiv = dojo.doc.createElement('div'); 
    192246                        dojo.addClass(div,this.baseClass+"Item"); 
    193247                        dojo.addClass(innerDiv,this.baseClass+"ItemInner"); 
    194                         innerDiv.innerHTML = dojo.date.locale.format(date, this.constraints);                            
     248                        innerDiv.innerHTML = dateString; 
    195249                        div.appendChild(innerDiv); 
    196250 
     
    208262                                div.selected = true; 
    209263                                dojo.addClass(div, this.baseClass+"ItemSelected"); 
     264                                if(dojo.hasClass(div, this.baseClass+"Marker")){ 
     265                                        dojo.addClass(div, this.baseClass+"MarkerSelected"); 
     266                                }else{ 
     267                                        dojo.addClass(div, this.baseClass+"TickSelected"); 
     268                                } 
    210269                        } 
    211270                        return div; 
     
    215274                        var tdate = tgt.target.date || tgt.target.parentNode.date;                       
    216275                        if(!tdate || this.isDisabledDate(tdate)){ return; } 
     276                        this._highlighted_option = null; 
    217277                        this.setValue(tdate); 
    218278                        this.onValueSelected(tdate); 
     
    222282                }, 
    223283 
     284 
     285                _highlightOption: function(/*node*/node, /*Boolean*/ highlight){ 
     286                        if(!node){return;} 
     287                        if(highlight){ 
     288                                if(this._highlighted_option){ 
     289                                        this._highlightOption(this._highlighted_option, false); 
     290                                } 
     291                                this._highlighted_option = node; 
     292                        }else if(this._highlighted_option !== node){ 
     293                                return; 
     294                        }else{ 
     295                                this._highlighted_option = null; 
     296                        } 
     297                        dojo.toggleClass(node, this.baseClass+"ItemHover", highlight); 
     298                        if(dojo.hasClass(node, this.baseClass+"Marker")){ 
     299                                dojo.toggleClass(node, this.baseClass+"MarkerHover", highlight); 
     300                        }else{ 
     301                                dojo.toggleClass(node, this.baseClass+"TickHover", highlight); 
     302                        } 
     303                }, 
     304                 
    224305                onmouseover:function(/*Event*/ e){ 
    225306                        var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;                      
    226307                        // if we aren't targeting an item, then we return 
    227308                        if(!dojo.hasClass(tgr, this.baseClass+"Item")){return;} 
    228                         this._highlighted_option=tgr; 
    229                         dojo.addClass(tgr, this.baseClass+"ItemHover"); 
    230                         if(dojo.hasClass(tgr, this.baseClass+"Marker")){ 
    231                                 dojo.addClass(tgr, this.baseClass+"MarkerHover"); 
    232                         }else{ 
    233                                 dojo.addClass(tgr, this.baseClass+"TickHover"); 
    234                         } 
     309                        this._highlightOption(tgr, true); 
    235310                }, 
    236311 
    237312                onmouseout:function(/*Event*/ e){ 
    238313                        var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode; 
    239                         if(this._highlighted_option===tgr){                      
    240                                 dojo.removeClass(tgr, this.baseClass+"ItemHover"); 
    241                                 dojo.removeClass(tgr, this.baseClass+"MarkerHover"); 
    242                                 dojo.removeClass(tgr, this.baseClass+"TickHover"); 
    243                         } 
     314                        this._highlightOption(tgr, false); 
    244315                }, 
    245316 
     
    254325                _onArrowUp:function(){ 
    255326                        // summary: remove the bottom time and add one to the top 
    256                         var index = this.timeMenu.childNodes[0].index - 1; 
    257                         var div = this._createOption(index); 
    258                         this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1]); 
    259                         this.timeMenu.insertBefore(div, this.timeMenu.childNodes[0]); 
     327                        var index = this.timeMenu.childNodes[0].index; 
     328                        var divs = this._getFilteredNodes(index, 1, true); 
     329                        if(divs.length){ 
     330                                this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1]); 
     331                                this.timeMenu.insertBefore(divs[0], this.timeMenu.childNodes[0]); 
     332                        } 
    260333                }, 
    261334 
     
    263336                        // summary: remove the top time and add one to the bottom 
    264337                        var index = this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1].index + 1; 
    265                         var div = this._createOption(index); 
    266                         this.timeMenu.removeChild(this.timeMenu.childNodes[0]); 
    267                         this.timeMenu.appendChild(div); 
     338                        var divs = this._getFilteredNodes(index, 1, false); 
     339                        if(divs.length){ 
     340                                this.timeMenu.removeChild(this.timeMenu.childNodes[0]); 
     341                                this.timeMenu.appendChild(divs[0]); 
     342                        } 
     343                }, 
     344 
     345                handleKey:function(/*Event*/e){ 
     346                        var dk = dojo.keys; 
     347                        if(e.keyChar || e.keyCode == dk.BACKSPACE || e.keyCode == dk.DELETE){ 
     348                                // Set a timeout to kick off our filter 
     349                                setTimeout(dojo.hitch(this, function(){ 
     350                                        this._filterString = e.target.value.toLowerCase(); 
     351                                        this._showText(); 
     352                                }),1); 
     353                        }else if(e.keyCode == dk.DOWN_ARROW || e.keyCode == dk.UP_ARROW){ 
     354                                dojo.stopEvent(e); 
     355                                // Figure out which option to highlight now and then highlight it 
     356                                if(this._highlighted_option && !this._highlighted_option.parentNode){ 
     357                                        this._highlighted_option = null; 
     358                                } 
     359                                var timeMenu = this.timeMenu,  
     360                                        tgt = this._highlighted_option || dojo.query("." + this.baseClass + "ItemSelected", timeMenu)[0]; 
     361                                if(!tgt){ 
     362                                        tgt = timeMenu.childNodes[0]; 
     363                                }else if(timeMenu.childNodes.length){ 
     364                                        if(e.keyCode == dk.DOWN_ARROW && !tgt.nextSibling){ 
     365                                                this._onArrowDown(); 
     366                                        }else if(e.keyCode == dk.UP_ARROW && !tgt.previousSibling){ 
     367                                                this._onArrowUp(); 
     368                                        } 
     369                                        if(e.keyCode == dk.DOWN_ARROW){ 
     370                                                tgt = tgt.nextSibling; 
     371                                        }else{ 
     372                                                tgt = tgt.previousSibling; 
     373                                        } 
     374                                } 
     375                                this._highlightOption(tgt, true); 
     376                        }else if(this._highlighted_option && (e.keyCode == dk.ENTER || e.keyCode == dk.TAB)){ 
     377                                // Accept the currently-highlighted option as the value 
     378                                if(e.keyCode == dk.ENTER){dojo.stopEvent(e);} 
     379                                setTimeout(dojo.hitch(this, function(){ 
     380                                        this._onOptionSelected({target: this._highlighted_option}); 
     381                                }),1); 
     382                        } 
    268383                } 
    269384        }