diff options
author | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
commit | 81bea17aefb26859f825b9293c7c99192874806e (patch) | |
tree | fb244408ca271affa2899adb634788802c9a89d8 /lib/dijit/_TimePicker.js | |
parent | 870a70e109ac9e80a88047044530de53d0404ec7 (diff) |
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dijit/_TimePicker.js')
-rw-r--r-- | lib/dijit/_TimePicker.js | 726 |
1 files changed, 471 insertions, 255 deletions
diff --git a/lib/dijit/_TimePicker.js b/lib/dijit/_TimePicker.js index fc3ae29a8..678223c45 100644 --- a/lib/dijit/_TimePicker.js +++ b/lib/dijit/_TimePicker.js @@ -1,265 +1,481 @@ /* - Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved. + Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved. Available via Academic Free License >= 2.1 OR the modified BSD license. see: http://dojotoolkit.org/license for details */ -if(!dojo._hasResource["dijit._TimePicker"]){ -dojo._hasResource["dijit._TimePicker"]=true; +if(!dojo._hasResource["dijit._TimePicker"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._TimePicker"] = true; dojo.provide("dijit._TimePicker"); dojo.require("dijit.form._FormWidget"); dojo.require("dojo.date.locale"); -dojo.declare("dijit._TimePicker",[dijit._Widget,dijit._Templated],{templateString:dojo.cache("dijit","templates/TimePicker.html","<div id=\"widget_${id}\" class=\"dijitMenu\"\n ><div dojoAttachPoint=\"upArrow\" class=\"dijitButtonNode dijitUpArrowButton\" dojoAttachEvent=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" wairole=\"presentation\" role=\"presentation\"> </div\n\t\t><div class=\"dijitArrowButtonChar\">▲</div></div\n ><div dojoAttachPoint=\"timeMenu,focusNode\" dojoAttachEvent=\"onclick:_onOptionSelected,onmouseover,onmouseout\"></div\n ><div dojoAttachPoint=\"downArrow\" class=\"dijitButtonNode dijitDownArrowButton\" dojoAttachEvent=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" wairole=\"presentation\" role=\"presentation\"> </div\n\t\t><div class=\"dijitArrowButtonChar\">▼</div></div\n></div>\n"),baseClass:"dijitTimePicker",clickableIncrement:"T00:15:00",visibleIncrement:"T01:00:00",visibleRange:"T05:00:00",value:new Date(),_visibleIncrement:2,_clickableIncrement:1,_totalIncrements:10,constraints:{},serialize:dojo.date.stamp.toISOString,_filterString:"",setValue:function(_1){ -dojo.deprecated("dijit._TimePicker:setValue() is deprecated. Use set('value', ...) instead.","","2.0"); -this.set("value",_1); -},_setValueAttr:function(_2){ -this.value=_2; -this._showText(); -},onOpen:function(_3){ -if(this._beenOpened&&this.domNode.parentNode){ -var p=dijit.byId(this.domNode.parentNode.dijitPopupParent); -if(p){ -var _4=p.get("displayedValue"); -if(_4&&!p.parse(_4,p.constraints)){ -this._filterString=_4; -}else{ -this._filterString=""; -} -this._showText(); -} -} -this._beenOpened=true; -},isDisabledDate:function(_5,_6){ -return false; -},_getFilteredNodes:function(_7,_8,_9){ -var _a=[],n,i=_7,_b=this._maxIncrement+Math.abs(i),_c=_9?-1:1,_d=_9?1:0,_e=_9?0:1; -do{ -i=i-_d; -n=this._createOption(i); -if(n){ -_a.push(n); -} -i=i+_e; -}while(_a.length<_8&&(i*_c)<_b); -if(_9){ -_a.reverse(); -} -return _a; -},_showText:function(){ -this.timeMenu.innerHTML=""; -var _f=dojo.date.stamp.fromISOString; -this._clickableIncrementDate=_f(this.clickableIncrement); -this._visibleIncrementDate=_f(this.visibleIncrement); -this._visibleRangeDate=_f(this.visibleRange); -var _10=function(_11){ -return _11.getHours()*60*60+_11.getMinutes()*60+_11.getSeconds(); -}; -var _12=_10(this._clickableIncrementDate); -var _13=_10(this._visibleIncrementDate); -var _14=_10(this._visibleRangeDate); -var _15=this.value.getTime(); -this._refDate=new Date(_15-_15%(_13*1000)); -this._refDate.setFullYear(1970,0,1); -this._clickableIncrement=1; -this._totalIncrements=_14/_12; -this._visibleIncrement=_13/_12; -this._maxIncrement=(60*60*24)/_12; -var _16=this._getFilteredNodes(0,this._totalIncrements>>1,true); -var _17=this._getFilteredNodes(0,this._totalIncrements>>1,false); -if(_16.length<this._totalIncrements>>1){ -_16=_16.slice(_16.length/2); -_17=_17.slice(0,_17.length/2); -} -dojo.forEach(_16.concat(_17),function(n){ -this.timeMenu.appendChild(n); -},this); -},postCreate:function(){ -if(this.constraints===dijit._TimePicker.prototype.constraints){ -this.constraints={}; -} -dojo.mixin(this,this.constraints); -if(!this.constraints.locale){ -this.constraints.locale=this.lang; -} -this.connect(this.timeMenu,dojo.isIE?"onmousewheel":"DOMMouseScroll","_mouseWheeled"); -var _18=this; -var _19=function(){ -_18._connects.push(dijit.typematic.addMouseListener.apply(null,arguments)); -}; -_19(this.upArrow,this,this._onArrowUp,1,50); -_19(this.downArrow,this,this._onArrowDown,1,50); -var _1a=function(cb){ -return function(cnt){ -if(cnt>0){ -cb.call(this,arguments); -} -}; -}; -var _1b=function(_1c,cb){ -return function(e){ -dojo.stopEvent(e); -dijit.typematic.trigger(e,this,_1c,_1a(cb),_1c,1,50); -}; -}; -this.connect(this.upArrow,"onmouseover",_1b(this.upArrow,this._onArrowUp)); -this.connect(this.downArrow,"onmouseover",_1b(this.downArrow,this._onArrowDown)); -this.inherited(arguments); -},_buttonMouse:function(e){ -dojo.toggleClass(e.currentTarget,e.currentTarget==this.upArrow?"dijitUpArrowHover":"dijitDownArrowHover",e.type=="mouseenter"||e.type=="mouseover"); -},_createOption:function(_1d){ -var _1e=new Date(this._refDate); -var _1f=this._clickableIncrementDate; -_1e.setHours(_1e.getHours()+_1f.getHours()*_1d,_1e.getMinutes()+_1f.getMinutes()*_1d,_1e.getSeconds()+_1f.getSeconds()*_1d); -if(this.constraints.selector=="time"){ -_1e.setFullYear(1970,0,1); -} -var _20=dojo.date.locale.format(_1e,this.constraints); -if(this._filterString&&_20.toLowerCase().indexOf(this._filterString)!==0){ -return null; -} -var div=dojo.create("div",{"class":this.baseClass+"Item"}); -div.date=_1e; -div.index=_1d; -dojo.create("div",{"class":this.baseClass+"ItemInner",innerHTML:_20},div); -if(_1d%this._visibleIncrement<1&&_1d%this._visibleIncrement>-1){ -dojo.addClass(div,this.baseClass+"Marker"); -}else{ -if(!(_1d%this._clickableIncrement)){ -dojo.addClass(div,this.baseClass+"Tick"); -} -} -if(this.isDisabledDate(_1e)){ -dojo.addClass(div,this.baseClass+"ItemDisabled"); -} -if(!dojo.date.compare(this.value,_1e,this.constraints.selector)){ -div.selected=true; -dojo.addClass(div,this.baseClass+"ItemSelected"); -if(dojo.hasClass(div,this.baseClass+"Marker")){ -dojo.addClass(div,this.baseClass+"MarkerSelected"); -}else{ -dojo.addClass(div,this.baseClass+"TickSelected"); -} -} -return div; -},_onOptionSelected:function(tgt){ -var _21=tgt.target.date||tgt.target.parentNode.date; -if(!_21||this.isDisabledDate(_21)){ -return; -} -this._highlighted_option=null; -this.set("value",_21); -this.onValueSelected(_21); -},onValueSelected:function(_22){ -},_highlightOption:function(_23,_24){ -if(!_23){ -return; -} -if(_24){ -if(this._highlighted_option){ -this._highlightOption(this._highlighted_option,false); -} -this._highlighted_option=_23; -}else{ -if(this._highlighted_option!==_23){ -return; -}else{ -this._highlighted_option=null; -} -} -dojo.toggleClass(_23,this.baseClass+"ItemHover",_24); -if(dojo.hasClass(_23,this.baseClass+"Marker")){ -dojo.toggleClass(_23,this.baseClass+"MarkerHover",_24); -}else{ -dojo.toggleClass(_23,this.baseClass+"TickHover",_24); -} -},onmouseover:function(e){ -this._keyboardSelected=null; -var tgr=(e.target.parentNode===this.timeMenu)?e.target:e.target.parentNode; -if(!dojo.hasClass(tgr,this.baseClass+"Item")){ -return; -} -this._highlightOption(tgr,true); -},onmouseout:function(e){ -this._keyboardSelected=null; -var tgr=(e.target.parentNode===this.timeMenu)?e.target:e.target.parentNode; -this._highlightOption(tgr,false); -},_mouseWheeled:function(e){ -this._keyboardSelected=null; -dojo.stopEvent(e); -var _25=(dojo.isIE?e.wheelDelta:-e.detail); -this[(_25>0?"_onArrowUp":"_onArrowDown")](); -},_onArrowUp:function(_26){ -if(typeof _26=="number"&&_26==-1){ -return; -} -if(!this.timeMenu.childNodes.length){ -return; -} -var _27=this.timeMenu.childNodes[0].index; -var _28=this._getFilteredNodes(_27,1,true); -if(_28.length){ -this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length-1]); -this.timeMenu.insertBefore(_28[0],this.timeMenu.childNodes[0]); -} -},_onArrowDown:function(_29){ -if(typeof _29=="number"&&_29==-1){ -return; -} -if(!this.timeMenu.childNodes.length){ -return; -} -var _2a=this.timeMenu.childNodes[this.timeMenu.childNodes.length-1].index+1; -var _2b=this._getFilteredNodes(_2a,1,false); -if(_2b.length){ -this.timeMenu.removeChild(this.timeMenu.childNodes[0]); -this.timeMenu.appendChild(_2b[0]); -} -},handleKey:function(e){ -var dk=dojo.keys; -if(e.keyChar||e.charOrCode===dk.BACKSPACE||e.charOrCode==dk.DELETE){ -setTimeout(dojo.hitch(this,function(){ -this._filterString=e.target.value.toLowerCase(); -this._showText(); -}),1); -}else{ -if(e.charOrCode==dk.DOWN_ARROW||e.charOrCode==dk.UP_ARROW){ -dojo.stopEvent(e); -if(this._highlighted_option&&!this._highlighted_option.parentNode){ -this._highlighted_option=null; -} -var _2c=this.timeMenu,tgt=this._highlighted_option||dojo.query("."+this.baseClass+"ItemSelected",_2c)[0]; -if(!tgt){ -tgt=_2c.childNodes[0]; -}else{ -if(_2c.childNodes.length){ -if(e.charOrCode==dk.DOWN_ARROW&&!tgt.nextSibling){ -this._onArrowDown(); -}else{ -if(e.charOrCode==dk.UP_ARROW&&!tgt.previousSibling){ -this._onArrowUp(); -} -} -if(e.charOrCode==dk.DOWN_ARROW){ -tgt=tgt.nextSibling; -}else{ -tgt=tgt.previousSibling; -} -} -} -this._highlightOption(tgt,true); -this._keyboardSelected=tgt; -}else{ -if(this._highlighted_option&&(e.charOrCode==dk.ENTER||e.charOrCode===dk.TAB)){ -if(!this._keyboardSelected&&e.charOrCode===dk.TAB){ -return; -} -if(e.charOrCode==dk.ENTER){ -dojo.stopEvent(e); -} -this._onOptionSelected({target:this._highlighted_option}); -} -} -} -}}); + + +/*===== +dojo.declare( + "dijit._TimePicker.__Constraints", + dojo.date.locale.__FormatOptions, + { + // clickableIncrement: String + // See `dijit._TimePicker.clickableIncrement` + clickableIncrement: "T00:15:00", + + // visibleIncrement: String + // See `dijit._TimePicker.visibleIncrement` + visibleIncrement: "T01:00:00", + + // visibleRange: String + // See `dijit._TimePicker.visibleRange` + visibleRange: "T05:00:00" + } +); +=====*/ + +dojo.declare("dijit._TimePicker", + [dijit._Widget, dijit._Templated], + { + // summary: + // A graphical time picker. + // This widget is used internally by other widgets and is not available + // as a standalone widget due to lack of accessibility support. + + templateString: dojo.cache("dijit", "templates/TimePicker.html", "<div id=\"widget_${id}\" class=\"dijitMenu\"\n ><div dojoAttachPoint=\"upArrow\" class=\"dijitButtonNode dijitUpArrowButton\" dojoAttachEvent=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" role=\"presentation\"> </div\n\t\t><div class=\"dijitArrowButtonChar\">▲</div></div\n ><div dojoAttachPoint=\"timeMenu,focusNode\" dojoAttachEvent=\"onclick:_onOptionSelected,onmouseover,onmouseout\"></div\n ><div dojoAttachPoint=\"downArrow\" class=\"dijitButtonNode dijitDownArrowButton\" dojoAttachEvent=\"onmouseenter:_buttonMouse,onmouseleave:_buttonMouse\"\n\t\t><div class=\"dijitReset dijitInline dijitArrowButtonInner\" role=\"presentation\"> </div\n\t\t><div class=\"dijitArrowButtonChar\">▼</div></div\n></div>\n"), + + // baseClass: [protected] String + // The root className to use for the various states of this widget + baseClass: "dijitTimePicker", + + // clickableIncrement: String + // ISO-8601 string representing the amount by which + // every clickable element in the time picker increases. + // Set in local time, without a time zone. + // Example: `T00:15:00` creates 15 minute increments + // Must divide dijit._TimePicker.visibleIncrement evenly + clickableIncrement: "T00:15:00", + + // visibleIncrement: String + // ISO-8601 string representing the amount by which + // every element with a visible time in the time picker increases. + // Set in local time, without a time zone. + // Example: `T01:00:00` creates text in every 1 hour increment + visibleIncrement: "T01:00:00", + + // visibleRange: String + // ISO-8601 string representing the range of this TimePicker. + // The TimePicker will only display times in this range. + // Example: `T05:00:00` displays 5 hours of options + visibleRange: "T05:00:00", + + // value: String + // Date to display. + // Defaults to current time and date. + // Can be a Date object or an ISO-8601 string. + // If you specify the GMT time zone (`-01:00`), + // the time will be converted to the local time in the local time zone. + // Otherwise, the time is considered to be in the local time zone. + // If you specify the date and isDate is true, the date is used. + // Example: if your local time zone is `GMT -05:00`, + // `T10:00:00` becomes `T10:00:00-05:00` (considered to be local time), + // `T10:00:00-01:00` becomes `T06:00:00-05:00` (4 hour difference), + // `T10:00:00Z` becomes `T05:00:00-05:00` (5 hour difference between Zulu and local time) + // `yyyy-mm-ddThh:mm:ss` is the format to set the date and time + // Example: `2007-06-01T09:00:00` + value: new Date(), + + _visibleIncrement:2, + _clickableIncrement:1, + _totalIncrements:10, + + // constraints: dijit._TimePicker.__Constraints + // Specifies valid range of times (start time, end time) + constraints:{}, + +/*===== + serialize: function(val, options){ + // summary: + // User overridable function used to convert the attr('value') result to a String + // val: Date + // The current value + // options: Object? + // tags: + // protected + }, +=====*/ + serialize: dojo.date.stamp.toISOString, + +/*===== + // filterString: string + // The string to filter by + filterString: "", +=====*/ + + setValue: function(/*Date*/ value){ + // summary: + // Deprecated. Used set('value') instead. + // tags: + // deprecated + dojo.deprecated("dijit._TimePicker:setValue() is deprecated. Use set('value', ...) instead.", "", "2.0"); + this.set('value', value); + }, + + _setValueAttr: function(/*Date*/ date){ + // summary: + // Hook so set('value', ...) works. + // description: + // Set the value of the TimePicker. + // Redraws the TimePicker around the new date. + // tags: + // protected + this._set("value", date); + this._showText(); + }, + + _setFilterStringAttr: function(val){ + // summary: + // Called by TimeTextBox to filter the values shown in my list + this._set("filterString", val); + this._showText(); + }, + + isDisabledDate: function(/*Date*/ dateObject, /*String?*/ locale){ + // summary: + // May be overridden to disable certain dates in the TimePicker e.g. `isDisabledDate=dojo.date.locale.isWeekend` + // type: + // extension + return false; // Boolean + }, + + _getFilteredNodes: function(/*number*/ start, /*number*/ maxNum, /*Boolean*/ before, /*DOMnode*/ lastNode){ + // summary: + // Returns an array of nodes with the filter applied. At most maxNum nodes + // will be returned - but fewer may be returned as well. If the + // before parameter is set to true, then it will return the elements + // before the given index + // tags: + // private + var + nodes = [], + lastValue = lastNode ? lastNode.date : this._refDate, + n, + i = start, + max = this._maxIncrement + Math.abs(i), + chk = before ? -1 : 1, + dec = before ? 1 : 0, + inc = 1 - dec; + do{ + i = i - dec; + n = this._createOption(i); + if(n){ + if((before && n.date > lastValue) || (!before && n.date < lastValue)){ + break; // don't wrap + } + nodes[before ? "unshift" : "push"](n); + lastValue = n.date; + } + i = i + inc; + }while(nodes.length < maxNum && (i*chk) < max); + return nodes; + }, + + _showText: function(){ + // summary: + // Displays the relevant choices in the drop down list + // tags: + // private + var fromIso = dojo.date.stamp.fromISOString; + this.timeMenu.innerHTML = ""; + this._clickableIncrementDate=fromIso(this.clickableIncrement); + this._visibleIncrementDate=fromIso(this.visibleIncrement); + this._visibleRangeDate=fromIso(this.visibleRange); + // get the value of the increments and the range in seconds (since 00:00:00) to find out how many divs to create + var + sinceMidnight = function(/*Date*/ date){ + return date.getHours() * 60 * 60 + date.getMinutes() * 60 + date.getSeconds(); + }, + clickableIncrementSeconds = sinceMidnight(this._clickableIncrementDate), + visibleIncrementSeconds = sinceMidnight(this._visibleIncrementDate), + visibleRangeSeconds = sinceMidnight(this._visibleRangeDate), + + // round reference date to previous visible increment + time = (this.value || this.currentFocus).getTime(); + + this._refDate = new Date(time - time % (visibleIncrementSeconds*1000)); + this._refDate.setFullYear(1970,0,1); // match parse defaults + + // assume clickable increment is the smallest unit + this._clickableIncrement = 1; + // divide the visible range by the clickable increment to get the number of divs to create + // example: 10:00:00/00:15:00 -> display 40 divs + this._totalIncrements = visibleRangeSeconds / clickableIncrementSeconds; + // divide the visible increments by the clickable increments to get how often to display the time inline + // example: 01:00:00/00:15:00 -> display the time every 4 divs + this._visibleIncrement = visibleIncrementSeconds / clickableIncrementSeconds; + // divide the number of seconds in a day by the clickable increment in seconds to get the + // absolute max number of increments. + this._maxIncrement = (60 * 60 * 24) / clickableIncrementSeconds; + + var + // Find the nodes we should display based on our filter. + // Limit to 10 nodes displayed as a half-hearted attempt to stop drop down from overlapping <input>. + after = this._getFilteredNodes(0, Math.min(this._totalIncrements >> 1, 10) - 1), + before = this._getFilteredNodes(0, Math.min(this._totalIncrements, 10) - after.length, true, after[0]); + dojo.forEach(before.concat(after), function(n){this.timeMenu.appendChild(n);}, this); + }, + + constructor: function(){ + this.constraints = {}; // create instance object + }, + + postMixInProperties: function(){ + this.inherited(arguments); + this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls + }, + + _setConstraintsAttr: function(/* Object */ constraints){ + // brings in visibleRange, increments, etc. + dojo.mixin(this, constraints); + + // dojo.date.locale needs the lang in the constraints as locale + if(!constraints.locale){ + constraints.locale = this.lang; + } + }, + + postCreate: function(){ + // assign typematic mouse listeners to the arrow buttons + this.connect(this.timeMenu, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled"); + this._connects.push(dijit.typematic.addMouseListener(this.upArrow, this, "_onArrowUp", 33, 250)); + this._connects.push(dijit.typematic.addMouseListener(this.downArrow, this, "_onArrowDown", 33, 250)); + + this.inherited(arguments); + }, + + _buttonMouse: function(/*Event*/ e){ + // summary: + // Handler for hover (and unhover) on up/down arrows + // tags: + // private + + // in non-IE browser the "mouseenter" event will become "mouseover", + // but in IE it's still "mouseenter" + dojo.toggleClass(e.currentTarget, e.currentTarget == this.upArrow ? "dijitUpArrowHover" : "dijitDownArrowHover", + e.type == "mouseenter" || e.type == "mouseover"); + }, + + _createOption: function(/*Number*/ index){ + // summary: + // Creates a clickable time option + // tags: + // private + var date = new Date(this._refDate); + var incrementDate = this._clickableIncrementDate; + date.setHours(date.getHours() + incrementDate.getHours() * index, + date.getMinutes() + incrementDate.getMinutes() * index, + date.getSeconds() + incrementDate.getSeconds() * index); + if(this.constraints.selector == "time"){ + date.setFullYear(1970,0,1); // make sure each time is for the same date + } + var dateString = dojo.date.locale.format(date, this.constraints); + if(this.filterString && dateString.toLowerCase().indexOf(this.filterString) !== 0){ + // Doesn't match the filter - return null + return null; + } + + var div = dojo.create("div", {"class": this.baseClass+"Item"}); + div.date = date; + div.index = index; + dojo.create('div',{ + "class": this.baseClass + "ItemInner", + innerHTML: dateString + }, div); + + if(index%this._visibleIncrement<1 && index%this._visibleIncrement>-1){ + dojo.addClass(div, this.baseClass+"Marker"); + }else if(!(index%this._clickableIncrement)){ + dojo.addClass(div, this.baseClass+"Tick"); + } + + if(this.isDisabledDate(date)){ + // set disabled + dojo.addClass(div, this.baseClass+"ItemDisabled"); + } + if(this.value && !dojo.date.compare(this.value, date, this.constraints.selector)){ + div.selected = true; + dojo.addClass(div, this.baseClass+"ItemSelected"); + if(dojo.hasClass(div, this.baseClass+"Marker")){ + dojo.addClass(div, this.baseClass+"MarkerSelected"); + }else{ + dojo.addClass(div, this.baseClass+"TickSelected"); + } + + // Initially highlight the current value. User can change highlight by up/down arrow keys + // or mouse movement. + this._highlightOption(div, true); + } + return div; + }, + + _onOptionSelected: function(/*Object*/ tgt){ + // summary: + // Called when user clicks an option in the drop down list + // tags: + // private + var tdate = tgt.target.date || tgt.target.parentNode.date; + if(!tdate || this.isDisabledDate(tdate)){ return; } + this._highlighted_option = null; + this.set('value', tdate); + this.onChange(tdate); + }, + + onChange: function(/*Date*/ time){ + // summary: + // Notification that a time was selected. It may be the same as the previous value. + // tags: + // public + }, + + _highlightOption: function(/*node*/ node, /*Boolean*/ highlight){ + // summary: + // Turns on/off highlight effect on a node based on mouse out/over event + // tags: + // private + if(!node){return;} + if(highlight){ + if(this._highlighted_option){ + this._highlightOption(this._highlighted_option, false); + } + this._highlighted_option = node; + }else if(this._highlighted_option !== node){ + return; + }else{ + this._highlighted_option = null; + } + dojo.toggleClass(node, this.baseClass+"ItemHover", highlight); + if(dojo.hasClass(node, this.baseClass+"Marker")){ + dojo.toggleClass(node, this.baseClass+"MarkerHover", highlight); + }else{ + dojo.toggleClass(node, this.baseClass+"TickHover", highlight); + } + }, + + onmouseover: function(/*Event*/ e){ + // summary: + // Handler for onmouseover event + // tags: + // private + this._keyboardSelected = null; + var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode; + // if we aren't targeting an item, then we return + if(!dojo.hasClass(tgr, this.baseClass+"Item")){return;} + this._highlightOption(tgr, true); + }, + + onmouseout: function(/*Event*/ e){ + // summary: + // Handler for onmouseout event + // tags: + // private + this._keyboardSelected = null; + var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode; + this._highlightOption(tgr, false); + }, + + _mouseWheeled: function(/*Event*/ e){ + // summary: + // Handle the mouse wheel events + // tags: + // private + this._keyboardSelected = null; + dojo.stopEvent(e); + // we're not _measuring_ the scroll amount, just direction + var scrollAmount = (dojo.isIE ? e.wheelDelta : -e.detail); + this[(scrollAmount>0 ? "_onArrowUp" : "_onArrowDown")](); // yes, we're making a new dom node every time you mousewheel, or click + }, + + _onArrowUp: function(count){ + // summary: + // Handler for up arrow key. + // description: + // Removes the bottom time and add one to the top + // tags: + // private + if(typeof count == "number" && count == -1){ return; } // typematic end + if(!this.timeMenu.childNodes.length){ return; } + var index = this.timeMenu.childNodes[0].index; + var divs = this._getFilteredNodes(index, 1, true, this.timeMenu.childNodes[0]); + if(divs.length){ + this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1]); + this.timeMenu.insertBefore(divs[0], this.timeMenu.childNodes[0]); + } + }, + + _onArrowDown: function(count){ + // summary: + // Handler for up arrow key. + // description: + // Remove the top time and add one to the bottom + // tags: + // private + if(typeof count == "number" && count == -1){ return; } // typematic end + if(!this.timeMenu.childNodes.length){ return; } + var index = this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1].index + 1; + var divs = this._getFilteredNodes(index, 1, false, this.timeMenu.childNodes[this.timeMenu.childNodes.length - 1]); + if(divs.length){ + this.timeMenu.removeChild(this.timeMenu.childNodes[0]); + this.timeMenu.appendChild(divs[0]); + } + }, + + handleKey: function(/*Event*/ e){ + // summary: + // Called from `dijit.form._DateTimeTextBox` to pass a keypress event + // from the `dijit.form.TimeTextBox` to be handled in this widget + // tags: + // protected + var dk = dojo.keys; + if(e.charOrCode == dk.DOWN_ARROW || e.charOrCode == dk.UP_ARROW){ + dojo.stopEvent(e); + // Figure out which option to highlight now and then highlight it + if(this._highlighted_option && !this._highlighted_option.parentNode){ + this._highlighted_option = null; + } + var timeMenu = this.timeMenu, + tgt = this._highlighted_option || dojo.query("." + this.baseClass + "ItemSelected", timeMenu)[0]; + if(!tgt){ + tgt = timeMenu.childNodes[0]; + }else if(timeMenu.childNodes.length){ + if(e.charOrCode == dk.DOWN_ARROW && !tgt.nextSibling){ + this._onArrowDown(); + }else if(e.charOrCode == dk.UP_ARROW && !tgt.previousSibling){ + this._onArrowUp(); + } + if(e.charOrCode == dk.DOWN_ARROW){ + tgt = tgt.nextSibling; + }else{ + tgt = tgt.previousSibling; + } + } + this._highlightOption(tgt, true); + this._keyboardSelected = tgt; + return false; + }else if(e.charOrCode == dk.ENTER || e.charOrCode === dk.TAB){ + // mouse hover followed by TAB is NO selection + if(!this._keyboardSelected && e.charOrCode === dk.TAB){ + return true; // true means don't call stopEvent() + } + + // Accept the currently-highlighted option as the value + if(this._highlighted_option){ + this._onOptionSelected({target: this._highlighted_option}); + } + + // Call stopEvent() for ENTER key so that form doesn't submit, + // but not for TAB, so that TAB does switch focus + return e.charOrCode === dk.TAB; + } + } + } +); + } |