diff --git a/mozilla/calendar/base/content/calendar-dialog-utils.js b/mozilla/calendar/base/content/calendar-dialog-utils.js
index fdd7477249b..c224f78b8b0 100644
--- a/mozilla/calendar/base/content/calendar-dialog-utils.js
+++ b/mozilla/calendar/base/content/calendar-dialog-utils.js
@@ -81,6 +81,59 @@ function disableElement(elementId)
setElementValue(elementId, "true", "disabled");
}
+/**
+ * This function unconditionally disables the element for
+ * which the id has been passed as argument. Furthermore, it
+ * remembers who was responsible for this action by using
+ * the given key (lockId). In case the control should be
+ * enabled again the lock gets removed, but the control only
+ * gets enabled if *all* possibly held locks have been removed.
+ */
+function disableElementWithLock(elementId,lockId) {
+
+ // unconditionally disable the element.
+ disableElement(elementId);
+
+ // remember that this element has been locked with
+ // the key passed as argument. we keep a primitive
+ // form of ref-count in the attribute 'lock'.
+ var element = document.getElementById(elementId);
+ if (element) {
+ if (!element.hasAttribute(lockId)) {
+ element.setAttribute(lockId, "true");
+ var n = parseInt(element.getAttribute("lock") || 0);
+ element.setAttribute("lock", n + 1);
+ }
+ }
+}
+
+/**
+ * This function is intended to be used in tandem with the
+ * above defined function 'disableElementWithLock()'.
+ * See the respective comment for further details.
+ */
+function enableElementWithLock(elementId, lockId) {
+
+ var element = document.getElementById(elementId);
+ if (!element) {
+ dump("unable to find " + elementId + "\n");
+ return;
+ }
+
+ if (element.hasAttribute(lockId)) {
+ element.removeAttribute(lockId);
+ var n = parseInt(element.getAttribute("lock") || 0) - 1;
+ if (n > 0) {
+ element.setAttribute("lock", n);
+ } else {
+ element.removeAttribute("lock");
+ }
+ if (n <= 0) {
+ enableElement(elementId);
+ }
+ }
+}
+
/* use with textfields oninput to only allow integers */
function validateIntegerRange(event, lowerBound, upperBound) {
validateIntegers(event);
@@ -764,16 +817,17 @@ function saveReminder(item) {
}
function commonUpdateReminder() {
- // find relevant elements in the document
- var reminderPopup = document.getElementById("item-alarm");
- var reminderDetails = document.getElementById("reminder-details");
-
- // if a custom reminder was selected, we show the appropriate
+ // if a custom reminder has been selected, we show the appropriate
// dialog in order to allow the user to specify the details.
// the result will be placed in the 'reminder-custom-menuitem' tag.
+ var reminderPopup = document.getElementById("item-alarm");
if (reminderPopup.value == 'custom') {
// show the dialog.
- editReminder();
+ // don't pop up the dialog if this happens during
+ // initialization of the dialog.
+ if (reminderPopup.hasAttribute("last-value")) {
+ editReminder();
+ }
// Now check if the resulting custom reminder is valid.
// possibly we receive an invalid reminder if the user cancels the
@@ -786,6 +840,70 @@ function commonUpdateReminder() {
// remember the current reminder drop down selection index.
gLastAlarmSelection = reminderPopup.selectedIndex;
+ reminderPopup.setAttribute("last-value", reminderPopup.value);
+
+ // possibly the selected reminder conflicts with the item.
+ // for example an end-relation combined with a task without duedate
+ // is an invalid state we need to take care of. we take the same
+ // approach as with recurring tasks. in case the reminder is related
+ // to the entry date we check the entry date automatically and disable
+ // the checkbox. the same goes for end related reminder and the due date.
+ if (isToDo(window.calendarItem)) {
+
+ // custom reminder entries carry their own reminder object
+ // with them, pre-defined entries specify the necessary information
+ // as attributes attached to the menuitem elements.
+ var menuitem = reminderPopup.selectedItem;
+ if (menuitem.value == 'none') {
+ enableElementWithLock("todo-has-entrydate", "reminder-lock");
+ enableElementWithLock("todo-has-duedate", "reminder-lock");
+ } else {
+ var reminder = menuitem.reminder;
+ if (!reminder) {
+ reminder = {};
+ reminder.length = menuitem.getAttribute('length');
+ reminder.unit = menuitem.getAttribute('unit');
+ reminder.relation = menuitem.getAttribute('relation');
+ reminder.origin = menuitem.getAttribute('origin');
+ }
+
+ // if this reminder is related to the entry date...
+ if (Number(reminder.origin) > 0) {
+
+ // ...automatically check 'has entrydate'.
+ if (!getElementValue("todo-has-entrydate", "checked")) {
+ setElementValue("todo-has-entrydate", "true", "checked");
+
+ // make sure gStartTime is properly initialized
+ updateEntryDate();
+ }
+
+ // disable the checkbox to indicate that we need
+ // the entry-date. the 'disabled' state will be
+ // revoked if the user turns off the repeat pattern.
+ disableElementWithLock("todo-has-entrydate", "reminder-lock");
+ enableElementWithLock("todo-has-duedate", "reminder-lock");
+ }
+
+ // if this reminder is related to the due date...
+ if (Number(reminder.origin) < 0) {
+
+ // ...automatically check 'has duedate'.
+ if (!getElementValue("todo-has-duedate", "checked")) {
+ setElementValue("todo-has-duedate", "true", "checked");
+
+ // make sure gStartTime is properly initialized
+ updateDueDate();
+ }
+
+ // disable the checkbox to indicate that we need
+ // the entry-date. the 'disabled' state will be
+ // revoked if the user turns off the repeat pattern.
+ disableElementWithLock("todo-has-duedate", "reminder-lock");
+ enableElementWithLock("todo-has-entrydate", "reminder-lock");
+ }
+ }
+ }
updateReminderDetails();
}
diff --git a/mozilla/calendar/prototypes/wcap/sun-calendar-event-dialog.js b/mozilla/calendar/prototypes/wcap/sun-calendar-event-dialog.js
index aecca43c5ff..9588408ce70 100644
--- a/mozilla/calendar/prototypes/wcap/sun-calendar-event-dialog.js
+++ b/mozilla/calendar/prototypes/wcap/sun-calendar-event-dialog.js
@@ -429,7 +429,8 @@ function loadDialog(item) {
updateTitle();
updateAttendees();
- updateReminderDetails();
+ updateRepeat();
+ updateReminder();
// How easy would it be to just call hasProperty(), but unfortunately
// this is currently flawed and doesn't give us the answer we're longing for.
@@ -1029,10 +1030,6 @@ function updateAccept() {
enableAccept = false;
}
- if (!updateTaskAlarmWarnings()) {
- enableAccept = false;
- }
-
var accept = document.getElementById("cmd_accept");
if (enableAccept) {
accept.removeAttribute('disabled');
@@ -1043,39 +1040,6 @@ function updateAccept() {
return enableAccept;
}
-function updateTaskAlarmWarnings() {
- var alarmType = getElementValue("item-alarm");
- if (!isToDo(window.calendarItem) ||
- alarmType == "none") {
- return true;
- }
-
- var hasEntryDate =
- getElementValue(
- "todo-has-entrydate",
- "checked");
- var hasDueDate =
- getElementValue(
- "todo-has-duedate",
- "checked");
-
- var alarmRelated = document.getElementById("alarm-trigger-relation")
- .selectedItem.value;
-
- if ((alarmType != "custom" ||
- alarmRelated == "START") &&
- !hasEntryDate) {
- return false;
- }
-
- if (alarmRelated == "END" &&
- !hasDueDate) {
- return false;
- }
-
- return true;
-}
-
// this function sets the enabled/disabled
// state of the following controls:
// - 'event-starttime'
@@ -1125,17 +1089,6 @@ function updateAllDay() {
updateAccept();
}
-function setAlarmFields(alarmItem) {
- var alarmLength = alarmItem.getAttribute("length");
- if (alarmLength != "") {
- var alarmUnits = alarmItem.getAttribute("unit");
- var alarmRelation = alarmItem.getAttribute("relation");
- setElementValue("alarm-length-field", alarmLength);
- setElementValue("alarm-length-units", alarmUnits);
- setElementValue("alarm-trigger-relation", alarmRelation);
- }
-}
-
function openNewEvent() {
var item = window.calendarItem;
var args = window.arguments[0];
@@ -1515,12 +1468,7 @@ function updateCalendar() {
setElementValue("item-calendar", "true", "disabled");
// don't allow to revoke the entrydate of recurring todo's.
- disableElement("todo-has-entrydate");
- }
-
- // don't allow to revoke the entrydate of recurring todo's.
- if (window.recurrenceInfo) {
- disableElement("todo-has-entrydate");
+ disableElementWithLock("todo-has-entrydate", "permanent-lock");
}
// update datetime pickers
@@ -1554,10 +1502,12 @@ function editRepeat() {
args);
}
-// This function is called after the 'repeat pattern' selection has been
-// changed. As a consequence we need to create/modify recurrence rules or
-// bring up the custom 'repeat pattern'-dialog and modify states of several
-// elements of the document (i.e. task entrydate, etc.)
+/**
+ * This function is responsilble for propagating UI state to controls
+ * depending on the repeat setting of an item. This functionality is used
+ * after the dialog has been loaded as well as if the repeat pattern has
+ * been changed.
+ */
function updateRepeat() {
var repeatMenu = document.getElementById("item-repeat");
var repeatItem = repeatMenu.selectedItem;
@@ -1567,7 +1517,7 @@ function updateRepeat() {
window.recurrenceInfo = null;
var item = window.calendarItem;
if (isToDo(item)) {
- enableElement("todo-has-entrydate");
+ enableElementWithLock("todo-has-entrydate", "repeat-lock");
}
} else if (repeatValue == 'custom') {
// the user selected custom repeat pattern. we now need to bring
@@ -1590,7 +1540,7 @@ function updateRepeat() {
// disable the checkbox to indicate that we need
// the entry-date. the 'disabled' state will be
// revoked if the user turns off the repeat pattern.
- disableElement("todo-has-entrydate");
+ disableElementWithLock("todo-has-entrydate", "repeat-lock");
}
// retrieve the current recurrence info, we need this
@@ -1599,7 +1549,11 @@ function updateRepeat() {
var recurrenceInfo = window.recurrenceInfo;
// now bring up the recurrence dialog.
- editRepeat();
+ // don't pop up the dialog if this happens during
+ // initialization of the dialog.
+ if (repeatMenu.hasAttribute("last-value")) {
+ editRepeat();
+ }
// we need to address two separate cases here.
// 1) we need to revoke the selection of the repeat
@@ -1611,7 +1565,7 @@ function updateRepeat() {
repeatMenu.selectedIndex = gLastRepeatSelection;
if (isToDo(item)) {
if (!window.recurrenceInfo) {
- enableElement("todo-has-entrydate");
+ enableElementWithLock("todo-has-entrydate", "repeat-lock");
}
}
}
@@ -1677,13 +1631,16 @@ function updateRepeat() {
if (!getElementValue("todo-has-entrydate", "checked")) {
setElementValue("todo-has-entrydate", "true", "checked");
}
- disableElement("todo-has-entrydate");
+ disableElementWithLock("todo-has-entrydate", "repeat-lock");
}
}
gLastRepeatSelection = repeatMenu.selectedIndex;
+ repeatMenu.setAttribute("last-value", repeatValue);
updateRepeatDetails();
+ updateEntryDate();
+ updateDueDate();
updateAccept();
}
@@ -2211,12 +2168,12 @@ function updateAttendees() {
}
function updateRepeatDetails() {
- // Don't try to show the details text for anything but a custom recurrence
- // rule. Also, we don't currently support tasks.
+ // Don't try to show the details text for
+ // anything but a custom recurrence rule.
var item = window.calendarItem;
var recurrenceInfo = window.recurrenceInfo;
var itemRepeat = document.getElementById("item-repeat");
- if (itemRepeat.value == "custom" && isEvent(item) && recurrenceInfo) {
+ if (itemRepeat.value == "custom" && recurrenceInfo) {
var startDate = jsDateToDateTime(getElementValue("event-starttime"));
var endDate = jsDateToDateTime(getElementValue("event-endtime"));
var kDefaultTimezone = calendarDefaultTimezone();
diff --git a/mozilla/calendar/prototypes/wcap/sun-calendar-event-dialog.xul b/mozilla/calendar/prototypes/wcap/sun-calendar-event-dialog.xul
index 56c61e63f37..1bcbbe677c2 100644
--- a/mozilla/calendar/prototypes/wcap/sun-calendar-event-dialog.xul
+++ b/mozilla/calendar/prototypes/wcap/sun-calendar-event-dialog.xul
@@ -481,22 +481,6 @@
-
-
-
-
-
-
@@ -714,7 +698,7 @@
-
+
@@ -803,7 +787,7 @@
-
+