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 @@ -