/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Oracle Corporation code. * * The Initial Developer of the Original Code is Oracle Corporation * Portions created by the Initial Developer are Copyright (C) 2005 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Stuart Parmenter * Joey Minta * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var gReadOnlyMode = false; // If the user clicks 'More', then we set this to true. Otherwise, we don't // load/check the stuff in this area, because it hasn't changed. var gDetailsShown = false; var gItemDuration; /* dialog stuff */ function onLoad() { var args = window.arguments[0]; window.onAcceptCallback = args.onOk; window.calendarItem = args.calendarEvent; window.mode = args.mode; window.recurrenceInfo = null; if (window.calendarItem.calendar && window.calendarItem.calendar.readOnly) { gReadOnlyMode = true; } /* add calendars to the calendar menulist */ var calendarList = document.getElementById("item-calendar"); var calendars = getCalendarManager().getCalendars({}); for (i in calendars) { var calendar = calendars[i]; var menuitem = calendarList.appendItem(calendar.name, i); menuitem.calendar = calendar; } loadDialog(window.calendarItem); // figure out what the title of the dialog should be and set it updateTitle(); // hide rows based on if this is an event or todo updateStyle(); // update the accept button updateAccept(); // update datetime pickers updateDueDate(); updateEntryDate(); // update datetime pickers updateAllDay(); // update recurrence button updateRecurrence(); // update our size! window.sizeToContent(); document.getElementById("item-title").focus(); opener.setCursor("auto"); self.focus(); } function onAccept() { // if this event isn't mutable, we need to clone it like a sheep var originalItem = window.calendarItem; var item = (originalItem.isMutable) ? originalItem : originalItem.clone(); saveDialog(item); var calendar = document.getElementById("item-calendar").selectedItem.calendar; window.onAcceptCallback(item, calendar, originalItem); return true; } function onCancel() { } function loadDialog(item) { var kDefaultTimezone = calendarDefaultTimezone(); setElementValue("item-title", item.title); setElementValue("item-location", item.getProperty("LOCATION")); /* event specific properties */ if (isEvent(item)) { var startDate = item.startDate.getInTimezone(kDefaultTimezone); var endDate = item.endDate.getInTimezone(kDefaultTimezone); gItemDuration = endDate.subtractDate(startDate); // Check if an all-day event has been passed in (to adapt endDate). if (startDate.isDate) { setElementValue("event-all-day", true, "checked"); endDate.day -= 1; gItemDuration.days -= 1; // The date/timepicker uses jsDate internally. Because jsDate does // not know the concept of dates we end up displaying times unequal // to 00:00 for all-day events depending on local timezone setting. // Calling normalize() recalculates that times to represent 00:00 // in local timezone. endDate.normalize(); startDate.normalize(); } setElementValue("event-starttime", startDate.jsDate); setElementValue("event-endtime", endDate.jsDate); document.getElementById("component-type").selectedIndex = 0; } /* todo specific properties */ if (isToDo(item)) { var hasEntryDate = (item.entryDate != null); setElementValue("todo-has-entrydate", hasEntryDate, "checked"); if (hasEntryDate) setElementValue("todo-entrydate", item.entryDate.jsDate); var hasDueDate = (item.dueDate != null); setElementValue("todo-has-duedate", hasDueDate, "checked"); if (hasDueDate) setElementValue("todo-duedate", item.dueDate.jsDate); if (hasEntryDate && hasDueDate) { gItemDuration = item.dueDate.subtractDate(item.entryDate); } document.getElementById("component-type").selectedIndex = 1; } /* item default calendar */ // If this is a new item, it might not have a calendar, but a default // option could well have been passed in. var calendarToUse = item.calendar || window.arguments[0].calendar if (calendarToUse) { var calendarList = document.getElementById("item-calendar"); var calendars = getCalendarManager().getCalendars({}); for (i in calendars) { if (calendarToUse.uri.equals(calendars[i].uri)) calendarList.selectedIndex = i; } } else { // no calendar attached to item // select first entry in calendar list as default document.getElementById("item-calendar").selectedIndex = 0; } /* Categories */ try { var categoriesString = getLocalizedPref("calendar.categories.names"); var categoriesList = categoriesString.split( "," ); // insert the category already in the menulist so it doesn't get lost var itemCategory = item.getProperty("CATEGORIES"); if (itemCategory) { if (categoriesString.indexOf(itemCategory) == -1) categoriesList[categoriesList.length] = itemCategory; } categoriesList.sort(); var oldMenulist = document.getElementById("item-categories"); while (oldMenulist.hasChildNodes()) { oldMenulist.removeChild(oldMenulist.lastChild); } var categoryMenuList = document.getElementById("item-categories"); var indexToSelect = 0; // Add a 'none' option to allow users to cancel the category var noneItem = categoryMenuList.appendItem(calGetString("calendar", "None"), "NONE"); for (var i in categoriesList) { var catItem = categoryMenuList.appendItem(categoriesList[i], categoriesList[i]); catItem.value = categoriesList[i]; if (itemCategory && categoriesList[i] == itemCategory) { indexToSelect = parseInt(i)+1; // Add 1 because of 'None' } } var newCategory = calGetString("calendar", "newCategory"); categoryMenuList.appendItem(newCategory, "##NEW"); categoryMenuList.selectedIndex = indexToSelect; gOldCatIndex = indexToSelect; } catch (ex) { // The app using this dialog doesn't support categories document.getElementById("categories-box").collapsed = true; } /* recurrence */ /* if the item is a proxy occurrence/instance, a few things aren't valid: * - Setting recurrence on the item * - changing the calendar */ if (item.parentItem != item) { setElementValue("item-recurrence", "true", "disabled"); setElementValue("set-recurrence", "true", "disabled"); setElementValue("item-calendar", "true", "disabled"); // don't allow to revoke the entrydate of recurring todo's. disableElement("todo-has-entrydate"); } else if (item.recurrenceInfo) setElementValue("item-recurrence", "true", "checked"); var detailsButton = document.getElementById("calendar-event-dialog").getButton("disclosure"); var detailsElements = document.getElementsByAttribute("details", "true"); if (document.getElementById("description-row").getAttribute("collapsed") != "true") { detailsButton.setAttribute("label", lessLabel); for each (elem in detailsElements) { elem.collapsed = false; } loadDetails(); } else { for each (elem in detailsElements) { elem.collapsed = true; } detailsButton.setAttribute("label", moreLabel); } } function saveDialog(item) { setItemProperty(item, "title", getElementValue("item-title")); setItemProperty(item, "LOCATION", getElementValue("item-location")); var kDefaultTimezone = calendarDefaultTimezone(); if (isEvent(item)) { var startDate = jsDateToDateTime(getElementValue("event-starttime")); var endDate = jsDateToDateTime(getElementValue("event-endtime")); startDate = startDate.getInTimezone(kDefaultTimezone); endDate = endDate.getInTimezone(kDefaultTimezone); var isAllDay = getElementValue("event-all-day", "checked"); if (isAllDay) { startDate.isDate = true; startDate.normalize(); endDate.isDate = true; endDate.day += 1; endDate.normalize(); } setItemProperty(item, "startDate", startDate); setItemProperty(item, "endDate", endDate); } if (isToDo(item)) { var entryDate = getElementValue("todo-has-entrydate", "checked") ? jsDateToDateTime(getElementValue("todo-entrydate")) : null; if (entryDate) { entryDate = entryDate.getInTimezone(kDefaultTimezone); } else { // no entrydate, no recurrence item.recurrenceInfo = null; window.recurrenceInfo = null; } setItemProperty(item, "entryDate", entryDate); var dueDate = getElementValue("todo-has-duedate", "checked") ? jsDateToDateTime(getElementValue("todo-duedate")) : null; if (dueDate) { dueDate = dueDate.getInTimezone(kDefaultTimezone); } setItemProperty(item, "dueDate", dueDate); var percentCompleteInteger = 0; if (getElementValue("percent-complete-textbox") != "") { percentCompleteInteger = parseInt(getElementValue("percent-complete-textbox")); } if (percentCompleteInteger < 0) { percentCompleteInteger = 0; } else if (percentCompleteInteger > 100) { percentCompleteInteger = 100; } setItemProperty(item, "PERCENT-COMPLETE", percentCompleteInteger); } /* recurrence */ if (getElementValue("item-recurrence", "checked")) { if (window.recurrenceInfo) { item.recurrenceInfo = window.recurrenceInfo; } } else { item.recurrenceInfo = null; } /* Category */ var category = getElementValue("item-categories"); if (category != "NONE") { setItemProperty(item, "CATEGORIES", category); } else { item.deleteProperty("CATEGORIES"); } if (!gDetailsShown) { // We never showed the items in the 'More' box. That means that clone() // took care of it, so just return now dump(item.icalString + '\n'); return; } setItemProperty(item, "URL", getElementValue("item-url")); setItemProperty(item, "DESCRIPTION", getElementValue("item-description")); var status; if (isEvent(item)) { status = getElementValue("event-status"); } else { status = getElementValue("todo-status"); if (status != "COMPLETED") { item.completedDate = null; } } setItemProperty(item, "STATUS", status); setItemProperty(item, "PRIORITY", getElementValue("priority-levels")); setItemProperty(item, "CLASS", getElementValue("privacy-menulist")); if (item.status == "COMPLETED" && isToDo(item)) { item.completedDate = jsDateToDateTime(getElementValue("completed-date-picker")); } /* attendence */ item.removeAllAttendees(); var attendeeListBox = document.getElementById("attendees-listbox"); for each (kid in attendeeListBox.childNodes) { if (kid.attendee) { item.addAttendee(kid.attendee); } } /* alarms */ var hasAlarm = (getElementValue("item-alarm") != "none"); if (!hasAlarm) { item.alarmOffset = null; item.alarmLastAck = null; item.alarmRelated = null; } else { var alarmLength = getElementValue("alarm-length-field"); var alarmUnits = document.getElementById("alarm-length-units").selectedItem.value; if (document.getElementById("alarm-trigger-relation").selectedItem.value == "START") { item.alarmRelated = Components.interfaces.calIItemBase.ALARM_RELATED_START; } else { item.alarmRelated = Components.interfaces.calIItemBase.ALARM_RELATED_END; } var duration = Components.classes["@mozilla.org/calendar/duration;1"] .createInstance(Components.interfaces.calIDuration); if (item.alarmRelated == Components.interfaces.calIItemBase.ALARM_RELATED_START) { duration.isNegative = true; } duration[alarmUnits] = alarmLength; duration.normalize(); item.alarmOffset = duration; } dump(item.icalString + "\n"); } function updateTitle() { var isNew = window.calendarItem.isMutable; if (isEvent(window.calendarItem)) { if (isNew) document.title = calGetString("calendar", "newEventDialog"); else document.title = calGetString("calendar", "editEventDialog"); } else if (isToDo(window.calendarItem)) { if (isNew) document.title = calGetString("calendar", "newTaskDialog"); else document.title = calGetString("calendar", "editTaskDialog"); } } function updateComponentType() { //XXX We still can't properly convert from event <-> task via QI return; } function updateStyle() { const kDialogStylesheet = "chrome://calendar/content/calendar-event-dialog.css"; for each(var stylesheet in document.styleSheets) { if (stylesheet.href == kDialogStylesheet) { if (isEvent(window.calendarItem)) stylesheet.insertRule(".todo-only { display: none; }", 0); else if (isToDo(window.calendarItem)) stylesheet.insertRule(".event-only { display: none; }", 0); return; } } } function onStartTimeChange() { if (!gItemDuration) { return; } var startWidgetId; var endWidgetId; if (isEvent(window.calendarItem)) { startWidgetId = "event-starttime"; endWidgetId = "event-endtime"; } else { if (!getElementValue("todo-has-entrydate", "checked") || !getElementValue("todo-has-duedate", "checked")) { gItemDuration = null; return; } startWidgetId = "todo-entrydate"; endWidgetId = "todo-duedate"; } var start = jsDateToDateTime(getElementValue(startWidgetId)); start.addDuration(gItemDuration); setElementValue(endWidgetId, start.getInTimezone(calendarDefaultTimezone()).jsDate); updateAccept(); } function onEndTimeChange() { var startWidgetId; var endWidgetId; if (isEvent(window.calendarItem)) { startWidgetId = "event-starttime"; endWidgetId = "event-endtime"; } else { if (!getElementValue("todo-has-entrydate", "checked") || !getElementValue("todo-has-duedate", "checked")) { gItemDuration = null; return; } startWidgetId = "todo-entrydate"; endWidgetId = "todo-duedate"; } var start = jsDateToDateTime(getElementValue(startWidgetId)); var end = jsDateToDateTime(getElementValue(endWidgetId)); gItemDuration = end.subtractDate(start); updateAccept(); } function updateAccept() { var enableAccept = true; var kDefaultTimezone = calendarDefaultTimezone(); var title = getElementValue("item-title"); if (title.length == 0) enableAccept = false; // don't allow for end dates to be before start dates var startDate; var endDate; if (isEvent(window.calendarItem)) { startDate = jsDateToDateTime(getElementValue("event-starttime")); endDate = jsDateToDateTime(getElementValue("event-endtime")); // For all-day events we are not interested in times and compare only dates. if (getElementValue("event-all-day", "checked")) { // jsDateToDateTime returnes the values in UTC. Depending on the local // timezone and the values selected in datetimepicker the date in UTC // might be shifted to the previous or next day. // For example: The user (with local timezone GMT+05) selected // Feb 10 2006 00:00:00. The corresponding value in UTC is // Feb 09 2006 19:00:00. If we now set isDate to true we end up with // a date of Feb 09 2006 instead of Feb 10 2006 resulting in errors // during the following comparison. // Calling getInTimezone() ensures that we use the same dates as // displayed to the user in datetimepicker for comparison. startDate = startDate.getInTimezone(kDefaultTimezone); endDate = endDate.getInTimezone(kDefaultTimezone); startDate.isDate = true; endDate.isDate = true; } } else { startDate = getElementValue("todo-has-entrydate", "checked") ? jsDateToDateTime(getElementValue("todo-entrydate")) : null; endDate = getElementValue("todo-has-duedate", "checked") ? jsDateToDateTime(getElementValue("todo-duedate")) : null; var taskRepeatWarning = document.getElementById("task-repeat-warning"); if (!startDate && getElementValue("item-recurrence", "checked")) { enableAccept = false; taskRepeatWarning.removeAttribute("hidden"); } else { taskRepeatWarning.setAttribute("hidden", "true"); } } var timeWarning = document.getElementById("end-time-warning"); if (endDate && startDate && endDate.compare(startDate) == -1) { enableAccept = false; timeWarning.removeAttribute("hidden"); } else { timeWarning.setAttribute("hidden", "true"); } // can't add/edit items in readOnly calendars document.getElementById("read-only-item").setAttribute("hidden", !gReadOnlyMode); var cal = document.getElementById("item-calendar").selectedItem.calendar; document.getElementById("read-only-cal").setAttribute("hidden", !cal.readOnly); if (gReadOnlyMode || cal.readOnly) { enableAccept = false; } if (!updateTaskAlarmWarnings()) { enableAccept = false; } var acceptButton = document.getElementById("calendar-event-dialog").getButton("accept"); if (!enableAccept) { acceptButton.setAttribute("disabled", "true"); } else if (acceptButton.getAttribute("disabled")) { acceptButton.removeAttribute("disabled"); } return; } function updateDueDate() { if (!isToDo(window.calendarItem)) return; // force something to get set if there was nothing there before setElementValue("todo-duedate", getElementValue("todo-duedate")); setElementValue("todo-duedate", !getElementValue("todo-has-duedate", "checked"), "disabled"); if (getElementValue("todo-has-entrydate", "checked") && getElementValue("todo-has-duedate", "checked")) { var start = jsDateToDateTime(getElementValue("todo-entrydate")); var end = jsDateToDateTime(getElementValue("todo-duedate")); gItemDuration = end.subtractDate(start); } else { gItemDuration = null; } updateAccept(); } function updateEntryDate() { if (!isToDo(window.calendarItem)) return; // force something to get set if there was nothing there before setElementValue("todo-entrydate", getElementValue("todo-entrydate")); setElementValue("todo-entrydate", !getElementValue("todo-has-entrydate", "checked"), "disabled"); if (getElementValue("todo-has-entrydate", "checked") && getElementValue("todo-has-duedate", "checked")) { var start = jsDateToDateTime(getElementValue("todo-entrydate")); var end = jsDateToDateTime(getElementValue("todo-duedate")); gItemDuration = end.subtractDate(start); } else { gItemDuration = null; } updateAccept(); } function updateTaskAlarmWarnings() { document.getElementById("alarm-start-warning").setAttribute("hidden", true); document.getElementById("alarm-end-warning").setAttribute("hidden", true); var alarmType = getElementValue("item-alarm"); if (!gDetailsShown || !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) { document.getElementById("alarm-start-warning").removeAttribute("hidden"); return false; } if (alarmRelated == "END" && !hasDueDate) { document.getElementById("alarm-end-warning").removeAttribute("hidden"); return false; } return true; } function updateAllDay() { if (!isEvent(window.calendarItem)) return; var allDay = getElementValue("event-all-day", "checked"); setElementValue("event-starttime", allDay, "timepickerdisabled"); setElementValue("event-endtime", allDay, "timepickerdisabled"); updateAccept(); } function updateRecurrence() { var recur = getElementValue("item-recurrence", "checked"); if (recur) { setElementValue("set-recurrence", false, "disabled"); } else { setElementValue("set-recurrence", "true", "disabled"); } updateAccept(); } var prevAlarmItem = null; 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 updateAlarm() { var alarmMenu = document.getElementById("item-alarm"); var alarmItem = alarmMenu.selectedItem; var alarmItemValue = alarmItem.getAttribute("value"); switch (alarmItemValue) { case "custom": /* restore old values if they're around */ setAlarmFields(alarmItem); document.getElementById("alarm-details").removeAttribute("hidden"); break; default: var customItem = document.getElementById("alarm-custom-menuitem"); if (prevAlarmItem == customItem) { customItem.setAttribute("length", getElementValue("alarm-length-field")); customItem.setAttribute("unit", getElementValue("alarm-length-units")); customItem.setAttribute("relation", getElementValue("alarm-trigger-relation")); } setAlarmFields(alarmItem); document.getElementById("alarm-details").setAttribute("hidden", true); break; } prevAlarmItem = alarmItem; updateAccept(); this.sizeToContent(); } function editRecurrence() { var args = new Object(); args.calendarEvent = window.calendarItem; args.recurrenceInfo = window.recurrenceInfo || args.calendarEvent.recurrenceInfo; var kDefaultTimezone = calendarDefaultTimezone(); if (isEvent(window.calendarItem)) { var startDate = jsDateToDateTime(getElementValue("event-starttime")).getInTimezone(kDefaultTimezone); if (getElementValue("event-all-day", "checked")) { startDate.isDate = true; startDate.normalize(); } args.startDate = startDate; } else if (isToDo(window.calendarItem)) { if (!getElementValue("todo-has-entrydate", "checked")) { return; } args.startDate = jsDateToDateTime(getElementValue("todo-entrydate")).getInTimezone(kDefaultTimezone); } var savedWindow = window; args.onOk = function(recurrenceInfo) { savedWindow.recurrenceInfo = recurrenceInfo; }; // wait cursor will revert to auto in eventDialog.js loadCalendarEventDialog window.setCursor("wait"); // open the dialog modally openDialog("chrome://calendar/content/calendar-recurrence-dialog.xul", "_blank", "chrome,titlebar,modal", args); } /* utility functions */ function setItemProperty(item, propertyName, value) { switch(propertyName) { case "startDate": if (value.isDate && !item.startDate.isDate || !value.isDate && item.startDate.isDate || value.timezone != item.startDate.timezone || value.compare(item.startDate) != 0) item.startDate = value; break; case "endDate": if (value.isDate && !item.endDate.isDate || !value.isDate && item.endDate.isDate || value.timezone != item.endDate.timezone || value.compare(item.endDate) != 0) item.endDate = value; break; case "entryDate": if (value == item.entryDate) break; if ((value && !item.entryDate) || (!value && item.entryDate) || (value.timezone != item.entryDate.timezone) || (value.compare(item.entryDate) != 0) || (value.isDate != item.entryDate.isDate)) item.entryDate = value; break; case "dueDate": if (value == item.dueDate) break; if ((value && !item.dueDate) || (!value && item.dueDate) || (value.timezone != item.dueDate.timezone) || (value.compare(item.dueDate) != 0) || (value.isDate != item.dueDate.isDate)) item.dueDate = value; break; case "isCompleted": if (value != item.isCompleted) item.isCompleted = value; break; case "title": if (value != item.title) item.title = value; break; default: if (!value || value == "") item.deleteProperty(propertyName); else if (item.getProperty(propertyName) != value) item.setProperty(propertyName, value); break; } } function toggleDetails() { var detailsElements = document.getElementsByAttribute("details", "true"); var detailsButton = document.getElementById("calendar-event-dialog").getButton("disclosure"); if (!detailsElements[0].collapsed) { // Hide details for each (elem in detailsElements) { elem.collapsed = true; } detailsButton.setAttribute("label", moreLabel); this.sizeToContent(); return; } // Display details for each (elem in detailsElements) { elem.collapsed = false; } detailsButton.setAttribute("label", lessLabel); this.sizeToContent(); if (gDetailsShown) { // We've already loaded this stuff before, so we're done return; } loadDetails(); } function loadDetails() { gDetailsShown = true; var item = window.calendarItem; /* attendence */ var attendeeString = ""; var attendeeListBox = document.getElementById("attendees-listbox"); var child; while ((child = attendeeListBox.lastChild) && (child.tagName == "listitem")) { attendeeListBox.removeChild(child); } for each (var attendee in item.getAttendees({})) { var listItem = document.createElement("listitem"); var nameCell = document.createElement("listcell"); nameCell.setAttribute("label", attendee.id.split("MAILTO:")[1]); listItem.appendChild(nameCell); listItem.attendee = attendee; attendeeListBox.appendChild(listItem); } /* Status */ setElementValue("item-url", item.getProperty("URL")); setElementValue("item-description", item.getProperty("DESCRIPTION")); if (isEvent(item)) { setElementValue("event-status", item.getProperty("STATUS")); } else { setElementValue("todo-status", item.getProperty("STATUS")); } /* Task completed date */ if (item.completedDate) { updateToDoStatus(item.status, item.completedDate.jsDate); } else { updateToDoStatus(item.status); } /* Task percent complete */ if (isToDo(item)) { var percentCompleteInteger = 0; var percentCompleteProperty = item.getProperty("PERCENT-COMPLETE"); if (percentCompleteProperty != null) { percentCompleteInteger = parseInt(percentCompleteProperty); } if (percentCompleteInteger < 0) { percentCompleteInteger = 0; } else if (percentCompleteInteger > 100) { percentCompleteInteger = 100; } setElementValue("percent-complete-textbox", percentCompleteInteger); } /* Priority */ var priorityInteger = parseInt(item.priority); if (priorityInteger >= 1 && priorityInteger <= 4) { document.getElementById("priority-levels").selectedIndex = 3; // high priority } else if (priorityInteger == 5) { document.getElementById("priority-levels").selectedIndex = 2; // medium priority } else if (priorityInteger >= 6 && priorityInteger <= 9) { document.getElementById("priority-levels").selectedIndex = 1; // low priority } else { document.getElementById("priority-levels").selectedIndex = 0; // not defined } /* Privacy */ switch (item.privacy) { case "PUBLIC": case "PRIVATE": case "CONFIDENTIAL": setElementValue("privacy-menulist", item.privacy); break; case "": setElementValue("private-menulist", "PUBLIC"); break; default: // bogus value dump("ERROR! Event has invalid privacy string: " + item.privacy + "\n"); break; } /* alarms */ if (item.alarmOffset) { var alarmRelatedStart = (item.alarmRelated == Components.interfaces.calIItemBase.ALARM_RELATED_START); if (alarmRelatedStart) { setElementValue("alarm-trigger-relation", "START"); } else { setElementValue("alarm-trigger-relation", "END"); } var offset = item.alarmOffset; if (offset.minutes) { var minutes = offset.minutes + offset.hours*60 + offset.days*24*60 + offset.weeks*60*24*7; // Special cases for the common alarms if ((minutes == 15) && alarmRelatedStart) { document.getElementById("item-alarm").selectedIndex = 2; } else if ((minutes == 30) && alarmRelatedStart) { document.getElementById("item-alarm").selectedIndex = 3; } else { setElementValue("alarm-length-field", minutes); setElementValue("alarm-length-units", "minutes"); setElementValue("item-alarm", "custom"); } } else if (offset.hours) { var hours = offset.hours + offset.days*24 + offset.weeks*24*7; setElementValue("alarm-length-field", hours); setElementValue("alarm-length-units", "hours"); setElementValue("item-alarm", "custom"); } else { // days var days = offset.days + offset.weeks*7; setElementValue("alarm-length-field", days); setElementValue("alarm-length-units", "days"); setElementValue("item-alarm", "custom"); } } // update alarm checkbox/label/settings button updateAlarm(); updateTaskAlarmWarnings(); updateURL(item.getProperty("URL")); return; } function updateToDoStatus(status, passedInCompletedDate) { // RFC2445 doesn't support completedDates without the todo's status // being "COMPLETED", however twiddling the status menulist shouldn't // destroy that information at this point (in case you change status // back to COMPLETED). When we go to store this VTODO as .ics the // date will get lost. var completedDate; if (passedInCompletedDate) { completedDate = passedInCompletedDate; } else { completedDate = null; } // remember the original values var oldPercentComplete = getElementValue("percent-complete-textbox"); var oldCompletedDate = getElementValue("completed-date-picker"); switch (status) { case null: case "": case "NONE": document.getElementById("todo-status").selectedIndex = 0; disableElement("percent-complete-textbox"); disableElement("percent-complete-label"); break; case "CANCELLED": document.getElementById("todo-status").selectedIndex = 4; disableElement("percent-complete-textbox"); disableElement("percent-complete-label"); break; case "COMPLETED": document.getElementById("todo-status").selectedIndex = 3; enableElement("percent-complete-textbox"); enableElement("percent-complete-label"); // if there isn't a completedDate, set it to now if (!completedDate) completedDate = new Date(); break; case "IN-PROCESS": document.getElementById("todo-status").selectedIndex = 2; disableElement("completed-date-picker"); enableElement("percent-complete-textbox"); enableElement("percent-complete-label"); break; case "NEEDS-ACTION": document.getElementById("todo-status").selectedIndex = 1; enableElement("percent-complete-textbox"); enableElement("percent-complete-label"); break; } if (status == "COMPLETED") { setElementValue("percent-complete-textbox", "100"); setElementValue("completed-date-picker", completedDate); enableElement("completed-date-picker"); } else { if (oldPercentComplete != 100) { setElementValue("percent-complete-textbox", oldPercentComplete); } else { setElementValue("percent-complete-textbox", ""); } setElementValue("completed-date-picker", oldCompletedDate); disableElement("completed-date-picker"); } } function updateURL(aValue) { var button = document.getElementById("load-url-button"); button.setAttribute("disabled", true) if (!aValue) { return; } // The user might have just put in 'www.foo.com', correct that here if (aValue.indexOf( ":" ) == -1) { aValue = "http://" + aValue; } try { makeURL(aValue); // If we made it this far, that means it's a valid url button.removeAttribute("disabled"); } catch(ex) {} return; } function loadURL() { var url = getElementValue("item-url"); // The user might have just put in 'www.foo.com', correct that here if (url.indexOf( ":" ) == -1) { url = "http://" + url; } launchBrowser(url); return; } var gOldCatIndex = 0; function categorySelect(aValue) { if (aValue != "##NEW") { gOldCatIndex = document.getElementById("item-categories").selectedIndex; return; } // Make sure we don't leave 'New..' selected if they hit cancel document.getElementById("item-categories").selectedIndex = gOldCatIndex; window.openDialog("chrome://calendar/content/preferences/editCategory.xul", "addCategory", "modal,centerscreen,chrome,resizable=no", "", null, calGetString("calendar", "addCategory")); } // Trick the dialog into thinking we're the categories pane var gCategoriesPane = { saveCategory: function eventDialog_saveCategory(aName, aColor) { //Check to make sure another category doesn't have the same name var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(Components.interfaces.nsIPromptService); var categoriesString = getLocalizedPref("calendar.categories.names"); var categoriesList = categoriesString.split( "," ); for each (cat in categoriesList) { if (aName.toLowerCase() == cat.toLowerCase()) { var repTitle = calGetString("calendar", "categoryReplaceTitle"); var rep = calGetString("calendar", "categoryReplace"); if (promptService.confirm(null, repTitle, rep)) { var categoryNameFix = aName.toLowerCase().replace(' ','_'); setPref("calendar.category.color."+categoryNameFix, "CHAR", aColor); } return; } } if (aName.length == 0) { promptService.alert(null, null, noBlankCategories); return; } categoriesList.push(aName); categoriesList.sort(); setLocalizedPref("calendar.categories.names", categoriesList.join(',')); if (aColor) { var categoryNameFix = aName.toLowerCase().replace(' ','_'); setPref("calendar.category.color."+categoryNameFix, "CHAR", aColor); } var catList = document.getElementById("item-categories"); var index = categoriesList.indexOf(aName); catList.insertItemAt(index, aName, aName); catList.selectedIndex = index; } };