cacert-testmgr/external/ZendFramework-1.9.5/externals/dojo/dijit/_TimePicker.js
Markus Warg 8398c9048d initially import ZendFramework-1.9.5 into repository
code was modified slightly, so the code differs from the original downloadable 1.9.5 version
2010-03-31 10:12:32 +02:00

482 lines
16 KiB
JavaScript

dojo.provide("dijit._TimePicker");
dojo.require("dijit.form._FormWidget");
dojo.require("dojo.date.locale");
/*=====
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 accessible
// as a standalone widget.
templatePath: dojo.moduleUrl("dijit", "templates/TimePicker.html"),
// 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 attr('value') instead.
// tags:
// deprecated
dojo.deprecated("dijit._TimePicker:setValue() is deprecated. Use attr('value') instead.", "", "2.0");
this.attr('value', value);
},
_setValueAttr: function(/*Date*/ date){
// summary:
// Hook so attr('value', ...) works.
// description:
// Set the value of the TimePicker.
// Redraws the TimePicker around the new date.
// tags:
// protected
this.value = date;
this._showText();
},
onOpen: function(best){
// summary:
// This is called by the popup manager when a TimeTextBox is displayed on the screen
// best:
// Whether it is being displayed above or below the `dijit.form.TimeTextBox`
// tags:
// protected
if(this._beenOpened && this.domNode.parentNode){
// We've been opened before - so set our filter to to the
// currently-displayed value (or empty string if it's already
// valid)
var p = dijit.byId(this.domNode.parentNode.dijitPopupParent);
if(p){
var val = p.getDisplayedValue();
if(val && !p.parse(val, p.constraints)){
this._filterString = val;
}else{
this._filterString = "";
}
this._showText();
}
}
this._beenOpened = true;
},
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){
// 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 = [], n, i = start, max = this._maxIncrement + Math.abs(i),
chk = before?-1:1, dec = before?1:0, inc = before?0:1;
do{
i = i - dec;
n = this._createOption(i);
if(n){nodes.push(n);}
i = i + inc;
}while(nodes.length < maxNum && (i*chk) < max);
if(before){ nodes.reverse(); }
return nodes;
},
_showText: function(){
// summary:
// Displays the relevant choices in the drop down list
// tags:
// private
this.timeMenu.innerHTML = "";
var fromIso = dojo.date.stamp.fromISOString;
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();
};
var clickableIncrementSeconds = sinceMidnight(this._clickableIncrementDate);
var visibleIncrementSeconds = sinceMidnight(this._visibleIncrementDate);
var visibleRangeSeconds = sinceMidnight(this._visibleRangeDate);
// round reference date to previous visible increment
var time = this.value.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;
// find the nodes we should display based on our filter
var before = this._getFilteredNodes(0, this._totalIncrements >> 1, true);
var after = this._getFilteredNodes(0, this._totalIncrements >> 1, false);
if(before.length < this._totalIncrements >> 1){
before = before.slice(before.length / 2);
after = after.slice(0, after.length / 2);
}
dojo.forEach(before.concat(after), function(n){this.timeMenu.appendChild(n);}, this);
// TODO:
// I commented this out because it
// causes problems for a TimeTextBox in a Dialog, or as the editor of an InlineEditBox,
// because the timeMenu node isn't visible yet. -- Bill (Bug #????)
// dijit.focus(this.timeMenu);
},
postCreate: function(){
// instantiate constraints
if(this.constraints===dijit._TimePicker.prototype.constraints){
this.constraints={};
}
// brings in visibleRange, increments, etc.
dojo.mixin(this, this.constraints);
// dojo.date.locale needs the lang in the constraints as locale
if(!this.constraints.locale){
this.constraints.locale=this.lang;
}
// assign typematic mouse listeners to the arrow buttons
this.connect(this.timeMenu, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
var _this = this;
var typematic = function(){
_this._connects.push(
dijit.typematic.addMouseListener.apply(null, arguments)
);
};
typematic(this.upArrow,this,this._onArrowUp, 1.0, 50);
typematic(this.downArrow,this,this._onArrowDown, 1.0, 50);
// Connect some callback functions to the hover event of the arrows
var triggerFx = function(cb){
return function(cnt){
// don't run on the first firing
if(cnt > 0){cb.call(this, arguments);}
};
};
var hoverFx = function(node, cb){
return function(e){
dojo.stopEvent(e);
dijit.typematic.trigger(e, this, node, triggerFx(cb), node, 1.0, 50);
};
};
this.connect(this.upArrow, "onmouseover", hoverFx(this.upArrow, this._onArrowUp));
this.connect(this.downArrow, "onmouseover", hoverFx(this.downArrow, this._onArrowDown));
this.inherited(arguments);
},
_buttonMouse: function(/*Event*/ e){
// summary:
// Handler for mouse button presses
// tags:
// private
dojo.toggleClass(e.currentTarget, "dijitButtonNodeHover", 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);
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(!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");
}
}
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.attr('value', tdate);
this.onValueSelected(tdate);
},
onValueSelected: function(/*Date*/ time){
// summary:
// Notification that a time was selected. It may be the same as the previous value.
// description:
// Used by `dijit.form._DateTimeTextBox` (and thus `dijit.form.TimeTextBox`)
// to get notification when the user has clicked a time.
// tags:
// protected
},
_highlightOption: function(/*node*/ node, /*Boolean*/ highlight){
// summary:
// Turns on/off hover 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
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
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
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);
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);
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.keyChar || e.charOrCode === dk.BACKSPACE || e.charOrCode == dk.DELETE){
// Set a timeout to kick off our filter
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);
// 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);
}else if(this._highlighted_option && (e.charOrCode == dk.ENTER || e.charOrCode === dk.TAB)){
// Accept the currently-highlighted option as the value
if(e.charOrCode == dk.ENTER){dojo.stopEvent(e);}
setTimeout(dojo.hitch(this, function(){
this._onOptionSelected({target: this._highlighted_option});
}),1);
}
}
}
);