sogo/UI/WebServerResources/SOGoTimePicker.js
Francis Lachapelle 2b1a8f6b30 See ChangeLog
Monotone-Parent: 377f173bfaa310b58f7ebe5b7fb0f70204cbb0e5
Monotone-Revision: 1eadd109045fc1edf90a763470ff31e5ad34bebf

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2012-03-14T14:38:57
2012-03-14 14:38:57 +00:00

223 lines
8 KiB
JavaScript

/* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Time picker widget interface to be added to an INPUT (this!)
*
* Available events:
* time:change -- fired once the value of the input has changed
*
*/
var SOGoTimePickerInterface = {
div: null,
extendedButton: null,
minutes: '00',
hours: '00',
extended: false,
mouseInside: false,
disposeHandler: null,
bind: function () {
// Build widget
this.div = new Element("div", {'class': 'SOGoTimePickerMenu'});
this.div.hide();
document.body.appendChild(this.div);
var inner = new Element("div");
this.div.appendChild(inner);
var hours = new Element("div", {'class': 'hours'});
inner.appendChild(hours);
for (var i = 0; i < 24; i++) {
var v = (i < 10)? '0' + i : i;
var content = new Element("div", {'class': 'SOGoTimePickerHour_'+v}).update(v);
content.on("click", this.onHourClick.bindAsEventListener(this));
var span = new Element("span", {'class': 'cell'});
span.appendChild(content);
hours.appendChild(span);
if (i == 11) {
hours = new Element("div", {'class': 'hours'});
inner.appendChild(hours);
}
}
var minutes = new Element("div", {'class': 'minutes min5'});
inner.appendChild(minutes);
for (var i = 0; i < 60; i += 5) {
var v = (i < 10)? '0' + i : i;
var content = new Element("div", {'class': 'SOGoTimePickerMinute_'+v}).update(":"+v);
content.on("click", this.onMinuteClick.bindAsEventListener(this));
var span = new Element("span", {'class': 'cell'});
span.appendChild(content);
minutes.appendChild(span);
if (i == 25) {
minutes = new Element("div", {'class': 'minutes min5'});
inner.appendChild(minutes);
}
}
var minutes = new Element("div", {'class': 'minutes min1'});
minutes.hide();
inner.appendChild(minutes);
for (var i = 0; i < 60;) {
var v = (i < 10)? '0' + i : i;
var content = new Element("div", {'class': 'SOGoTimePickerMinute_'+v}).update(":"+v);
content.on("click", this.onMinuteClick.bindAsEventListener(this));
var span = new Element("span", {'class': 'cell'});
span.appendChild(content);
minutes.appendChild(span);
i++;
if (i % 5 == 0) {
minutes = new Element("div", {'class': 'minutes min1'});
minutes.hide();
inner.appendChild(minutes);
}
}
var a = new Element("a", {'class': 'button'});
a.on("click", this.toggleExtendedView.bindAsEventListener(this));
this.extendedButton = new Element("span").update('&gt;&gt;');
a.appendChild(this.extendedButton);
inner.appendChild(a);
inner.appendChild(new Element("hr"));
// Compute position
this.position();
// Register observers
this.on("click", this.toggleVisibility.bindAsEventListener(this));
this.on("change", this.onChange.bindAsEventListener(this));
this.on("keydown", this.onKeydown.bindAsEventListener(this));
this.div.on("mouseenter", this.onEnter.bindAsEventListener(this));
this.div.on("mouseleave", this.onLeave.bindAsEventListener(this));
this.disposeHandler = $(document.body).on("click", this.onDispose.bindAsEventListener(this));
this.disposeHandler.stop();
// Apply current input value if defined
this.onChange();
},
position: function () {
var inputPosition = this.cumulativeOffset();
var inputDimensions = this.getDimensions();
var divWidth = this.div.getWidth();
var windowWidth = window.width();
var left = inputPosition[0];
var arrow = -1000 + inputDimensions['width'] - 10;
if (left + divWidth > windowWidth) {
left = windowWidth - divWidth - 2;
arrow += (inputPosition[0] - left);
}
var top = inputPosition[1] + 12;
this.div.setStyle({ top: top+"px",
left: left+"px",
backgroundPosition: arrow+'px top'});
},
onHourClick: function (event) {
this.div.down('.SOGoTimePickerHour_' + this.hours).removeClassName("selected");
this.hours = Event.findElement(event).className.substring(19);
this.div.down('.SOGoTimePickerHour_' + this.hours).addClassName("selected");
this._updateValue();
},
onMinuteClick: function (event) {
this.div.select('.SOGoTimePickerMinute_' + this.minutes).each(function(e) { e.removeClassName("selected") });
this.minutes = Event.findElement(event).className.substring(21);
this.div.select('.SOGoTimePickerMinute_' + this.minutes).each(function(e) { e.addClassName("selected") });
this._updateValue();
this.div.hide();
},
toggleExtendedView: function (event) {
this.extended = !this.extended;
if (this.extended) {
this.extendedButton.update('&lt;&lt;');
this.div.select("DIV.min5").invoke('hide');
this.div.select("DIV.min1").invoke('show');
}
else {
this.extendedButton.update('&gt;&gt;');
this.div.select("DIV.min1").invoke('hide');
this.div.select("DIV.min5").invoke('show');
}
},
toggleVisibility: function (event) {
if (this.div.visible())
this.div.hide();
else {
$$('DIV.SOGoTimePickerMenu').invoke('hide');
this.div.show();
this.disposeHandler.start();
}
Event.stop(event);
},
onChange: function (event) {
this.div.down('.SOGoTimePickerHour_' + this.hours).removeClassName("selected");
this.div.select('.SOGoTimePickerMinute_' + this.minutes).each(function(e) { e.removeClassName("selected") });
var matches = this.value.match(/([0-9]{1,2}):?([0-9]{2})/);
if (matches) {
this.hours = matches[1];
this.minutes = matches[2] || '0';
if (parseInt(this.hours, 10) > 23) this.hours = 23;
if (parseInt(this.minutes, 10) > 59) this.minutes = 59;
if (this.minutes % 5 == 0) {
if (this.extended)
this.toggleExtendedView();
}
else if (!this.extended)
this.toggleExtendedView();
if (this.hours.length < 2) this.hours = '0' + this.hours;
if (this.minutes.length < 2) this.minutes = '0' + this.minutes;
this.div.down('.SOGoTimePickerHour_' + this.hours).addClassName("selected");
this.div.select('.SOGoTimePickerMinute_' + this.minutes).each(function(e) { e.addClassName("selected") });
}
this._updateValue(true);
},
onKeydown: function (event) {
this.div.hide();
this.disposeHandler.stop();
if (event.metaKey == 1 || event.ctrlKey == 1 ||
event.keyCode == Event.KEY_TAB ||
event.keyCode == Event.KEY_BACKSPACE)
return true;
if (event.keyCode > 57 && event.keyCode != 186 && event.keyCode != 59 ||
(event.keyCode == 186 || event.keyCode == 59) && this.value.indexOf(":") >= 0)
Event.stop(event);
},
onEnter: function (event) {
this.mouseInside = true;
this.disposeHandler.stop();
},
onLeave: function (event) {
this.mouseInside = false;
this.disposeHandler.start();
},
onDispose: function (event) {
if (!this.mouseInside) {
this.div.hide();
this.disposeHandler.stop();
Event.stop(event);
}
},
_updateValue: function (force) {
var value = this.hours + ':' + this.minutes;
if (force || value != this.value) {
this.value = value;
this.fire("time:change");
}
}
};