See ChangeLog.

Monotone-Parent: d11c3e99fe05eb716e0732c7b5c44019dcd75934
Monotone-Revision: 0a8cad3c6a768c445cd15f040d34f93bba3eb6ea

Monotone-Author: flachapelle@inverse.ca
Monotone-Date: 2011-06-13T20:28:10
Monotone-Branch: ca.inverse.sogo
This commit is contained in:
Francis Lachapelle
2011-06-13 20:28:10 +00:00
parent 80b7efed49
commit 2015c05a3c
15 changed files with 497 additions and 298 deletions
@@ -178,11 +178,11 @@ Date.prototype.getHourString = function() {
};
Date.prototype.getDisplayHoursString = function() {
var hoursString = "" + this.getUTCHours();
var hoursString = "" + this.getHours();
if (hoursString.length == 1)
hoursString = '0' + hoursString;
var minutesString = "" + this.getUTCMinutes();
var minutesString = "" + this.getMinutes();
if (minutesString.length == 1)
minutesString = '0' + minutesString;
+220
View File
@@ -0,0 +1,220 @@
/* -*- 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
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] + parseInt(inputDimensions['height']/2);
var top = inputPosition[1] + 12;
this.div.setStyle({ top: top+"px",
left: left+"px",
backgroundPosition: arrow+'px top'});
// 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();
},
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]+):([0-9]+)/);
if (matches) {
this.hours = matches[1];
this.minutes = matches[2];
if (parseInt(this.hours) > 23) this.hours = 23;
if (parseInt(this.minutes) > 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();
},
onKeydown: function (event) {
this.div.hide();
this.disposeHandler.stop();
if (event.metaKey == 1 || event.ctrlKey == 1 ||
event.keyCode == Event.KEY_TAB)
return true;
if (event.keyCode > 57 && event.keyCode != 186 ||
event.keyCode == 186 && this.value.indexOf(":") >= 0 ||
event.keyCode != Event.KEY_BACKSPACE && this.value.length > 4) {
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 () {
var value = this.hours + ':' + this.minutes;
if (value != this.value) {
this.value = value;
this.fire("time:change");
}
}
};
+51 -48
View File
@@ -77,23 +77,38 @@ function validateAptEditor() {
}
else if (tmpdate == null /* means: same date */) {
// TODO: check time
var start, end;
var startHour, startMinute, endHour, endMinute;
var matches;
start = parseInt(document.forms[0]['startTime_time_hour'].value);
end = parseInt(document.forms[0]['endTime_time_hour'].value);
matches = document.forms[0]['startTime_time'].value.match(/([0-9]+):([0-9]+)/);
if (matches) {
startHour = parseInt(matches[1]);
startMinute = parseInt(matches[2]);
matches = document.forms[0]['endTime_time'].value.match(/([0-9]+):([0-9]+)/);
if (matches) {
endHour = parseInt(matches[1]);
endMinute = parseInt(matches[2]);
if (start > end) {
alert(labels.validate_endbeforestart);
return false;
}
else if (start == end) {
start = parseInt(document.forms[0]['startTime_time_minute'].value);
end = parseInt(document.forms[0]['endTime_time_minute'].value);
if (start > end) {
alert(labels.validate_endbeforestart);
if (startHour > endHour) {
alert(labels.validate_endbeforestart);
return false;
}
else if (startHour == endHour) {
if (startMinute > endMinute) {
alert(labels.validate_endbeforestart);
return false;
}
}
}
else {
alert(labels.validate_invalid_enddate);
return false;
}
}
else {
alert(labels.validate_invalid_startdate);
return false;
}
}
AIM.submit($(document.editform), {'onComplete' : onEventPostComplete});
@@ -212,18 +227,18 @@ function endDayAsShortString() {
function _getDate(which) {
var date = window.timeWidgets[which]['date'].inputAsDate();
date.setHours( window.timeWidgets[which]['hour'].value );
date.setMinutes( window.timeWidgets[which]['minute'].value );
var time = window.timeWidgets[which]['time'].value.split(":");
date.setHours(time[0]);
date.setMinutes(time[1]);
return date;
}
function _getShadowDate(which) {
var date = window.timeWidgets[which]['date'].getAttribute("shadow-value").asDate();
var intValue = parseInt(window.timeWidgets[which]['hour'].getAttribute("shadow-value"));
date.setHours(intValue);
intValue = parseInt(window.timeWidgets[which]['minute'].getAttribute("shadow-value"));
date.setMinutes(intValue);
var time = window.timeWidgets[which]['time'].getAttribute("shadow-value").split(":");
date.setHours(time[0]);
date.setMinutes(time[1]);
return date;
}
@@ -246,11 +261,7 @@ function getShadowEndDate() {
function _setDate(which, newDate) {
window.timeWidgets[which]['date'].setInputAsDate(newDate);
window.timeWidgets[which]['hour'].value = newDate.getHours();
var minutes = newDate.getMinutes();
if (minutes % 15)
minutes += (15 - minutes % 15);
window.timeWidgets[which]['minute'].value = minutes;
window.timeWidgets[which]['time'].value = newDate.getDisplayHoursString();
}
function setStartDate(newStartDate) {
@@ -273,11 +284,9 @@ function onAdjustTime(event) {
window.setEndDate(newEndDate);
window.timeWidgets['end']['date'].updateShadowValue();
window.timeWidgets['end']['hour'].updateShadowValue();
window.timeWidgets['end']['minute'].updateShadowValue();
window.timeWidgets['end']['time'].updateShadowValue();
window.timeWidgets['start']['date'].updateShadowValue();
window.timeWidgets['start']['hour'].updateShadowValue();
window.timeWidgets['start']['minute'].updateShadowValue();
window.timeWidgets['start']['time'].updateShadowValue();
}
else {
// End date was changed
@@ -288,17 +297,15 @@ function onAdjustTime(event) {
window.setEndDate(oldEndDate);
window.timeWidgets['end']['date'].updateShadowValue();
window.timeWidgets['end']['hour'].updateShadowValue();
window.timeWidgets['end']['minute'].updateShadowValue();
window.timeWidgets['end']['time'].updateShadowValue();
window.timeWidgets['end']['time'].onChange(); // method from SOGoTimePicker
}
}
}
function onAllDayChanged(event) {
for (var type in window.timeWidgets) {
window.timeWidgets[type]['hour'].disabled = this.checked;
window.timeWidgets[type]['minute'].disabled = this.checked;
}
for (var type in window.timeWidgets)
window.timeWidgets[type]['time'].disabled = this.checked;
}
function initTimeWidgets(widgets) {
@@ -306,14 +313,14 @@ function initTimeWidgets(widgets) {
if (widgets['start']['date']) {
widgets['start']['date'].observe("change", this.onAdjustTime, false);
widgets['start']['hour'].observe("change", this.onAdjustTime, false);
widgets['start']['minute'].observe("change", this.onAdjustTime, false);
widgets['start']['time'].observe("time:change", this.onAdjustTime, false);
widgets['start']['time'].addInterface(SOGoTimePickerInterface);
}
if (widgets['end']['date']) {
widgets['end']['date'].observe("change", this.onAdjustTime, false);
widgets['end']['hour'].observe("change", this.onAdjustTime, false);
widgets['end']['minute'].observe("change", this.onAdjustTime, false);
widgets['end']['time'].observe("time:change", this.onAdjustTime, false);
widgets['end']['time'].addInterface(SOGoTimePickerInterface);
}
var allDayLabel = $("allDay");
@@ -321,10 +328,8 @@ function initTimeWidgets(widgets) {
var input = $(allDayLabel).childNodesWithTag("input")[0];
input.observe("change", onAllDayChanged.bindAsEventListener(input));
if (input.checked) {
for (var type in widgets) {
widgets[type]['hour'].disabled = true;
widgets[type]['minute'].disabled = true;
}
for (var type in widgets)
widgets[type]['time'].disabled = true;
}
}
}
@@ -375,15 +380,15 @@ function refreshAttendees(newAttendees) {
if (attendees.keys().length > 0) {
// Update attendees link and show label
var names = new Array();
var names = new Array();
attendees.values().each(function(attendee) {
attendee = $H(attendee);
var name = attendee.get('name') || attendee.get('email');
if (!attendee.get('delegated-to'))
var delegatedTo = attendee.get('delegated-to');
if (!delegatedTo)
names.push(name);
if (attendeesMenu) {
var delegatedTo = attendee.get('delegated-to');
if (!attendee.get('delegated-from') || delegatedTo) {
var node = createElement("li");
attendeesMenu.appendChild(node);
@@ -475,11 +480,9 @@ function onAppointmentEditorLoad() {
assignCalendar('endTime_date');
var widgets = {'start': {'date': $("startTime_date"),
'hour': $("startTime_time_hour"),
'minute': $("startTime_time_minute")},
'time': $("startTime_time")},
'end': {'date': $("endTime_date"),
'hour': $("endTime_time_hour"),
'minute': $("endTime_time_minute")}};
'time': $("endTime_time")}};
initTimeWidgets(widgets);
}
+69 -2
View File
@@ -14,8 +14,9 @@ A#changeAttachButton
right: 0;
display: inline; }
SPAN.datePicker INPUT.textField
{ width: 7em; }
SPAN.datePicker INPUT.textField,
SPAN.timeDateControl INPUT.textField
{ width: 7em; }
SPAN.timeDateControl A.button
{ border: 0; }
@@ -131,3 +132,69 @@ SPAN.timeDateControl INPUT,
SPAN.timeDateControl SELECT,
SPAN.timeDateControl SPAN
{ vertical-align: top; }
/* SOGoTimePicker */
.SOGoTimePickerMenu
{ position: absolute;
z-index: 1000;
background-image: url("dialog-top.png");
background-repeat: no-repeat;
color: #000;
font-family: sans-serif;
font-size: 11px;
text-align: center; }
.SOGoTimePickerMenu > DIV
{ background-color: #fff;
border: 1px solid #444;
border-top: 0px;
margin-top: 19px;
padding: 5px; }
.SOGoTimePickerMenu SPAN DIV
{ padding: 2px; }
.SOGoTimePickerMenu DIV.hours SPAN
{ float: left;
width: 25px; }
.SOGoTimePickerMenu DIV.hours SPAN DIV
{ background-color: #ddd;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc; }
.SOGoTimePickerMenu DIV.min5 SPAN
{ float: left;
width: 50px; }
.SOGoTimePickerMenu DIV.min1 SPAN
{ float: left;
width: 60px; }
.SOGoTimePickerMenu DIV.minutes SPAN DIV
{ border-right: 1px solid #fff;
border-bottom: 1px solid #fff; }
.SOGoTimePickerMenu DIV.hours SPAN DIV:hover,
.SOGoTimePickerMenu DIV.minutes SPAN DIV:hover
{ background-color: #eee;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
color: #333;
cursor: pointer; }
.SOGoTimePickerMenu DIV.hours SPAN DIV.selected,
.SOGoTimePickerMenu DIV.minutes SPAN DIV.selected
{ background-color: #9ABCD8;
border-right: 1px solid #9ABCD8;
border-bottom: 1px solid #9ABCD8;
color: #fff; }
.SOGoTimePickerMenu HR
{ clear: both;
height: 0px;
margin: 0px;
padding: 0px;
color: #fff;
border: 0px; }
+47 -41
View File
@@ -4,16 +4,13 @@ var contactSelectorAction = 'calendars-contacts';
function uixEarlierDate(date1, date2) {
// can this be done in a sane way?
// cuicui = 'year';
if (date1 && date2) {
if (date1.getYear() < date2.getYear()) return date1;
if (date1.getYear() > date2.getYear()) return date2;
// same year
// cuicui += '/month';
if (date1.getMonth() < date2.getMonth()) return date1;
if (date1.getMonth() > date2.getMonth()) return date2;
// // same month
// cuicui += '/date';
// same month
if (date1.getDate() < date2.getDate()) return date1;
if (date1.getDate() > date2.getDate()) return date2;
}
@@ -65,23 +62,39 @@ function validateTaskEditor() {
}
else if (tmpdate == null /* means: same date */) {
// TODO: check time
var start, end;
start = parseInt(document.forms[0]['startTime_time_hour'].value);
end = parseInt(document.forms[0]['dueTime_time_hour'].value);
if (start > end) {
alert(labels.validate_endbeforestart);
return false;
}
else if (start == end) {
start = parseInt(document.forms[0]['startTime_time_minute'].value);
end = parseInt(document.forms[0]['dueTime_time_minute'].value);
if (start > end) {
alert(labels.validate_endbeforestart);
return false;
var startHour, startMinute, endHour, endMinute;
var matches;
matches = document.forms[0]['startTime_time'].value.match(/([0-9]+):([0-9]+)/);
if (matches) {
startHour = parseInt(matches[1]);
startMinute = parseInt(matches[2]);
matches = document.forms[0]['dueTime_time'].value.match(/([0-9]+):([0-9]+)/);
if (matches) {
endHour = parseInt(matches[1]);
endMinute = parseInt(matches[2]);
if (startHour > endHour) {
alert(labels.validate_endbeforestart);
return false;
}
else if (startHour == endHour) {
if (startMinute > endMinute) {
alert(labels.validate_endbeforestart);
return false;
}
}
}
else {
alert(labels.validate_invalid_enddate);
return false;
}
}
else {
alert(labels.validate_invalid_startdate);
return false;
}
}
}
}
@@ -187,19 +200,18 @@ function dueDayAsShortString() {
this._getDate = function(which) {
var date = window.timeWidgets[which]['date'].inputAsDate();
date.setHours( window.timeWidgets[which]['hour'].value );
date.setMinutes( window.timeWidgets[which]['minute'].value );
var time = window.timeWidgets[which]['time'].value.split(":");
date.setHours(time[0]);
date.setMinutes(time[1]);
return date;
};
this._getShadowDate = function(which) {
var date = window.timeWidgets[which]['date'].getAttribute("shadow-value").asDate();
var intValue = parseInt(window.timeWidgets[which]['hour'].getAttribute("shadow-value"));
date.setHours(intValue);
intValue = parseInt(window.timeWidgets[which]['minute'].getAttribute("shadow-value"));
date.setMinutes(intValue);
// window.alert("shadow: " + date);
var time = window.timeWidgets[which]['time'].getAttribute("shadow-value").split(":");
date.setHours(time[0]);
date.setMinutes(time[1]);
return date;
};
@@ -222,11 +234,7 @@ this.getShadowDueDate = function() {
this._setDate = function(which, newDate) {
window.timeWidgets[which]['date'].setInputAsDate(newDate);
window.timeWidgets[which]['hour'].value = newDate.getHours();
var minutes = newDate.getMinutes();
if (minutes % 15)
minutes += (15 - minutes % 15);
window.timeWidgets[which]['minute'].value = minutes;
window.timeWidgets[which]['time'].value = newDate.getDisplayHoursString();
};
this.setStartDate = function(newStartDate) {
@@ -250,16 +258,16 @@ this.onAdjustDueTime = function(event) {
window.setDueDate(newDueDate);
}
window.timeWidgets['start']['date'].updateShadowValue();
window.timeWidgets['start']['hour'].updateShadowValue();
window.timeWidgets['start']['minute'].updateShadowValue();
window.timeWidgets['start']['time'].updateShadowValue();
};
this.initTimeWidgets = function (widgets) {
this.timeWidgets = widgets;
widgets['start']['date'].observe("change", this.onAdjustDueTime, false);
widgets['start']['hour'].observe("change", this.onAdjustDueTime, false);
widgets['start']['minute'].observe("change", this.onAdjustDueTime, false);
widgets['start']['time'].observe("time:change", this.onAdjustDueTime, false);
widgets['start']['time'].addInterface(SOGoTimePickerInterface);
widgets['due']['time'].addInterface(SOGoTimePickerInterface);
};
function onStatusListChange(event) {
@@ -308,11 +316,9 @@ function onTaskEditorLoad() {
if (readOnly == false) {
var widgets = {'start': {'date': $("startTime_date"),
'hour': $("startTime_time_hour"),
'minute': $("startTime_time_minute")},
'time': $("startTime_time")},
'due': {'date': $("dueTime_date"),
'hour': $("dueTime_time_hour"),
'minute': $("dueTime_time_minute")}};
'time': $("dueTime_time")}};
initTimeWidgets(widgets);
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

+6 -1
View File
@@ -206,4 +206,9 @@ DIV#filtersListWrapper
{ overflow-x: hidden; }
TABLE#filtersList
{ width: auto; }
{ width: auto; }
/* UIxComponentEditor */
.SOGoTimePickerMenu > DIV
{ width: 310px; }