Bug 1277972 - Let event/task dialog open in a tab. r=MakeMyDay
authorPaul Morris <paul@paulwmorris.com>
Thu, 21 Jul 2016 23:20:10 -0400
changeset 25805 341f2588de6410bb151926249dd334317785a0d7
parent 25804 7f35b399aa0050d2cdc1f83e7aac54230b9d03e1
child 25806 79420fdeab5bd6b9ab8c1fb69dd818572182aa54
push id1771
push userclokep@gmail.com
push dateMon, 14 Nov 2016 17:47:53 +0000
treeherdercomm-beta@399ae9d71595 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMakeMyDay
bugs1277972
Bug 1277972 - Let event/task dialog open in a tab. r=MakeMyDay
calendar/base/content/calendar-chrome-startup.js
calendar/base/content/calendar-item-editing.js
calendar/base/content/dialogs/calendar-dialog-utils.js
calendar/base/content/dialogs/calendar-event-dialog.js
calendar/base/content/dialogs/calendar-event-dialog.xul
calendar/base/jar.mn
calendar/base/themes/common/calendar-attendees.css
calendar/base/themes/common/dialogs/calendar-event-dialog.css
calendar/base/themes/common/dialogs/images/calendar-event-tab.png
calendar/base/themes/common/dialogs/images/calendar-task-tab.png
calendar/lightning/content/lightning-item-iframe.js
calendar/lightning/content/lightning-item-iframe.xul
calendar/lightning/content/lightning-item-panel.js
calendar/lightning/content/lightning-item-panel.xul
calendar/lightning/content/lightning-item-toolbar.xul
calendar/lightning/content/lightning.js
calendar/lightning/content/messenger-overlay-sidebar.js
calendar/lightning/content/messenger-overlay-sidebar.xul
calendar/lightning/jar.mn
calendar/lightning/themes/linux/lightning.css
calendar/test/mozmill/testLocalICS.js
calendar/test/mozmill/testTodayPane.js
--- a/calendar/base/content/calendar-chrome-startup.js
+++ b/calendar/base/content/calendar-chrome-startup.js
@@ -143,29 +143,53 @@ var calendarWindowPrefs = {
     }
 }
 
 /**
  * Migrate calendar UI. This function is called at each startup and can be used
  * to change UI items that require js code intervention
  */
 function migrateCalendarUI() {
-    const UI_VERSION = 1;
+    const UI_VERSION = 2;
     let currentUIVersion = Preferences.get("calendar.ui.version");
-
     if (currentUIVersion >= UI_VERSION) {
         return;
     }
 
     try {
         if (currentUIVersion < 1) {
             let calbar = document.getElementById("calendar-toolbar2");
             calbar.insertItem("calendar-appmenu-button");
             let taskbar = document.getElementById("task-toolbar2");
             taskbar.insertItem("task-appmenu-button");
         }
+        if (currentUIVersion < 2) {
+            // If the user has customized the event/task window dialog toolbar,
+            // we copy that custom set of toolbar items to the event/task tab
+            // toolbar and add the app menu button and a spring for alignment.
+            let xulStore = Components.classes["@mozilla.org/xul/xulstore;1"]
+                                     .getService(Components.interfaces.nsIXULStore);
+            let uri = "chrome://calendar/content/calendar-event-dialog.xul";
 
+            if (xulStore.hasValue(uri, "event-toolbar", "currentset")) {
+                let windowSet = xulStore.getValue(uri, "event-toolbar", "currentset");
+                let items = "calendar-item-appmenu-button";
+                if (!windowSet.includes("spring")) {
+                    items = "spring," + items;
+                }
+                let previousSet = windowSet == "__empty" ? "" : windowSet + ",";
+                let tabSet = previousSet + items;
+                let tabBar = document.getElementById("event-tab-toolbar");
+
+                tabBar.currentSet = tabSet;
+                // For some reason we also have to do the following,
+                // presumably because the toolbar has already been
+                // loaded into the DOM so the toolbar's currentset
+                // attribute does not yet match the new currentSet.
+                tabBar.setAttribute("currentset", tabSet);
+            }
+        }
         Preferences.set("calendar.ui.version", UI_VERSION);
     } catch (e) {
         cal.ERROR("Error upgrading UI from " + currentUIVersion + " to " +
                   UI_VERSION + ": " + e);
     }
 }
--- a/calendar/base/content/calendar-item-editing.js
+++ b/calendar/base/content/calendar-item-editing.js
@@ -437,16 +437,17 @@ function openEventDialog(calendarItem, c
     // Setup the window arguments
     var args = new Object();
     args.calendarEvent = calendarItem;
     args.calendar = calendar;
     args.mode = mode;
     args.onOk = callback;
     args.job = job;
     args.initialStartDateValue = (initialDate || getDefaultStartDate());
+    args.inTab = Preferences.get("calendar.item.editInTab", false);
 
     // this will be called if file->new has been selected from within the dialog
     args.onNewEvent = function(calendar) {
         createEventWithDialog(calendar, null, null);
     };
     args.onNewTodo = function(calendar) {
         createTodoWithDialog(calendar);
     };
@@ -457,37 +458,51 @@ function openEventDialog(calendarItem, c
     // ask the provide if this item is an invitation. if this is the case
     // we'll open the summary dialog since the user is not allowed to change
     // the details of the item.
     let wrappedCalendar = cal.wrapInstance(calendar, Components.interfaces.calISchedulingSupport);
     let isInvitation = wrappedCalendar && wrappedCalendar.isInvitation(calendarItem);
 
     // open the dialog modeless
     let url;
-    if (isCalendarWritable(calendar)
-        && (mode == "new"
-            || (mode == "modify" && !isInvitation && userCanModifyItem((calendarItem))))) {
-        url = "chrome://calendar/content/calendar-event-dialog.xul";
+    let isEditable = mode == "modify" && !isInvitation && userCanModifyItem(calendarItem);
+    if (isCalendarWritable(calendar) && (mode == "new" || isEditable)) {
+        if (args.inTab) {
+            url = "chrome://lightning/content/lightning-item-iframe.xul";
+        } else {
+            url = "chrome://calendar/content/calendar-event-dialog.xul";
+        }
     } else {
         url = "chrome://calendar/content/calendar-summary-dialog.xul";
+        args.inTab = false;
     }
 
-    // reminder: event dialog should not be modal (cf bug 122671)
-    var features;
-    // keyword "dependent" should not be used (cf bug 752206)
-    if (Services.appinfo.OS == "WINNT") {
-        features = "chrome,titlebar,resizable";
-    } else if (Services.appinfo.OS == "Darwin") {
-        features = "chrome,titlebar,resizable,minimizable=no";
+    if (args.inTab) {
+        // open in a tab, currently the read-only summary dialog is
+        // never opened in a tab
+        args.url = url;
+        let tabmail = document.getElementById('tabmail');
+        let tabtype = cal.isEvent(args.calendarEvent) ? 'calendarEvent' : 'calendarTask';
+        tabmail.openTab(tabtype, args);
     } else {
-        // All other targets, mostly Linux flavors using gnome.
-        features = "chrome,titlebar,resizable,minimizable=no,dialog=no";
+        // open in a window
+
+        // reminder: event dialog should not be modal (cf bug 122671)
+        let features;
+        // keyword "dependent" should not be used (cf bug 752206)
+        if (Services.appinfo.OS == "WINNT") {
+            features = "chrome,titlebar,resizable";
+        } else if (Services.appinfo.OS == "Darwin") {
+            features = "chrome,titlebar,resizable,minimizable=no";
+        } else {
+            // All other targets, mostly Linux flavors using gnome.
+            features = "chrome,titlebar,resizable,minimizable=no,dialog=no";
+        }
+        openDialog(url, "_blank", features, args);
     }
-
-    openDialog(url, "_blank", features, args);
 }
 
 /**
  * Prompts the user how the passed item should be modified. If the item is an
  * exception or already a parent item, the item is returned without prompting.
  * If "all occurrences" is specified, the parent item is returned. If "this
  * occurrence only" is specified, then aItem is returned. If "this and following
  * occurrences" is selected, aItem's parentItem is modified so that the
--- a/calendar/base/content/dialogs/calendar-dialog-utils.js
+++ b/calendar/base/content/dialogs/calendar-dialog-utils.js
@@ -5,16 +5,35 @@
 Components.utils.import("resource://gre/modules/PluralForm.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/iteratorUtils.jsm");
 
 Components.utils.import("resource://calendar/modules/calAlarmUtils.jsm");
 Components.utils.import("resource://calendar/modules/calIteratorUtils.jsm");
 Components.utils.import("resource://calendar/modules/calRecurrenceUtils.jsm");
 
+// Variables related to whether we are in a tab or a window dialog.
+var gInTab = false;
+var gMainWindow = null;
+var gTabmail = null;
+
+/**
+ * Initialize variables for tab vs window.
+ */
+function intializeTabOrWindowVariables() {
+    let args = window.arguments[0];
+    gInTab = args.inTab;
+    if (gInTab) {
+        gTabmail = parent.document.getElementById("tabmail");
+        gMainWindow = parent;
+    } else {
+        gMainWindow = parent.opener;
+    }
+}
+
 /**
  * Dispose of controlling operations of this event dialog. Uses
  * window.arguments[0].job.dispose()
  */
 function dispose() {
     var args = window.arguments[0];
     if (args.job && args.job.dispose) {
         args.job.dispose();
@@ -470,22 +489,22 @@ function commonUpdateReminder(aSuppressD
                     updateDueDate();
                 }
 
                 // Disable the checkbox to indicate that we need the entry-date.
                 disableElementWithLock("todo-has-duedate", "reminder-lock");
             }
         }
     }
-
     updateReminderDetails();
 }
 
 /**
- * Updates the related link on the dialog
+ * Updates the related link on the dialog. Currently only used by the
+ * read-only summary dialog.
  */
 function updateLink() {
     var itemUrlString = window.calendarItem.getProperty("URL") || "";
     var linkCommand = document.getElementById("cmd_toggle_link");
 
     function hideOrShow(aBool) {
         setElementValue("event-grid-link-row", !aBool && "true", "hidden");
         var separator = document.getElementById("event-grid-link-separator");
--- a/calendar/base/content/dialogs/calendar-event-dialog.xul
+++ b/calendar/base/content/dialogs/calendar-event-dialog.xul
@@ -19,1388 +19,626 @@
     <!ENTITY % calendarDTD SYSTEM "chrome://calendar/locale/calendar.dtd">
     <!ENTITY % eventDialogDTD SYSTEM "chrome://calendar/locale/calendar-event-dialog.dtd">
     %brandDTD;
     %globalDTD;
     %calendarDTD;
     %eventDialogDTD;
 ]>
 
+<?xul-overlay href="chrome://lightning/content/lightning-item-toolbar.xul"?>
+
 <!-- Dialog id is changed during excution to allow different Window-icons
      on this dialog. document.loadOverlay() will not work on this one. -->
 <dialog id="calendar-event-dialog"
         title="&event.title.label;"
         windowtype="Calendar:EventDialog"
         onload="onLoad();"
-        onunload="onEventDialogUnload();"
         ondialogaccept="return onAccept();"
         ondialogcancel="return onCancel();"
-        onresize="rearrangeAttendees();"
         persist="screenX screenY width height"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
-    <stringbundleset id="stringbundleset">
-      <stringbundle id="languageBundle"
-                    src="chrome://global/locale/languageNames.properties"/>
-    </stringbundleset>
+  <!-- Javascript includes -->
+  <script type="application/javascript"
+          src="chrome://lightning/content/lightning-item-panel.js"/>
+  <script type="application/javascript"
+          src="chrome://calendar/content/calendar-dialog-utils.js"/>
+  <script type="application/javascript"
+          src="chrome://calendar/content/calendar-ui-utils.js"/>
+  <script type="application/javascript"
+          src="chrome://global/content/globalOverlay.js"/>
+
+  <stringbundleset id="stringbundleset">
+    <stringbundle id="languageBundle"
+                  src="chrome://global/locale/languageNames.properties"/>
+  </stringbundleset>
 
-    <!-- Javascript includes -->
-    <script type="application/javascript"
-            src="chrome://calendar/content/calendar-event-dialog.js"/>
-    <script type="application/javascript"
-            src="chrome://calendar/content/calendar-dialog-utils.js"/>
-    <script type="application/javascript"
-            src="chrome://calendar/content/calendar-ui-utils.js"/>
-    <script type="application/javascript"
-            src="chrome://calendar/content/calUtils.js"/>
-    <script type="application/javascript"
-            src="chrome://calendar/content/calApplicationUtils.js"/>
-    <script type="application/javascript"
-            src="chrome://global/content/globalOverlay.js"/>
-    <script type="application/javascript"
-            src="chrome://global/content/printUtils.js"/>
-    <script type="application/javascript"
-            src="chrome://calendar/content/calendar-statusbar.js"/>
-    <script type="application/javascript"
-            src="chrome://messenger/content/toolbarIconColor.js"/>
+  <!-- Command updater -->
+  <commandset id="globalEditMenuItems"
+              commandupdater="true"
+              events="focus"
+              oncommandupdate="goUpdateGlobalEditMenuItems()"/>
+  <commandset id="selectEditMenuItems"
+              commandupdater="true"
+              events="select"
+              oncommandupdate="goUpdateSelectEditMenuItems()"/>
+  <commandset id="undoEditMenuItems"
+              commandupdater="true"
+              events="undo"
+              oncommandupdate="goUpdateUndoEditMenuItems()"/>
+  <commandset id="clipboardEditMenuItems"
+              commandupdater="true"
+              events="clipboard"
+              oncommandupdate="goUpdatePasteMenuItems()"/>
 
-    <!-- Command updater -->
-    <commandset id="globalEditMenuItems"
-                commandupdater="true"
-                events="focus"
-                oncommandupdate="goUpdateGlobalEditMenuItems()"/>
-    <commandset id="selectEditMenuItems"
-                commandupdater="true"
-                events="select"
-                oncommandupdate="goUpdateSelectEditMenuItems()"/>
-    <commandset id="undoEditMenuItems"
-                commandupdater="true"
-                events="undo"
-                oncommandupdate="goUpdateUndoEditMenuItems()"/>
-    <commandset id="clipboardEditMenuItems"
-                commandupdater="true"
-                events="clipboard"
-                oncommandupdate="goUpdatePasteMenuItems()"/>
-
-    <!-- Commands -->
-    <commandset id="itemCommands">
+  <!-- Commands -->
+  <commandset id="itemCommands">
 
-        <!-- Item menu -->
-        <command id="cmd_item_new_event"
-                 oncommand="openNewEvent()"/>
-        <command id="cmd_item_new_task"
-                 oncommand="openNewTask()"/>
-        <command id="cmd_item_new_message"
-                 oncommand="openNewMessage()"/>
-        <command id="cmd_item_new_card"
-                 oncommand="openNewCardDialog()"/>
-        <command id="cmd_item_close"
-                 oncommand="cancelDialog()"/>
-        <command id="cmd_save"
-                 disable-on-readonly="true"
-                 oncommand="onCommandSave()"/>
-        <command id="cmd_item_delete"
-                 disable-on-readonly="true"
-                 oncommand="onCommandDeleteItem()"/>
-        <command id="cmd_printSetup"
-                 oncommand="PrintUtils.showPageSetup()"/>
-        <command id="cmd_print"
-                 disabled="true"
-                 oncommand="calPrint()"/>
+    <!-- Item menu -->
+    <command id="cmd_item_new_event"
+             oncommand="openNewEvent()"/>
+    <command id="cmd_item_new_task"
+             oncommand="openNewTask()"/>
+    <command id="cmd_item_new_message"
+             oncommand="openNewMessage()"/>
+    <command id="cmd_item_new_card"
+             oncommand="openNewCardDialog()"/>
+    <command id="cmd_item_close"
+             oncommand="cancelDialog()"/>
+    <command id="cmd_save"
+             disable-on-readonly="true"
+             oncommand="onCommandSave()"/>
+    <command id="cmd_item_delete"
+             disable-on-readonly="true"
+             oncommand="onCommandDeleteItem()"/>
+    <command id="cmd_printSetup"
+             oncommand="PrintUtils.showPageSetup()"/>
+    <command id="cmd_print"
+             disabled="true"
+             oncommand="calPrint()"/>
 
-        <!-- Edit menu -->
-        <command id="cmd_undo"
-                 disabled="true"
-                 oncommand="goDoCommand('cmd_undo')"/>
-        <command id="cmd_redo"
-                 disabled="true"
-                 oncommand="goDoCommand('cmd_redo')"/>
-        <command id="cmd_cut"
-                 disabled="true"
-                 oncommand="goDoCommand('cmd_cut')"/>
-        <command id="cmd_copy"
-                 disabled="true"
-                 oncommand="goDoCommand('cmd_copy')"/>
-        <command id="cmd_paste"
-                 disabled="true"
-                 oncommand="goDoCommand('cmd_paste')"/>
-        <command id="cmd_selectAll"
-                 disabled="true"
-                 oncommand="goDoCommand('cmd_selectAll')"/>
+    <!-- Edit menu -->
+    <command id="cmd_undo"
+             disabled="true"
+             oncommand="goDoCommand('cmd_undo')"/>
+    <command id="cmd_redo"
+             disabled="true"
+             oncommand="goDoCommand('cmd_redo')"/>
+    <command id="cmd_cut"
+             disabled="true"
+             oncommand="goDoCommand('cmd_cut')"/>
+    <command id="cmd_copy"
+             disabled="true"
+             oncommand="goDoCommand('cmd_copy')"/>
+    <command id="cmd_paste"
+             disabled="true"
+             oncommand="goDoCommand('cmd_paste')"/>
+    <command id="cmd_selectAll"
+             disabled="true"
+             oncommand="goDoCommand('cmd_selectAll')"/>
 
-        <!-- View menu -->
-        <command id="cmd_toolbar"
-                 oncommand="onCommandViewToolbar('event-toolbar',
-                                                 'view-toolbars-event-menuitem')"/>
-        <command id="cmd_customize"
-                 oncommand="onCommandCustomize()"/>
-        <command id="cmd_toggle_link"
-                 persist="checked"
-                 oncommand="toggleLink()"/>
+    <!-- View menu -->
+    <command id="cmd_toolbar"
+             oncommand="onCommandViewToolbar('event-toolbar',
+                                             'view-toolbars-event-menuitem')"/>
+    <command id="cmd_customize"
+             oncommand="onCommandCustomize()"/>
+    <command id="cmd_toggle_link"
+             persist="checked"
+             oncommand="toggleLink()"/>
 
-        <!-- Toolbar commands -->
-        <command id="cmd_accept"
-                 disable-on-readonly="true"
-                 oncommand="acceptDialog();"/>
-        <command id="cmd_recurrence"
-                 oncommand="editRepeat();"/>
-        <command id="cmd_attendees"
-                 oncommand="editAttendees();"/>
-        <command id="cmd_email"
-                 oncommand="sendMailToAttendees(window.attendees);"/>
-        <command id="cmd_email_undecided"
-                 oncommand="sendMailToUndecidedAttendees(window.attendees);"/>
-        <command id="cmd_status_none"
-                 oncommand="editStatus(event.target)"
-                 hidden="true"
-                 value="NONE"/>
-        <command id="cmd_status_tentative"
-                 oncommand="editStatus(event.target)"
-                 value="TENTATIVE"/>
-        <command id="cmd_status_confirmed"
-                 oncommand="editStatus(event.target)"
-                 value="CONFIRMED"/>
-        <command id="cmd_status_cancelled"
-                 oncommand="editStatus(event.target)"
-                 value="CANCELLED"/>
-        <command id="cmd_priority_none"
-                 oncommand="editPriority(event.target)"
-                 value="0"/>
-        <command id="cmd_priority_low"
-                 oncommand="editPriority(event.target)"
-                 value="9"/>
-        <command id="cmd_priority_normal"
-                 oncommand="editPriority(event.target)"
-                 value="5"/>
-        <command id="cmd_priority_high"
-                 oncommand="editPriority(event.target)"
-                 value="1"/>
-        <command id="cmd_showtimeas_busy"
-                 oncommand="editShowTimeAs(event.target)"
-                 value="OPAQUE"/>
-        <command id="cmd_showtimeas_free"
-                 oncommand="editShowTimeAs(event.target)"
-                 value="TRANSPARENT"/>
-        <command id="cmd_attach_url"
-                 disable-on-readonly="true"
-                 oncommand="attachURL()"/>
-        <command id="cmd_attach_cloud"
-                 disable-on-readonly="true"/>
-        <command id="cmd_openAttachment"
-                 oncommand="openAttachment()"/>
-        <command id="cmd_copyAttachment"
-                 oncommand="copyAttachment()"/>
-        <command id="cmd_deleteAttachment"
-                 disable-on-readonly="true"
-                 oncommand="deleteAttachment()"/>
-        <command id="cmd_deleteAllAttachments"
-                 disable-on-readonly="true"
-                 oncommand="deleteAllAttachments()"/>
-        <command id="cmd_timezone"
-                 persist="checked"
-                 checked="false"
-                 oncommand="toggleTimezoneLinks()"/>
-    </commandset>
+    <!-- status -->
+    <command id="cmd_status_none"
+             oncommand="editStatus(event.target)"
+             hidden="true"
+             value="NONE"/>
+    <command id="cmd_status_tentative"
+             oncommand="editStatus(event.target)"
+             value="TENTATIVE"/>
+    <command id="cmd_status_confirmed"
+             oncommand="editStatus(event.target)"
+             value="CONFIRMED"/>
+    <command id="cmd_status_cancelled"
+             oncommand="editStatus(event.target)"
+             value="CANCELLED"/>
+
+    <!-- priority -->
+    <command id="cmd_priority_none"
+             oncommand="editPriority(event.target)"
+             value="0"/>
+    <command id="cmd_priority_low"
+             oncommand="editPriority(event.target)"
+             value="9"/>
+    <command id="cmd_priority_normal"
+             oncommand="editPriority(event.target)"
+             value="5"/>
+    <command id="cmd_priority_high"
+             oncommand="editPriority(event.target)"
+             value="1"/>
+
+    <!-- freebusy -->
+    <command id="cmd_showtimeas_busy"
+             oncommand="editShowTimeAs(event.target)"
+             value="OPAQUE"/>
+    <command id="cmd_showtimeas_free"
+             oncommand="editShowTimeAs(event.target)"
+             value="TRANSPARENT"/>
+
+    <!-- attendees -->
+    <command id="cmd_attendees"
+             oncommand="editAttendees();"/>
+    <command id="cmd_email"
+             oncommand="sendMailToAttendees(window.attendees);"/>
+    <command id="cmd_email_undecided"
+             oncommand="sendMailToUndecidedAttendees(window.attendees);"/>
+
+    <!-- accept, attachments, timezone -->
+    <command id="cmd_accept"
+             disable-on-readonly="true"
+             oncommand="acceptDialog();"/>
+    <command id="cmd_attach_url"
+             disable-on-readonly="true"
+             oncommand="attachURL()"/>
+    <command id="cmd_timezone"
+             persist="checked"
+             checked="false"
+             oncommand="toggleTimezoneLinks()"/>
+  </commandset>
 
-    <keyset id="calendar-event-dialog-keyset">
-        <key id="new-event-key"
-             modifiers="accel"
-             key="&event.dialog.new.event.key2;"
-             command="cmd_item_new_event"/>
-        <key id="new-task-key"
-             modifiers="accel"
-             key="&event.dialog.new.task.key2;"
-             command="cmd_item_new_task"/>
-        <key id="new-message-key"
-             modifiers="accel"
-             key="&event.dialog.new.message.key2;"
-             command="cmd_item_new_message"/>
-        <key id="close-key"
-             modifiers="accel"
-             key="&event.dialog.close.key;"
-             command="cmd_item_close"/>
-        <key id="save-key"
-             modifiers="accel"
-             key="&event.dialog.save.key;"
-             command="cmd_save"/>
-        <key id="saveandclose-key"
-             modifiers="accel"
-             key="&event.dialog.saveandclose.key;"
-             command="cmd_accept"/>
-        <key id="saveandclose-key2"
-             modifiers="accel"
-             keycode="VK_RETURN"
-             command="cmd_accept"/>
-        <key id="print-key"
-             modifiers="accel"
-             key="&event.dialog.print.key;"
-             command="cmd_print"/>
-        <key id="undo-key"
-             modifiers="accel"
-             key="&event.dialog.undo.key;"
-             command="cmd_undo"/>
-        <key id="redo-key"
-             modifiers="accel"
-             key="&event.dialog.redo.key;"
-             command="cmd_redo"/>
-        <key id="cut-key"
-             modifiers="accel"
-             key="&event.dialog.cut.key;"
-             command="cmd_cut"/>
-        <key id="copy-key"
-             modifiers="accel"
-             key="&event.dialog.copy.key;"
-             command="cmd_copy"/>
-        <key id="paste-key"
-             modifiers="accel"
-             key="&event.dialog.paste.key;"
-             command="cmd_paste"/>
-        <key id="select-all-key"
-             modifiers="accel"
-             key="&event.dialog.select.all.key;"
-             command="cmd_selectAll"/>
-    </keyset>
+  <keyset id="calendar-event-dialog-keyset">
+    <key id="new-event-key"
+         modifiers="accel"
+         key="&event.dialog.new.event.key2;"
+         command="cmd_item_new_event"/>
+    <key id="new-task-key"
+         modifiers="accel"
+         key="&event.dialog.new.task.key2;"
+         command="cmd_item_new_task"/>
+    <key id="new-message-key"
+         modifiers="accel"
+         key="&event.dialog.new.message.key2;"
+         command="cmd_item_new_message"/>
+    <key id="close-key"
+         modifiers="accel"
+         key="&event.dialog.close.key;"
+         command="cmd_item_close"/>
+    <key id="save-key"
+         modifiers="accel"
+         key="&event.dialog.save.key;"
+         command="cmd_save"/>
+    <key id="saveandclose-key"
+         modifiers="accel"
+         key="&event.dialog.saveandclose.key;"
+         command="cmd_accept"/>
+    <key id="saveandclose-key2"
+         modifiers="accel"
+         keycode="VK_RETURN"
+         command="cmd_accept"/>
+    <key id="print-key"
+         modifiers="accel"
+         key="&event.dialog.print.key;"
+         command="cmd_print"/>
+    <key id="undo-key"
+         modifiers="accel"
+         key="&event.dialog.undo.key;"
+         command="cmd_undo"/>
+    <key id="redo-key"
+         modifiers="accel"
+         key="&event.dialog.redo.key;"
+         command="cmd_redo"/>
+    <key id="cut-key"
+         modifiers="accel"
+         key="&event.dialog.cut.key;"
+         command="cmd_cut"/>
+    <key id="copy-key"
+         modifiers="accel"
+         key="&event.dialog.copy.key;"
+         command="cmd_copy"/>
+    <key id="paste-key"
+         modifiers="accel"
+         key="&event.dialog.paste.key;"
+         command="cmd_paste"/>
+    <key id="select-all-key"
+         modifiers="accel"
+         key="&event.dialog.select.all.key;"
+         command="cmd_selectAll"/>
+  </keyset>
 
   <menupopup id="event-dialog-toolbar-context-menu">
     <menuitem id="CustomizeDialogToolbar"
               label="&event.menu.view.toolbars.customize.label;"
               command="cmd_customize"/>
   </menupopup>
 
-  <!-- Toolbox contains the toolbar and menubar -->
-    <toolbox id="event-toolbox"
-             class="toolbox-top"
-             mode="full"
-             defaultmode="full"
+  <!-- Toolbox contains the menubar -->
+  <toolbox id="event-toolbox"
+           class="mail-toolbox"
+           mode="full"
+           defaultmode="full"
 #ifdef XP_MACOSX
-             iconsize="small"
-             defaulticonsize="small"
+           iconsize="small"
+           defaulticonsize="small"
 #endif
-             labelalign="end"
-             defaultlabelalign="end">
-
-        <!-- Menubar -->
-        <menubar id="event-menubar">
+           labelalign="end"
+           defaultlabelalign="end">
 
-            <!-- Item menu -->
-                  <!-- These 2 Strings are placeholders, values are set at runtime -->
-            <menu label="Item"
-                  accesskey="I"
-                  id="item-menu">
-                <menupopup id="item-menupopup">
-                    <menu id="item-new-menu"
-                          label="&event.menu.item.new.label;"
-                          accesskey="&event.menu.item.new.accesskey;">
-                        <menupopup id="item-new-menupopup">
-                            <menuitem id="item-new-message-menuitem"
-                                      label="&event.menu.item.new.message.label;"
-                                      accesskey="&event.menu.item.new.message.accesskey;"
-                                      key="new-message-key"
-                                      command="cmd_item_new_message"
-                                      disable-on-readonly="true"/>
-                            <menuitem id="item-new-event-menuitem"
-                                      label="&event.menu.item.new.event.label;"
-                                      accesskey="&event.menu.item.new.event.accesskey;"
-                                      key="new-event-key"
-                                      command="cmd_item_new_event"
-                                      disable-on-readonly="true"/>
-                            <menuitem id="item-new-task-menuitem"
-                                      label="&event.menu.item.new.task.label;"
-                                      accesskey="&event.menu.item.new.task.accesskey;"
-                                      key="new-task-key"
-                                      command="cmd_item_new_task"
-                                      disable-on-readonly="true"/>
-                            <menuseparator id="item-new-menuseparator1"/>
-                            <menuitem id="item-new-address-menuitem"
-                                      label="&event.menu.item.new.contact.label;"
-                                      accesskey="&event.menu.item.new.contact.accesskey;"
-                                      command="cmd_item_new_card"
-                                      disable-on-readonly="true"/>
-                        </menupopup>
-                    </menu>
-                    <menuseparator id="item-menuseparator1"/>
-                    <menuitem id="item-save-menuitem"
-                              label="&event.menu.item.save.label;"
-                              accesskey="&event.menu.item.save.accesskey;"
-                              key="save-key"
-                              command="cmd_save"/>
-                    <menuitem id="item-saveandclose-menuitem"
-                              label="&event.menu.item.saveandclose.label;"
-                              accesskey="&event.menu.item.saveandclose.accesskey;"
-                              key="saveandclose-key"
-                              command="cmd_accept"/>
-                    <menuitem id="item-delete-menuitem"
-                              label="&event.menu.item.delete.label;"
-                              accesskey="&event.menu.item.delete.accesskey;"
-                              command="cmd_item_delete"
-                              disable-on-readonly="true"/>
-                    <menuitem id="item-pagesetup-menuitem"
-                              label="&event.menu.item.page.setup.label;"
-                              accesskey="&event.menu.item.page.setup.accesskey;"
-                              command="cmd_printSetup"
-                              disable-on-readonly="true"/>
-                    <menuitem id="item-print-menuitem"
-                              label="&event.menu.item.print.label;"
-                              accesskey="&event.menu.item.print.accesskey;"
-                              key="print-key"
-                              command="cmd_print"
-                              disable-on-readonly="true"/>
-                    <menuseparator id="item-menuseparator1"/>
-                    <menuitem id="item-close-menuitem"
-                              label="&event.menu.item.close.label;"
-                              accesskey="&event.menu.item.close.accesskey;"
-                              key="close-key"
-                              command="cmd_item_close"
-                              disable-on-readonly="true"/>
-                </menupopup>
-            </menu>
-
-            <!-- Edit menu -->
-            <menu id="edit-menu"
-                  label="&event.menu.edit.label;"
-                  accesskey="&event.menu.edit.accesskey;"
-                  collapse-on-readonly="true">
-                <menupopup id="edit-menupopup">
-                    <menuitem id="edit-undo-menuitem"
-                              label="&event.menu.edit.undo.label;"
-                              accesskey="&event.menu.edit.undo.accesskey;"
-                              key="undo-key"
-                              command="cmd_undo"/>
-                    <menuitem id="edit-redo-menuitem"
-                              label="&event.menu.edit.redo.label;"
-                              accesskey="&event.menu.edit.redo.accesskey;"
-                              key="redo-key"
-                              command="cmd_redo"/>
-                    <menuseparator id="edit-menuseparator1"/>
-                    <menuitem id="edit-cut-menuitem"
-                              label="&event.menu.edit.cut.label;"
-                              accesskey="&event.menu.edit.cut.accesskey;"
-                              key="cut-key"
-                              command="cmd_cut"/>
-                    <menuitem id="edit-copy-menuitem"
-                              label="&event.menu.edit.copy.label;"
-                              accesskey="&event.menu.edit.copy.accesskey;"
-                              key="copy-key"
-                              command="cmd_copy"/>
-                    <menuitem id="edit-paste-menuitem"
-                              label="&event.menu.edit.paste.label;"
-                              accesskey="&event.menu.edit.paste.accesskey;"
-                              key="paste-key"
-                              command="cmd_paste"/>
-                    <menuseparator id="edit-menuseparator2"/>
-                    <menuitem id="edit-selectall-menuitem"
-                              label="&event.menu.edit.select.all.label;"
-                              accesskey="&event.menu.edit.select.all.accesskey;"
-                              key="select-all-key"
-                              command="cmd_selectAll"/>
-                </menupopup>
-            </menu>
-
-            <!-- View menu -->
-            <menu id="view-menu"
-                  label="&event.menu.view.label;"
-                  accesskey="&event.menu.view.accesskey;"
-                  collapse-on-readonly="true">
-                <menupopup id="view-menupopup">
-                    <menu id="view-toolbars-menu"
-                          label="&event.menu.view.toolbars.label;"
-                          accesskey="&event.menu.view.toolbars.accesskey;">
-                        <menupopup id="view-toolbars-menupopup">
-                            <menuitem id="view-toolbars-event-menuitem"
-                                      label="&event.menu.view.toolbars.event.label;"
-                                      accesskey="&event.menu.view.toolbars.event.accesskey;"
-                                      type="checkbox"
-                                      checked="true"
-                                      command="cmd_toolbar"/>
-                            <menuseparator id="view-toolbars-menuseparator1"/>
-                            <menuitem id="view-toolbars-customize-menuitem"
-                                      label="&event.menu.view.toolbars.customize.label;"
-                                      accesskey="&event.menu.view.toolbars.customize.accesskey;"
-                                      command="cmd_customize"/>
-                        </menupopup>
-                    </menu>
-                    <menuseparator id="view-menu-toolbars-separator"/>
-                    <menuitem id="view-show-link-menuitem"
-                              label="&event.menu.view.showlink.label;"
-                              accesskey="&event.menu.view.showlink.accesskey;"
-                              type="checkbox"
-                              command="cmd_toggle_link"
-                              observes="cmd_toggle_link"/>
-                </menupopup>
-            </menu>
+    <!-- Menubar -->
+    <menubar id="event-menubar">
 
-            <!-- Options menu -->
-            <menu id="options-menu"
-                  label="&event.menu.options.label;"
-                  accesskey="&event.menu.options.accesskey;">
-                <menupopup id="options-menupopup">
-                  <menuitem id="options-attendees-menuitem"
-                            label="&event.menu.options.attendees.label;"
-                            accesskey="&event.menu.options.attendees.accesskey;"
-                            command="cmd_attendees"
-                            disable-on-readonly="true"/>
-                  <menu id="options-attachments-menu"
-                        label="&event.attachments.menubutton.label;"
-                        accesskey="&event.attachments.menubutton.accesskey;">
-                    <menupopup id="options-attachments-menupopup">
-                      <menuitem id="options-attachments-url-menuitem"
-                                label="&event.attachments.url.label;"
-                                accesskey="&event.attachments.url.accesskey;"
-                                command="cmd_attach_url"/>
-                    </menupopup>
-                  </menu>
-                  <menuitem id="options-timezones-menuitem"
-                            label="&event.menu.options.timezone2.label;"
-                            accesskey="&event.menu.options.timezone2.accesskey;"
-                            type="checkbox"
-                            command="cmd_timezone"
-                            disable-on-readonly="true"/>
-                  <menuseparator id="options-menuseparator1"/>
-                  <menu id="options-priority-menu"
-                        label="&event.menu.options.priority2.label;"
-                        accesskey="&event.menu.options.priority2.accesskey;"
-                        disable-on-readonly="true">
-                      <menupopup id="options-priority-menupopup">
-                          <menuitem id="options-priority-none-menuitem"
-                                    label="&event.menu.options.priority.notspecified.label;"
-                                    accesskey="&event.menu.options.priority.notspecified.accesskey;"
-                                    type="radio"
-                                    command="cmd_priority_none"
-                                    disable-on-readonly="true"/>
-                          <menuitem id="options-priority-low-menuitem"
-                                    label="&event.menu.options.priority.low.label;"
-                                    accesskey="&event.menu.options.priority.low.accesskey;"
-                                    type="radio"
-                                    command="cmd_priority_low"
-                                    disable-on-readonly="true"/>
-                          <menuitem id="options-priority-normal-label"
-                                    label="&event.menu.options.priority.normal.label;"
-                                    accesskey="&event.menu.options.priority.normal.accesskey;"
-                                    type="radio"
-                                    command="cmd_priority_normal"
-                                    disable-on-readonly="true"/>
-                          <menuitem id="options-priority-high-label"
-                                    label="&event.menu.options.priority.high.label;"
-                                    accesskey="&event.menu.options.priority.high.accesskey;"
-                                    type="radio"
-                                    command="cmd_priority_high"
-                                    disable-on-readonly="true"/>
-                      </menupopup>
-                  </menu>
-                  <menu id="options-privacy-menu"
-                        label="&event.menu.options.privacy.label;"
-                        accesskey="&event.menu.options.privacy.accesskey;"
-                        disable-on-readonly="true">
-                      <menupopup id="options-privacy-menupopup">
-                          <menuitem id="options-privacy-public-menuitem"
-                                    label="&event.menu.options.privacy.public.label;"
-                                    accesskey="&event.menu.options.privacy.public.accesskey;"
-                                    type="radio"
-                                    privacy="PUBLIC"
-                                    oncommand="editPrivacy(this, event)"
-                                    disable-on-readonly="true"/>
-                          <menuitem id="options-privacy-confidential-menuitem"
-                                    label="&event.menu.options.privacy.confidential.label;"
-                                    accesskey="&event.menu.options.privacy.confidential.accesskey;"
-                                    type="radio"
-                                    privacy="CONFIDENTIAL"
-                                    oncommand="editPrivacy(this, event)"
-                                    disable-on-readonly="true"/>
-                          <menuitem id="options-privacy-private-menuitem"
-                                    label="&event.menu.options.privacy.private.label;"
-                                    accesskey="&event.menu.options.privacy.private.accesskey;"
-                                    type="radio"
-                                    privacy="PRIVATE"
-                                    oncommand="editPrivacy(this, event)"
-                                    disable-on-readonly="true"/>
-                      </menupopup>
-                  </menu>
-                  <menu id="options-status-menu"
-                        label="&newevent.status.label;"
-                        accesskey="&newevent.status.accesskey;"
-                        class="event-only"
-                        disable-on-readonly="true">
-                    <menupopup id="options-status-menupopup">
-                      <menuitem id="options-status-none-menuitem"
-                                label="&newevent.eventStatus.none.label;"
-                                accesskey="&newevent.eventStatus.none.accesskey;"
-                                type="radio"
-                                command="cmd_status_none"
-                                disable-on-readonly="true"/>
-                      <menuitem id="options-status-tentative-menuitem"
-                                label="&newevent.status.tentative.label;"
-                                accesskey="&newevent.status.tentative.accesskey;"
-                                type="radio"
-                                command="cmd_status_tentative"
-                                disable-on-readonly="true"/>
-                      <menuitem id="options-status-confirmed-menuitem"
-                                label="&newevent.status.confirmed.label;"
-                                accesskey="&newevent.status.confirmed.accesskey;"
-                                type="radio"
-                                command="cmd_status_confirmed"
-                                disable-on-readonly="true"/>
-                      <menuitem id="options-status-canceled-menuitem"
-                                label="&newevent.eventStatus.cancelled.label;"
-                                accesskey="&newevent.eventStatus.cancelled.accesskey;"
-                                type="radio"
-                                command="cmd_status_cancelled"
-                                disable-on-readonly="true"/>
-                    </menupopup>
-                  </menu>
-                  <menuseparator id="options-menuseparator2" class="event-only"/>
-                  <menu id="options-freebusy-menu"
-                        class="event-only"
-                        label="&event.menu.options.show.time.label;"
-                        accesskey="&event.menu.options.show.time.accesskey;"
-                        disable-on-readonly="true">
-                      <menupopup id="options-freebusy-menupopup">
-                          <menuitem id="options-freebusy-busy-menuitem"
-                                    label="&event.menu.options.show.time.busy.label;"
-                                    accesskey="&event.menu.options.show.time.busy.accesskey;"
-                                    type="radio"
-                                    command="cmd_showtimeas_busy"
-                                    disable-on-readonly="true"/>
-                          <menuitem id="options-freebusy-free-menuitem"
-                                    label="&event.menu.options.show.time.free.label;"
-                                    accesskey="&event.menu.options.show.time.free.accesskey;"
-                                    type="radio"
-                                    command="cmd_showtimeas_free"
-                                    disable-on-readonly="true"/>
-                      </menupopup>
-                  </menu>
-                </menupopup>
-            </menu>
-        </menubar>
+      <!-- Item menu -->
+      <!-- These 2 Strings are placeholders, values are set at runtime -->
+      <menu label="Item"
+            accesskey="I"
+            id="item-menu">
+        <menupopup id="item-menupopup">
+          <menu id="item-new-menu"
+                label="&event.menu.item.new.label;"
+                accesskey="&event.menu.item.new.accesskey;">
+            <menupopup id="item-new-menupopup">
+              <menuitem id="item-new-message-menuitem"
+                        label="&event.menu.item.new.message.label;"
+                        accesskey="&event.menu.item.new.message.accesskey;"
+                        key="new-message-key"
+                        command="cmd_item_new_message"
+                        disable-on-readonly="true"/>
+              <menuitem id="item-new-event-menuitem"
+                        label="&event.menu.item.new.event.label;"
+                        accesskey="&event.menu.item.new.event.accesskey;"
+                        key="new-event-key"
+                        command="cmd_item_new_event"
+                        disable-on-readonly="true"/>
+              <menuitem id="item-new-task-menuitem"
+                        label="&event.menu.item.new.task.label;"
+                        accesskey="&event.menu.item.new.task.accesskey;"
+                        key="new-task-key"
+                        command="cmd_item_new_task"
+                        disable-on-readonly="true"/>
+              <menuseparator id="item-new-menuseparator1"/>
+              <menuitem id="item-new-address-menuitem"
+                        label="&event.menu.item.new.contact.label;"
+                        accesskey="&event.menu.item.new.contact.accesskey;"
+                        command="cmd_item_new_card"
+                        disable-on-readonly="true"/>
+            </menupopup>
+          </menu>
+          <menuseparator id="item-menuseparator1"/>
+          <menuitem id="item-save-menuitem"
+                    label="&event.menu.item.save.label;"
+                    accesskey="&event.menu.item.save.accesskey;"
+                    key="save-key"
+                    command="cmd_save"/>
+          <menuitem id="item-saveandclose-menuitem"
+                    label="&event.menu.item.saveandclose.label;"
+                    accesskey="&event.menu.item.saveandclose.accesskey;"
+                    key="saveandclose-key"
+                    command="cmd_accept"/>
+          <menuitem id="item-delete-menuitem"
+                    label="&event.menu.item.delete.label;"
+                    accesskey="&event.menu.item.delete.accesskey;"
+                    command="cmd_item_delete"
+                    disable-on-readonly="true"/>
+          <menuitem id="item-pagesetup-menuitem"
+                    label="&event.menu.item.page.setup.label;"
+                    accesskey="&event.menu.item.page.setup.accesskey;"
+                    command="cmd_printSetup"
+                    disable-on-readonly="true"/>
+          <menuitem id="item-print-menuitem"
+                    label="&event.menu.item.print.label;"
+                    accesskey="&event.menu.item.print.accesskey;"
+                    key="print-key"
+                    command="cmd_print"
+                    disable-on-readonly="true"/>
+          <menuseparator id="item-menuseparator1"/>
+          <menuitem id="item-close-menuitem"
+                    label="&event.menu.item.close.label;"
+                    accesskey="&event.menu.item.close.accesskey;"
+                    key="close-key"
+                    command="cmd_item_close"
+                    disable-on-readonly="true"/>
+        </menupopup>
+      </menu>
 
-        <!-- Toolbar -->
-        <toolbarpalette id="event-toolbarpalette">
-            <toolbarbutton id="button-save"
-                           mode="dialog"
-                           class="cal-event-toolbarbutton toolbarbutton-1"
-                           label="&event.toolbar.save.label;"
-                           tooltiptext="&event.toolbar.save.tooltip;"
-                           command="cmd_accept"/>
-            <toolbarbutton id="button-attendees"
-                           mode="dialog"
-                           class="cal-event-toolbarbutton toolbarbutton-1 event-only"
-                           disable-on-readonly="true"
-                           label="&event.toolbar.attendees.label;"
-                           tooltiptext="&event.toolbar.attendees.tooltip;"
-                           command="cmd_attendees"/>
-            <toolbarbutton id="button-privacy"
-                           mode="dialog"
-                           class="cal-event-toolbarbutton toolbarbutton-1"
-                           type="menu-button"
-                           disable-on-readonly="true"
-                           label="&event.toolbar.privacy.label;"
-                           tooltiptext="&event.toolbar.privacy.tooltip;"
-                           oncommand="rotatePrivacy()">
-                <menupopup id="event-privacy-menupopup">
-                    <menuitem id="event-privacy-public-menuitem"
-                              name="event-privacy-group"
-                              label="&event.menu.options.privacy.public.label;"
-                              type="radio"
-                              privacy="PUBLIC"
-                              oncommand="editPrivacy(this, event)"/>
-                    <menuitem id="event-privacy-confidential-menuitem"
-                              name="event-privacy-group"
-                              label="&event.menu.options.privacy.confidential.label;"
-                              type="radio"
-                              privacy="CONFIDENTIAL"
-                              oncommand="editPrivacy(this, event)"/>
-                    <menuitem id="event-privacy-private-menuitem"
-                              name="event-privacy-group"
-                              label="&event.menu.options.privacy.private.label;"
-                              type="radio"
-                              privacy="PRIVATE"
-                              oncommand="editPrivacy(this, event)"/>
-                </menupopup>
-            </toolbarbutton>
-            <toolbarbutton id="button-url"
-                           type="menu-button"
-                           mode="dialog"
-                           class="cal-event-toolbarbutton toolbarbutton-1"
-                           label="&event.attachments.menubutton.label;"
-                           tooltiptext="&event.toolbar.attachments.tooltip;"
-                           command="cmd_attach_url"
-                           disable-on-readonly="true">
-              <menupopup id="button-attach-menupopup">
-                <menuitem id="button-attach-url"
-                          label="&event.attachments.url.label;"
-                          command="cmd_attach_url"/>
-              </menupopup>
-            </toolbarbutton>
-            <toolbarbutton id="button-delete"
-                           mode="dialog"
-                           class="cal-event-toolbarbutton toolbarbutton-1"
-                           label="&event.toolbar.delete.label;"
-                           tooltiptext="&event.toolbar.delete.tooltip;"
-                           command="cmd_item_delete"
-                           disable-on-readonly="true"/>
-            <toolbarbutton id="button-priority"
-                           mode="dialog"
-                           class="cal-event-toolbarbutton toolbarbutton-1"
-                           type="menu-button"
-                           disable-on-readonly="true"
-                           label="&event.menu.options.priority2.label;"
-                           tooltiptext="&event.toolbar.priority.tooltip;"
-                           oncommand="rotatePriority()">
-                <menupopup id="event-priority-menupopup">
-                    <menuitem id="event-priority-none-menuitem"
-                              name="event-priority-group"
-                              label="&event.menu.options.priority.notspecified.label;"
-                              type="radio"
-                              command="cmd_priority_none"/>
-                    <menuitem id="event-priority-low-menuitem"
-                              name="event-priority-group"
-                              label="&event.menu.options.priority.low.label;"
-                              type="radio"
-                              command="cmd_priority_low"/>
-                    <menuitem id="event-priority-normal-menuitem"
-                              name="event-priority-group"
-                              label="&event.menu.options.priority.normal.label;"
-                              type="radio"
-                              command="cmd_priority_normal"/>
-                    <menuitem id="event-priority-high-menuitem"
-                              name="event-priority-group"
-                              label="&event.menu.options.priority.high.label;"
-                              type="radio"
-                              command="cmd_priority_high"/>
-                </menupopup>
-            </toolbarbutton>
-            <toolbarbutton id="button-status"
-                           mode="dialog"
-                           class="cal-event-toolbarbutton toolbarbutton-1 event-only"
-                           type="menu-button"
-                           disable-on-readonly="true"
-                           label="&newevent.status.label;"
-                           tooltiptext="&event.toolbar.status.tooltip;"
-                           oncommand="rotateStatus()">
-                <menupopup id="event-status-menupopup">
-                    <menuitem id="event-status-none-menuitem"
-                              name="event-status-group"
-                              label="&newevent.eventStatus.none.label;"
-                              type="radio"
-                              command="cmd_status_none"/>
-                    <menuitem id="event-status-tentative-menuitem"
-                              name="event-status-group"
-                              label="&newevent.status.tentative.label;"
-                              type="radio"
-                              command="cmd_status_tentative"/>
-                    <menuitem id="event-status-confirmed-menuitem"
-                              name="event-status-group"
-                              label="&newevent.status.confirmed.label;"
-                              type="radio"
-                              command="cmd_status_confirmed"/>
-                    <menuitem id="event-status-cancelled-menuitem"
-                              name="event-status-group"
-                              label="&newevent.eventStatus.cancelled.label;"
-                              type="radio"
-                              command="cmd_status_cancelled"/>
-                </menupopup>
-            </toolbarbutton>
-            <toolbarbutton id="button-freebusy"
-                           mode="dialog"
-                           class="cal-event-toolbarbutton toolbarbutton-1 event-only"
-                           type="menu-button"
-                           disable-on-readonly="true"
-                           label="&event.menu.options.show.time.label;"
-                           tooltiptext="&event.toolbar.freebusy.tooltip;"
-                           oncommand="rotateShowTimeAs()">
-                <menupopup id="event-freebusy-menupopup">
-                    <menuitem id="event-freebusy-busy-menuitem"
-                              name="event-freebusy-group"
-                              label="&event.menu.options.show.time.busy.label;"
-                              type="radio"
-                              command="cmd_showtimeas_busy"/>
-                    <menuitem id="event-freebusy-free-menuitem"
-                              name="event-freebusy-group"
-                              label="&event.menu.options.show.time.free.label;"
-                              type="radio"
-                              command="cmd_showtimeas_free"/>
-                </menupopup>
-            </toolbarbutton>
-            <toolbarbutton id="button-timezones"
-                           mode="dialog"
-                           type="checkbox"
-                           class="cal-event-toolbarbutton toolbarbutton-1"
-                           label="&event.menu.options.timezone2.label;"
-                           tooltiptext="&event.menu.options.timezone2.label;"
-                           command="cmd_timezone"/>
-        </toolbarpalette>
+      <!-- Edit menu -->
+      <menu id="edit-menu"
+            label="&event.menu.edit.label;"
+            accesskey="&event.menu.edit.accesskey;"
+            collapse-on-readonly="true">
+        <menupopup id="edit-menupopup">
+          <menuitem id="edit-undo-menuitem"
+                    label="&event.menu.edit.undo.label;"
+                    accesskey="&event.menu.edit.undo.accesskey;"
+                    key="undo-key"
+                    command="cmd_undo"/>
+          <menuitem id="edit-redo-menuitem"
+                    label="&event.menu.edit.redo.label;"
+                    accesskey="&event.menu.edit.redo.accesskey;"
+                    key="redo-key"
+                    command="cmd_redo"/>
+          <menuseparator id="edit-menuseparator1"/>
+          <menuitem id="edit-cut-menuitem"
+                    label="&event.menu.edit.cut.label;"
+                    accesskey="&event.menu.edit.cut.accesskey;"
+                    key="cut-key"
+                    command="cmd_cut"/>
+          <menuitem id="edit-copy-menuitem"
+                    label="&event.menu.edit.copy.label;"
+                    accesskey="&event.menu.edit.copy.accesskey;"
+                    key="copy-key"
+                    command="cmd_copy"/>
+          <menuitem id="edit-paste-menuitem"
+                    label="&event.menu.edit.paste.label;"
+                    accesskey="&event.menu.edit.paste.accesskey;"
+                    key="paste-key"
+                    command="cmd_paste"/>
+          <menuseparator id="edit-menuseparator2"/>
+          <menuitem id="edit-selectall-menuitem"
+                    label="&event.menu.edit.select.all.label;"
+                    accesskey="&event.menu.edit.select.all.accesskey;"
+                    key="select-all-key"
+                    command="cmd_selectAll"/>
+        </menupopup>
+      </menu>
 
-        <toolbar id="event-toolbar"
-                 class="chromeclass-toolbar"
-                 customizable="true"
-                 labelalign="end"
-                 defaultlabelalign="end"
-                 context="event-dialog-toolbar-context-menu"
-                 defaultset="button-save,button-attendees,button-privacy,button-url,button-delete"/>
-        <toolbarset id="custom-toolbars"/>
-
-    </toolbox>
-    <notificationbox id="event-dialog-notifications" notificationside="top"/>
-    <grid id="event-grid"
-          flex="1"
-          style="padding-top: 8px; padding-bottom: 10px; padding-inline-start: 8px; padding-inline-end: 10px;">
-        <columns id="event-grid-columns">
-            <column id="event-description-column"/>
-            <column id="event-controls-column" flex="1"/>
-        </columns>
-
-        <rows id="event-grid-rows">
-            <!-- Title -->
-            <row id="event-grid-title-row"
-                 align="center">
-                <label value="&event.title.textbox.label;"
-                       accesskey="&event.title.textbox.accesskey;"
-                       control="item-title"
-                       disable-on-readonly="true"/>
-                <textbox id="item-title"
-                         disable-on-readonly="true"
-                         flex="1"
-                         oninput="updateTitle()"/>
-            </row>
-
-            <!-- Location -->
-            <row id="event-grid-location-row"
-                 align="center">
-                <label value="&event.location.label;"
-                       accesskey="&event.location.accesskey;"
-                       control="item-location"
-                       disable-on-readonly="true"/>
-                <textbox id="item-location"
-                         disable-on-readonly="true"/>
-            </row>
-
-            <!-- Category & Calendar -->
-            <row id="event-grid-category-color-row"
-                 align="center">
-                <hbox id="event-grid-category-labels-box">
-                    <label value="&event.categories.label;"
-                           accesskey="&event.categories.accesskey;"
-                           control="item-categories"
-                           id="item-categories-label"
-                           disable-on-readonly="true"/>
-                    <label value="&event.calendar.label;"
-                           accesskey="&event.calendar.accesskey;"
-                           id="item-calendar-aux-label"
-                           control="item-calendar"
-                           disable-on-readonly="true"/>
-                </hbox>
-                <hbox id="event-grid-category-box" align="center">
-                    <menulist id="item-categories"
-                              type="panel-menulist"
-                              disable-on-readonly="true"
-                              flex="1">
-                        <panel id="item-categories-panel"
-                               type="category-panel"
-                               onpopuphiding="updateCategoryMenulist()"/>
-                    </menulist>
-                    <label value="&event.calendar.label;"
-                           accesskey="&event.calendar.accesskey;"
-                           control="item-calendar"
-                           id="item-calendar-label"
-                           disable-on-readonly="true"/>
-                    <menulist id="item-calendar"
-                              disable-on-readonly="true"
-                              flex="1"
-                              oncommand="updateCalendar();"/>
-                </hbox>
-            </row>
-
-            <separator class="groove" id="event-grid-basic-separator"/>
-
-            <!-- All-Day -->
-            <row id="event-grid-allday-row"
-                 align="center">
-                <spacer/>
-                <checkbox id="event-all-day"
-                          class="event-only"
-                          disable-on-readonly="true"
-                          label="&event.alldayevent.label;"
-                          accesskey="&event.alldayevent.accesskey;"
-                          oncommand="onUpdateAllDay();"/>
-            </row>
+      <!-- View menu -->
+      <menu id="view-menu"
+            label="&event.menu.view.label;"
+            accesskey="&event.menu.view.accesskey;"
+            collapse-on-readonly="true">
+        <menupopup id="view-menupopup">
+          <menu id="view-toolbars-menu"
+                label="&event.menu.view.toolbars.label;"
+                accesskey="&event.menu.view.toolbars.accesskey;">
+            <menupopup id="view-toolbars-menupopup">
+              <menuitem id="view-toolbars-event-menuitem"
+                        label="&event.menu.view.toolbars.event.label;"
+                        accesskey="&event.menu.view.toolbars.event.accesskey;"
+                        type="checkbox"
+                        checked="true"
+                        command="cmd_toolbar"/>
+              <menuseparator id="view-toolbars-menuseparator1"/>
+              <menuitem id="view-toolbars-customize-menuitem"
+                        label="&event.menu.view.toolbars.customize.label;"
+                        accesskey="&event.menu.view.toolbars.customize.accesskey;"
+                        command="cmd_customize"/>
+            </menupopup>
+          </menu>
+          <menuseparator id="view-menu-toolbars-separator"/>
+          <menuitem id="view-show-link-menuitem"
+                    label="&event.menu.view.showlink.label;"
+                    accesskey="&event.menu.view.showlink.accesskey;"
+                    type="checkbox"
+                    command="cmd_toggle_link"
+                    observes="cmd_toggle_link"/>
+        </menupopup>
+      </menu>
 
-            <!-- StartDate -->
-            <row id="event-grid-startdate-row">
-                <hbox id="event-grid-startdate-label-box"
-                      align="center">
-                    <label value="&event.from.label;"
-                           accesskey="&event.from.accesskey;"
-                           control="event-starttime"
-                           class="event-only"
-                           disable-on-readonly="true"/>
-                    <label value="&task.from.label;"
-                           accesskey="&task.from.accesskey;"
-                           control="todo-has-entrydate"
-                           class="todo-only"
-                           disable-on-readonly="true"/>
-                </hbox>
-                <hbox id="event-grid-startdate-picker-box">
-                    <datetimepicker id="event-starttime"
-                                    class="event-only"
-                                    disable-on-readonly="true"
-                                    onchange="dateTimeControls2State(true);"/>
-                    <checkbox id="todo-has-entrydate"
-                              class="todo-only checkbox-no-label"
-                              disable-on-readonly="true"
-                              oncommand="updateEntryDate();"/>
-                    <datetimepicker id="todo-entrydate"
-                                    class="todo-only"
-                                    disable-on-readonly="true"
-                                    onchange="dateTimeControls2State(true);"/>
-                    <vbox>
-                        <hbox>
-                            <image id="link-image-top" class="keepduration-link-image" keep="true"/>
-                        </hbox>
-                        <spacer flex="1"/>
-                        <toolbarbutton id="keepduration-button"
-                                       accesskey="&event.dialog.keepDurationButton.accesskey;"
-                                       oncommand="toggleKeepDuration();"
-                                       persist="keep"
-                                       keep="false"
-                                       tooltiptext="&event.dialog.keepDurationButton.tooltip;"/>
-                    </vbox>
-                    <hbox align="center">
-                        <label id="timezone-starttime"
-                               class="text-link"
-                               collapsed="true"
-                               crop="end"
-                               disable-on-readonly="true"
-                               flex="1"
-                               hyperlink="true"
-                               onclick="showTimezonePopup(event, gStartTime.getInTimezone(gStartTimezone), editStartTimezone)"/>
-                    </hbox>
-                </hbox>
-            </row>
-
-            <!-- EndDate -->
-            <row id="event-grid-enddate-row">
-                <hbox id="event-grid-enddate-label-box"
-                      align="center">
-                    <label value="&event.to.label;"
-                           accesskey="&event.to.accesskey;"
-                           control="event-endtime"
-                           class="event-only"
-                           disable-on-readonly="true"/>
-                    <label value="&task.to.label;"
-                           accesskey="&task.to.accesskey;"
-                           control="todo-has-duedate"
-                           class="todo-only"
-                           disable-on-readonly="true"/>
-                </hbox>
-                <vbox>
-                    <hbox id="event-grid-enddate-picker-box">
-                        <datetimepicker id="event-endtime"
-                                        class="event-only"
-                                        disable-on-readonly="true"
-                                        onchange="dateTimeControls2State(false);"/>
-                        <checkbox id="todo-has-duedate"
-                                  class="todo-only checkbox-no-label"
-                                  disable-on-readonly="true"
-                                  oncommand="updateDueDate();"/>
-                        <datetimepicker id="todo-duedate"
-                                        class="todo-only"
-                                        disable-on-readonly="true"
-                                        onchange="dateTimeControls2State(false);"/>
-                        <vbox pack="end">
-                            <image id="link-image-bottom" class="keepduration-link-image"/>
-                        </vbox>
-                        <hbox align="center">
-                            <label id="timezone-endtime"
-                                   class="text-link"
-                                   collapsed="true"
-                                   crop="end"
-                                   disable-on-readonly="true"
-                                   flex="1"
-                                   hyperlink="true"
-                                   onclick="showTimezonePopup(event, gEndTime.getInTimezone(gEndTimezone), editEndTimezone)"/>
-                        </hbox>
-                    </hbox>
-                </vbox>
-            </row>
-
-            <row id="event-grid-todo-status-row"
-                 class="todo-only"
-                 align="center">
-                <label id="todo-status-label"
-                       value="&task.status.label;"
-                       accesskey="&task.status.accesskey;"
-                       control="todo-status"
-                       disable-on-readonly="true"/>
-                <hbox id="event-grid-todo-status-picker-box"
-                      align="center">
-                    <menulist id="todo-status"
-                              class="todo-only"
-                              disable-on-readonly="true"
-                              oncommand="updateToDoStatus(this.value);">
-                        <menupopup id="todo-status-menupopup">
-                            <menuitem id="todo-status-none-menuitem"
-                                      label="&newevent.todoStatus.none.label;"
-                                      value="NONE"/>
-                            <menuitem id="todo-status-needsaction-menuitem"
-                                      label="&newevent.status.needsaction.label;"
-                                      value="NEEDS-ACTION"/>
-                            <menuitem id="todo-status-inprogress-menuitem"
-                                      label="&newevent.status.inprogress.label;"
-                                      value="IN-PROCESS"/>
-                            <menuitem id="todo-status-completed-menuitem"
-                                      label="&newevent.status.completed.label;"
-                                      value="COMPLETED"/>
-                            <menuitem id="todo-status-canceled-menuitem"
-                                      label="&newevent.todoStatus.cancelled.label;"
-                                      value="CANCELLED"/>
-                        </menupopup>
-                    </menulist>
-                    <datepicker id="completed-date-picker"
-                                class="todo-only"
-                                disable-on-readonly="true"
-                                disabled="true"
-                                value=""/>
-                    <textbox id="percent-complete-textbox"
-                             type="number"
-                             min="0"
-                             max="100"
-                             disable-on-readonly="true"
-                             size="3"
-                             oninput="updateToDoStatus('percent-changed')"
-                             onselect="updateToDoStatus('percent-changed')"/>
-                    <label id="percent-complete-label"
-                           class="todo-only"
-                           disable-on-readonly="true"
-                           value="&newtodo.percentcomplete.label;"/>
-                </hbox>
-            </row>
-
-            <separator id="event-grid-recurrence-separator" class="groove"/>
-
-            <!-- Recurrence -->
-            <row id="event-grid-recurrence-row"
-                 align="center">
-                <label value="&event.repeat.label;"
-                       accesskey="&event.repeat.accesskey;"
-                       control="item-repeat"
-                       disable-on-readonly="true"/>
-                <hbox id="event-grid-recurrence-picker-box"
-                      align="center"
-                      flex="1">
-                    <menulist id="item-repeat"
-                              disable-on-readonly="true"
-                              oncommand="updateRepeat(null, true)">
-                        <menupopup id="item-repeat-menupopup">
-                            <menuitem id="repeat-none-menuitem"
-                                      label="&event.repeat.does.not.repeat.label;"
-                                      selected="true"
-                                      value="none"/>
-                            <menuitem id="repeat-daily-menuitem"
-                                      label="&event.repeat.daily.label;"
-                                      value="daily"/>
-                            <menuitem id="repeat-weekly-menuitem"
-                                      label="&event.repeat.weekly.label;"
-                                      value="weekly"/>
-                            <menuitem id="repeat-weekday-menuitem"
-                                      label="&event.repeat.every.weekday.label;"
-                                      value="every.weekday"/>
-                            <menuitem id="repeat-biweekly-menuitem"
-                                      label="&event.repeat.bi.weekly.label;"
-                                      value="bi.weekly"/>
-                            <menuitem id="repeat-monthly-menuitem"
-                                      label="&event.repeat.monthly.label;"
-                                      value="monthly"/>
-                            <menuitem id="repeat-yearly-menuitem"
-                                      label="&event.repeat.yearly.label;"
-                                      value="yearly"/>
-                            <menuseparator id="item-repeat-separator"/>
-                            <menuitem id="repeat-custom-menuitem"
-                                      label="&event.repeat.custom.label;"
-                                      value="custom"/>
-                        </menupopup>
-                    </menulist>
-                    <deck id="repeat-deck" selectedIndex="-1">
-                        <hbox id="repeat-untilDate" align="center">
-                            <label value="&event.until.label;"
-                                   accesskey="&event.until.accesskey;"
-                                   control="repeat-until-datepicker"
-                                   disable-on-readonly="true"/>
-                            <datepicker-forever id="repeat-until-datepicker" flex="1"
-                                                disable-on-readonly="true"
-                                                onchange="checkUntilDate();"
-                                                oncommand="checkUntilDate();"
-                                                value=""/>
-                        </hbox>
-                        <vbox id="repeat-details" flex="1">
-                            <label class="text-link"
-                                   crop="right"
-                                   disable-on-readonly="true"
-                                   hyperlink="true"
-                                   flex="1"
-                                   onclick="updateRepeat()"/>
-                        </vbox>
-                    </deck>
-                </hbox>
-            </row>
-
-            <separator id="event-grid-alarm-separator"
-                       class="groove"/>
+      <!-- Options menu -->
+      <menu id="options-menu"
+            label="&event.menu.options.label;"
+            accesskey="&event.menu.options.accesskey;">
+        <menupopup id="options-menupopup">
+          <menuitem id="options-attendees-menuitem"
+                    label="&event.menu.options.attendees.label;"
+                    accesskey="&event.menu.options.attendees.accesskey;"
+                    command="cmd_attendees"
+                    disable-on-readonly="true"/>
+          <menu id="options-attachments-menu"
+                label="&event.attachments.menubutton.label;"
+                accesskey="&event.attachments.menubutton.accesskey;">
+            <menupopup id="options-attachments-menupopup">
+              <menuitem id="options-attachments-url-menuitem"
+                        label="&event.attachments.url.label;"
+                        accesskey="&event.attachments.url.accesskey;"
+                        command="cmd_attach_url"/>
+            </menupopup>
+          </menu>
+          <menuitem id="options-timezones-menuitem"
+                    label="&event.menu.options.timezone2.label;"
+                    accesskey="&event.menu.options.timezone2.accesskey;"
+                    type="checkbox"
+                    command="cmd_timezone"
+                    disable-on-readonly="true"/>
+          <menuseparator id="options-menuseparator1"/>
+          <menu id="options-priority-menu"
+                label="&event.menu.options.priority2.label;"
+                accesskey="&event.menu.options.priority2.accesskey;"
+                disable-on-readonly="true">
+            <menupopup id="options-priority-menupopup">
+              <menuitem id="options-priority-none-menuitem"
+                        label="&event.menu.options.priority.notspecified.label;"
+                        accesskey="&event.menu.options.priority.notspecified.accesskey;"
+                        type="radio"
+                        command="cmd_priority_none"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-priority-low-menuitem"
+                        label="&event.menu.options.priority.low.label;"
+                        accesskey="&event.menu.options.priority.low.accesskey;"
+                        type="radio"
+                        command="cmd_priority_low"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-priority-normal-label"
+                        label="&event.menu.options.priority.normal.label;"
+                        accesskey="&event.menu.options.priority.normal.accesskey;"
+                        type="radio"
+                        command="cmd_priority_normal"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-priority-high-label"
+                        label="&event.menu.options.priority.high.label;"
+                        accesskey="&event.menu.options.priority.high.accesskey;"
+                        type="radio"
+                        command="cmd_priority_high"
+                        disable-on-readonly="true"/>
+            </menupopup>
+          </menu>
+          <menu id="options-privacy-menu"
+                label="&event.menu.options.privacy.label;"
+                accesskey="&event.menu.options.privacy.accesskey;"
+                disable-on-readonly="true">
+            <menupopup id="options-privacy-menupopup">
+              <menuitem id="options-privacy-public-menuitem"
+                        label="&event.menu.options.privacy.public.label;"
+                        accesskey="&event.menu.options.privacy.public.accesskey;"
+                        type="radio"
+                        privacy="PUBLIC"
+                        oncommand="editPrivacy(this, event)"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-privacy-confidential-menuitem"
+                        label="&event.menu.options.privacy.confidential.label;"
+                        accesskey="&event.menu.options.privacy.confidential.accesskey;"
+                        type="radio"
+                        privacy="CONFIDENTIAL"
+                        oncommand="editPrivacy(this, event)"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-privacy-private-menuitem"
+                        label="&event.menu.options.privacy.private.label;"
+                        accesskey="&event.menu.options.privacy.private.accesskey;"
+                        type="radio"
+                        privacy="PRIVATE"
+                        oncommand="editPrivacy(this, event)"
+                        disable-on-readonly="true"/>
+            </menupopup>
+          </menu>
+          <menu id="options-status-menu"
+                label="&newevent.status.label;"
+                accesskey="&newevent.status.accesskey;"
+                class="event-only"
+                disable-on-readonly="true">
+            <menupopup id="options-status-menupopup">
+              <menuitem id="options-status-none-menuitem"
+                        label="&newevent.eventStatus.none.label;"
+                        accesskey="&newevent.eventStatus.none.accesskey;"
+                        type="radio"
+                        command="cmd_status_none"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-status-tentative-menuitem"
+                        label="&newevent.status.tentative.label;"
+                        accesskey="&newevent.status.tentative.accesskey;"
+                        type="radio"
+                        command="cmd_status_tentative"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-status-confirmed-menuitem"
+                        label="&newevent.status.confirmed.label;"
+                        accesskey="&newevent.status.confirmed.accesskey;"
+                        type="radio"
+                        command="cmd_status_confirmed"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-status-canceled-menuitem"
+                        label="&newevent.eventStatus.cancelled.label;"
+                        accesskey="&newevent.eventStatus.cancelled.accesskey;"
+                        type="radio"
+                        command="cmd_status_cancelled"
+                        disable-on-readonly="true"/>
+            </menupopup>
+          </menu>
+          <menuseparator id="options-menuseparator2" class="event-only"/>
+          <menu id="options-freebusy-menu"
+                class="event-only"
+                label="&event.menu.options.show.time.label;"
+                accesskey="&event.menu.options.show.time.accesskey;"
+                disable-on-readonly="true">
+            <menupopup id="options-freebusy-menupopup">
+              <menuitem id="options-freebusy-busy-menuitem"
+                        label="&event.menu.options.show.time.busy.label;"
+                        accesskey="&event.menu.options.show.time.busy.accesskey;"
+                        type="radio"
+                        command="cmd_showtimeas_busy"
+                        disable-on-readonly="true"/>
+              <menuitem id="options-freebusy-free-menuitem"
+                        label="&event.menu.options.show.time.free.label;"
+                        accesskey="&event.menu.options.show.time.free.accesskey;"
+                        type="radio"
+                        command="cmd_showtimeas_free"
+                        disable-on-readonly="true"/>
+            </menupopup>
+          </menu>
+        </menupopup>
+      </menu>
+    </menubar>
 
-            <!-- Reminder (Alarm) -->
-            <row id="event-grid-alarm-row"
-                 align="center">
-                <label value="&event.reminder.label;"
-                       accesskey="&event.reminder.accesskey;"
-                       control="item-alarm"
-                       disable-on-readonly="true"/>
-                <hbox id="event-grid-alarm-picker-box"
-                      align="center">
-                    <menulist id="item-alarm"
-                              disable-on-readonly="true"
-                              oncommand="updateReminder()">
-                        <menupopup id="item-alarm-menupopup">
-                            <menuitem id="reminder-none-menuitem"
-                                      label="&event.reminder.none.label;"
-                                      selected="true"
-                                      value="none"/>
-                            <menuseparator id="reminder-none-separator"/>
-                            <menuitem id="reminder-0minutes-menuitem"
-                                      label="&event.reminder.0minutes.before.label;"
-                                      length="0"
-                                      origin="before"
-                                      relation="START"
-                                      unit="minutes"/>
-                            <menuitem id="reminder-5minutes-menuitem"
-                                      label="&event.reminder.5minutes.before.label;"
-                                      length="5"
-                                      origin="before"
-                                      relation="START"
-                                      unit="minutes"/>
-                            <menuitem id="reminder-15minutes-menuitem"
-                                      label="&event.reminder.15minutes.before.label;"
-                                      length="15"
-                                      origin="before"
-                                      relation="START"
-                                      unit="minutes"/>
-                            <menuitem id="reminder-30minutes-menuitem"
-                                      label="&event.reminder.30minutes.before.label;"
-                                      length="30"
-                                      origin="before"
-                                      relation="START"
-                                      unit="minutes"/>
-                            <menuseparator id="reminder-minutes-separator"/>
-                            <menuitem id="reminder-1hour-menuitem"
-                                      label="&event.reminder.1hour.before.label;"
-                                      length="1"
-                                      origin="before"
-                                      relation="START"
-                                      unit="hours"/>
-                            <menuitem id="reminder-2hours-menuitem"
-                                      label="&event.reminder.2hours.before.label;"
-                                      length="2"
-                                      origin="before"
-                                      relation="START"
-                                      unit="hours"/>
-                            <menuitem id="reminder-12hours-menuitem"
-                                      label="&event.reminder.12hours.before.label;"
-                                      length="12"
-                                      origin="before"
-                                      relation="START"
-                                      unit="hours"/>
-                            <menuseparator id="reminder-hours-separator"/>
-                            <menuitem id="reminder-1day-menuitem"
-                                      label="&event.reminder.1day.before.label;"
-                                      length="1"
-                                      origin="before"
-                                      relation="START"
-                                      unit="days"/>
-                            <menuitem id="reminder-2days-menuitem"
-                                      label="&event.reminder.2days.before.label;"
-                                      length="2"
-                                      origin="before"
-                                      relation="START"
-                                      unit="days"/>
-                            <menuitem id="reminder-1week-menuitem"
-                                      label="&event.reminder.1week.before.label;"
-                                      length="7"
-                                      origin="before"
-                                      relation="START"
-                                      unit="days"/>
-                            <menuseparator id="reminder-custom-separator"/>
-                            <menuitem id="reminder-custom-menuitem"
-                                      label="&event.reminder.custom.label;"
-                                      value="custom"/>
-                        </menupopup>
-                    </menulist>
-                    <hbox id="reminder-details">
-                        <hbox id="reminder-icon-box"
-                              class="alarm-icons-box"
-                              align="center"/>
-                        <!-- TODO oncommand? onkeypress? -->
-                        <label id="reminder-multiple-alarms-label"
-                               hidden="true"
-                               value="&event.reminder.multiple.label;"
-                               class="text-link"
-                               disable-on-readonly="true"
-                               flex="1"
-                               hyperlink="true"
-                               onclick="updateReminder()"/>
-                        <label id="reminder-single-alarms-label"
-                               hidden="true"
-                               class="text-link"
-                               disable-on-readonly="true"
-                               flex="1"
-                               hyperlink="true"
-                               onclick="updateReminder()"/>
-                    </hbox>
-               </hbox>
-            </row>
+    <!-- toolbarpalette items are added with an overlay -->
+    <toolbarpalette id="event-toolbarpalette"/>
+    <!-- toolboxid is set here since we move the toolbar around in tabs -->
+    <toolbar id="event-toolbar"
+             toolboxid="event-toolbox"
+             class="chromeclass-toolbar"
+             customizable="true"
+             labelalign="end"
+             defaultlabelalign="end"
+             context="event-dialog-toolbar-context-menu"
+             defaultset="button-save,button-attendees,button-privacy,button-url,button-delete"/>
+    <toolbarset id="custom-toolbars"/>
+  </toolbox>
 
-            <separator id="event-grid-tabbox-separator"
-                       class="groove"/>
+  <iframe id="lightning-item-panel-iframe"
+          flex="1"
+          src="chrome://lightning/content/lightning-item-iframe.xul"/>
 
-            <!-- Multi purpose tab box -->
-            <tabbox id="event-grid-tabbox"
-                    selectedIndex="0"
-                    flex="1">
-              <tabs id="event-grid-tabs">
-                <tab id="event-grid-tab-description"
-                     label="&event.description.label;"
-                     accesskey="&event.description.accesskey;"/>
-                <tab id="event-grid-tab-attachments"
-                     label="&event.attachments.label;"
-                      accesskey="&event.attachments.accesskey;"/>
-                <tab id="event-grid-tab-attendees"
-                     label="&event.attendees.label;"
-                     accesskey="&event.attendees.accesskey;"
-                     collapsed="true"/>
-              </tabs>
-              <tabpanels id="event-grid-tabpanels"
-                         flex="1">
-                <tabpanel id="event-grid-tabpanel-description">
-                  <textbox id="item-description"
-                           disable-on-readonly="true"
-                           flex="1"
-                           multiline="true"
-                           rows="12"/>
-                </tabpanel>
-                <tabpanel id="event-grid-tabpanel-attachements">
-                    <vbox flex="1">
-                      <listbox id="attachment-link"
-                               context="attachment-popup"
-                               rows="3"
-                               flex="1"
-                               disable-on-readonly="true"
-                               onkeypress="attachmentLinkKeyPress(event)"
-                               onclick="attachmentClick(event);"
-                               ondblclick="attachmentDblClick(event);"/>
-                    </vbox>
-                </tabpanel>
-                <tabpanel id="event-grid-tabpanel-attendees"
-                          collapsed="true">
-                  <vbox flex="1">
-                    <hbox id="item-organizer-row"
-                          collapsed="true"
-                          align="top"
-                          class="item-attendees-row">
-                      <label value="&read.only.organizer.label;"/>
-                      <hbox class="item-organizer-cell">
-                        <img class="itip-icon"/>
-                        <label id="item-organizer"
-                               class="item-attendees-cell-label"
-                               crop="right"/>
-                      </hbox>
-                    </hbox>
-                    <hbox flex="1">
-                      <vbox id="item-attendees-box"
-                            dialog-type="event"
-                            flex="1"
-                            context="attendee-popup"
-                            onclick="attendeeClick(event)"
-                            disable-on-readonly="true"/>
-                    </hbox>
-                    <hbox id="notify-options" align="center">
-                      <checkbox id="notify-attendees-checkbox"
-                                label="&event.attendees.notify.label;"
-                                accesskey="&event.attendees.notify.accesskey;"
-                                oncommand="changeUndiscloseCheckboxStatus();"
-                                pack="start"/>
-                      <checkbox id="undisclose-attendees-checkbox"
-                                label="&event.attendees.notifyundisclosed.label;"
-                                accesskey="&event.attendees.notifyundisclosed.accesskey;"
-                                tooltiptext="&event.attendees.notifyundisclosed.tooltip;"
-                                pack="start"/>
-                    </hbox>
-                  </vbox>
-                </tabpanel>
-              </tabpanels>
-            </tabbox>
-
-            <separator id="event-grid-link-separator"
-                       class="groove"
-                       hidden="true"/>
-            <row id="event-grid-link-row"
-                 align="center"
-                 hidden="true">
-                <label value="&event.url.label;"
-                       control="url-link"/>
-                <label id="url-link"
-                       onclick="launchBrowser(this.getAttribute('href'), event)"
-                       oncommand="launchBrowser(this.getAttribute('href'), event)"
-                       class="text-link"
-                       crop="end"/>
-            </row>
-        </rows>
-    </grid>
-
-    <statusbar class="chromeclass-status" id="status-bar">
-      <statusbarpanel id="status-text"
-                      flex="1"/>
-      <statusbarpanel id="status-privacy"
-                      align="center"
-                      flex="1"
-                      collapsed="true"
-                      pack="start">
-        <label value="&event.statusbarpanel.privacy.label;"/>
-        <hbox id="status-privacy-public-box" privacy="PUBLIC">
-          <label value="&event.menu.options.privacy.public.label;"/>
-        </hbox>
-        <hbox id="status-privacy-confidential-box" privacy="CONFIDENTIAL">
-          <label value="&event.menu.options.privacy.confidential.label;"/>
-        </hbox>
-        <hbox id="status-privacy-private-box" privacy="PRIVATE">
-          <label value="&event.menu.options.privacy.private.label;"/>
-        </hbox>
-      </statusbarpanel>
-      <statusbarpanel id="status-priority"
-                      align="center"
-                      flex="1"
-                      collapsed="true"
-                      pack="start">
-        <label value="&event.priority2.label;"/>
-        <image id="image-priority-low"
-               class="cal-statusbar-1"
-               collapsed="true"
-               value="low"/>
-        <image id="image-priority-normal"
-               class="cal-statusbar-1"
-               collapsed="true"
-               value="normal"/>
-        <image id="image-priority-high"
-               class="cal-statusbar-1"
-               collapsed="true"
-               value="high"/>
-      </statusbarpanel>
-      <statusbarpanel id="status-status"
-                      align="center"
-                      flex="1"
-                      collapsed="true"
-                      pack="start">
-        <label value="&task.status.label;"/>
-        <label id="status-status-tentative-label"
-               value="&newevent.status.tentative.label;"
-               hidden="true"/>
-        <label id="status-status-confirmed-label"
-               value="&newevent.status.confirmed.label;"
-               hidden="true"/>
-        <label id="status-status-cancelled-label"
-               value="&newevent.eventStatus.cancelled.label;"
-               hidden="true"/>
-      </statusbarpanel>
-      <statusbarpanel id="status-freebusy"
-                      class="event-only"
-                      align="center"
-                      flex="1"
-                      collapsed="true"
-                      pack="start">
-        <label value="&event.statusbarpanel.freebusy.label;"/>
-        <label id="status-freebusy-free-label"
-               value="&event.freebusy.legend.free;"
-               hidden="true"/>
-        <label id="status-freebusy-busy-label"
-               value="&event.freebusy.legend.busy;"
-               hidden="true"/>
-      </statusbarpanel>
-    </statusbar>
-
-    <popupset id="event-dialog-popupset">
-      <menupopup id="attendee-popup">
-        <menuitem id="attendee-popup-invite-menuitem"
-                  label="&event.invite.attendees.label;"
-                  accesskey="&event.invite.attendees.accesskey;"
-                  command="cmd_attendees"
-                  disable-on-readonly="true"/>
-        <menuitem id="attendee-popup-removeallattendees-menuitem"
-                  label="&event.remove.attendees.label2;"
-                  accesskey="&event.remove.attendees.accesskey;"
-                  oncommand="removeAllAttendees()"
-                  disable-on-readonly="true"
-                  crop="end"/>
-        <menuitem id="attendee-popup-removeattendee-menuitem"
-                  label="&event.remove.attendee.label;"
-                  accesskey="&event.remove.attendee.accesskey;"
-                  oncommand="removeAttendee(event.target.attendee)"
-                  crop="end"/>
-        <menuseparator id="attendee-popup-first-separator"/>
-        <menuitem id="attendee-popup-sendemail-menuitem"
-                  label="&event.email.attendees.label;"
-                  accesskey="&event.email.attendees.accesskey;"
-                  command="cmd_email"/>
-        <menuitem id="attendee-popup-sendtentativeemail-menuitem"
-                  label="&event.email.tentative.attendees.label;"
-                  accesskey="&event.email.tentative.attendees.accesskey;"
-                  command="cmd_email_undecided"/>
-        <menuseparator id="attendee-popup-second-separator"/>
-        <menuitem id="attendee-popup-emailattendee-menuitem"
-                  oncommand="sendMailToAttendees([event.target.attendee])"
-                  crop="end"/>
-      </menupopup>
-      <menupopup id="attachment-popup">
-            <menuitem id="attachment-popup-open"
-                      label="&event.attachments.popup.open.label;"
-                      accesskey="&event.attachments.popup.open.accesskey;"
-                      command="cmd_openAttachment"/>
-            <menuitem id="attachment-popup-copy"
-                      label="&calendar.copylink.label;"
-                      accesskey="&calendar.copylink.accesskey;"
-                      command="cmd_copyAttachment"/>
-            <menuitem id="attachment-popup-delete"
-                      label="&event.attachments.popup.remove.label;"
-                      accesskey="&event.attachments.popup.remove.accesskey;"
-                      command="cmd_deleteAttachment"/>
-            <menuitem id="attachment-popup-deleteAll"
-                      label="&event.attachments.popup.removeAll.label;"
-                      accesskey="&event.attachments.popup.removeAll.accesskey;"
-                      command="cmd_deleteAllAttachments"/>
-            <menuseparator/>
-            <menuitem id="attachment-popup-attachPage"
-                      label="&event.attachments.popup.attachPage.label;"
-                      accesskey="&event.attachments.popup.attachPage.accesskey;"
-                      command="cmd_attach_url"/>
-      </menupopup>
-      <menupopup id="timezone-popup" position="after_start" oncommand="chooseRecentTimezone(event)">
-        <menuitem id="timezone-popup-defaulttz"/>
-        <menuseparator id="timezone-popup-menuseparator"/>
-        <menuitem id="timezone-custom-menuitem"
-                  label="&event.timezone.custom.label;"
-                  value="custom"
-                  oncommand="this.parentNode.editTimezone()"/>
-      </menupopup>
-    </popupset>
-
-    <!-- attendee box template -->
-    <vbox id="item-attendees-box-template"
-          hidden="true">
-      <hbox flex="1" class="item-attendees-row" equalsize="always" hidden="true">
-        <box class="item-attendees-cell"
-             hidden="true"
-             flex="1"
-             context="attendee-popup"
-             ondblclick="attendeeDblClick(event)"
-             onclick="attendeeClick(event)">
-          <img class="itip-icon"/>
-          <label class="item-attendees-cell-label"
-                 crop="end"
-                 flex="1"/>
-        </box>
-        <box hidden="true" flex="1"/>
+  <statusbar class="chromeclass-status" id="status-bar">
+    <statusbarpanel id="status-text"
+                    flex="1"/>
+    <statusbarpanel id="status-privacy"
+                    align="center"
+                    flex="1"
+                    collapsed="true"
+                    pack="start">
+      <label value="&event.statusbarpanel.privacy.label;"/>
+      <hbox id="status-privacy-public-box" privacy="PUBLIC">
+        <label value="&event.menu.options.privacy.public.label;"/>
+      </hbox>
+      <hbox id="status-privacy-confidential-box" privacy="CONFIDENTIAL">
+        <label value="&event.menu.options.privacy.confidential.label;"/>
+      </hbox>
+      <hbox id="status-privacy-private-box" privacy="PRIVATE">
+        <label value="&event.menu.options.privacy.private.label;"/>
       </hbox>
-    </vbox>
+    </statusbarpanel>
+    <statusbarpanel id="status-priority"
+                    align="center"
+                    flex="1"
+                    collapsed="true"
+                    pack="start">
+      <label value="&event.priority2.label;"/>
+      <image id="image-priority-low"
+             class="cal-statusbar-1"
+             collapsed="true"
+             value="low"/>
+      <image id="image-priority-normal"
+             class="cal-statusbar-1"
+             collapsed="true"
+             value="normal"/>
+      <image id="image-priority-high"
+             class="cal-statusbar-1"
+             collapsed="true"
+             value="high"/>
+    </statusbarpanel>
+    <statusbarpanel id="status-status"
+                    align="center"
+                    flex="1"
+                    collapsed="true"
+                    pack="start">
+      <label value="&task.status.label;"/>
+      <label id="status-status-tentative-label"
+             value="&newevent.status.tentative.label;"
+             hidden="true"/>
+      <label id="status-status-confirmed-label"
+             value="&newevent.status.confirmed.label;"
+             hidden="true"/>
+      <label id="status-status-cancelled-label"
+             value="&newevent.eventStatus.cancelled.label;"
+             hidden="true"/>
+    </statusbarpanel>
+    <statusbarpanel id="status-freebusy"
+                    class="event-only"
+                    align="center"
+                    flex="1"
+                    collapsed="true"
+                    pack="start">
+      <label value="&event.statusbarpanel.freebusy.label;"/>
+      <label id="status-freebusy-free-label"
+             value="&event.freebusy.legend.free;"
+             hidden="true"/>
+      <label id="status-freebusy-busy-label"
+             value="&event.freebusy.legend.busy;"
+             hidden="true"/>
+    </statusbarpanel>
+  </statusbar>
 </dialog>
--- a/calendar/base/jar.mn
+++ b/calendar/base/jar.mn
@@ -46,17 +46,16 @@ calendar.jar:
     content/calendar/today-pane.js                         (content/today-pane.js)
     content/calendar/calendar-alarm-dialog.js              (content/dialogs/calendar-alarm-dialog.js)
     content/calendar/calendar-alarm-dialog.xul             (content/dialogs/calendar-alarm-dialog.xul)
     content/calendar/calendar-conflicts-dialog.xul         (content/dialogs/calendar-conflicts-dialog.xul)
     content/calendar/calendar-creation.js                  (content/dialogs/calendar-creation.js)
     content/calendar/calendar-dialog-utils.js              (content/dialogs/calendar-dialog-utils.js)
     content/calendar/calendar-error-prompt.xul             (content/dialogs/calendar-error-prompt.xul)
     content/calendar/calendar-event-dialog.css             (content/dialogs/calendar-event-dialog.css)
-    content/calendar/calendar-event-dialog.js              (content/dialogs/calendar-event-dialog.js)
 *   content/calendar/calendar-event-dialog.xul             (content/dialogs/calendar-event-dialog.xul)
     content/calendar/calendar-event-dialog-attendees.xml   (content/dialogs/calendar-event-dialog-attendees.xml)
     content/calendar/calendar-event-dialog-freebusy.xml    (content/dialogs/calendar-event-dialog-freebusy.xml)
     content/calendar/calendar-event-dialog-recurrence.xul  (content/dialogs/calendar-event-dialog-recurrence.xul)
     content/calendar/calendar-event-dialog-recurrence.js   (content/dialogs/calendar-event-dialog-recurrence.js)
     content/calendar/calendar-event-dialog-recurrence-preview.xml  (content/dialogs/calendar-event-dialog-recurrence-preview.xml)
     content/calendar/calendar-event-dialog-reminder.js     (content/dialogs/calendar-event-dialog-reminder.js)
     content/calendar/calendar-event-dialog-reminder.xul    (content/dialogs/calendar-event-dialog-reminder.xul)
@@ -105,32 +104,35 @@ calendar.jar:
     content/calendar/WindowsNTToZoneInfoTZId.properties    (src/WindowsNTToZoneInfoTZId.properties)
 % skin calendar classic/1.0 chrome/skin/linux/calendar/
 % skin calendar classic/1.0 chrome/skin/osx/calendar/ os=Darwin
 % skin calendar classic/1.0 chrome/skin/windows/calendar/ os=WINNT
 % skin calendar-common classic/1.0 chrome/skin/common/
 % style chrome://global/content/customizeToolbar.xul chrome://calendar/skin/calendar-task-view.css
 % style chrome://global/content/customizeToolbar.xul chrome://calendar/skin/calendar-event-dialog.css
 % style chrome://calendar/content/calendar-event-dialog.xul chrome://calendar-common/skin/dialogs/calendar-event-dialog.css
+% style chrome://lightning/content/lightning-item-iframe.xul chrome://calendar-common/skin/dialogs/calendar-event-dialog.css
 % style chrome://calendar/content/calendar-event-dialog-attendees.xul chrome://calendar-common/skin/dialogs/calendar-event-dialog.css
     ../skin/common/alarm-flashing.png                 (themes/common/images/alarm-flashing.png)
     ../skin/common/alarm-icons.png                    (themes/common/images/alarm-icons.png)
     ../skin/common/attendee-icons.png                 (themes/common/images/attendee-icons.png)
     ../skin/common/calendar-overlay.png               (themes/common/images/calendar-overlay.png)
     ../skin/common/calendar-status.png                (themes/common/images/calendar-status.png)
     ../skin/common/classification.png                 (themes/common/images/classification.png)
     ../skin/common/day-box-item-image.png             (themes/common/images/day-box-item-image.png)
     ../skin/common/event-grippy-bottom.png            (themes/common/images/event-grippy-bottom.png)
     ../skin/common/event-grippy-left.png              (themes/common/images/event-grippy-left.png)
     ../skin/common/event-grippy-right.png             (themes/common/images/event-grippy-right.png)
     ../skin/common/event-grippy-top.png               (themes/common/images/event-grippy-top.png)
     ../skin/common/task-images.png                    (themes/common/images/task-images.png)
     ../skin/common/timezone_map.png                   (themes/common/images/timezone_map.png)
     ../skin/common/timezones.png                      (themes/common/images/timezones.png)
     ../skin/common/calendar-event-dialog.png          (themes/common/dialogs/images/calendar-event-dialog.png)
+    ../skin/common/calendar-event-tab.png             (themes/common/dialogs/images/calendar-event-tab.png)
+    ../skin/common/calendar-task-tab.png              (themes/common/dialogs/images/calendar-task-tab.png)
     ../skin/common/widgets/nav-arrow.svg              (themes/common/widgets/images/nav-arrow.svg)
     ../skin/common/widgets/nav-today.svg              (themes/common/widgets/images/nav-today.svg)
     ../skin/common/widgets/nav-today-hov.svg          (themes/common/widgets/images/nav-today-hov.svg)
     ../skin/common/widgets/view-navigation.svg        (themes/common/widgets/images/view-navigation.svg)
     ../skin/common/widgets/view-navigation-hov.svg    (themes/common/widgets/images/view-navigation-hov.svg)
     ../skin/common/widgets/drag-center.svg            (themes/common/widgets/images/drag-center.svg)
     ../skin/common/calendar-alarms.css                (themes/common/calendar-alarms.css)
     ../skin/common/calendar-attendees.css             (themes/common/calendar-attendees.css)
@@ -172,16 +174,18 @@ calendar.jar:
     ../skin/linux/calendar/calendar-task-view.css                         (themes/linux/calendar-task-view.css)
     ../skin/linux/calendar/calendar-unifinder.css                         (themes/linux/calendar-unifinder.css)
     ../skin/linux/calendar/calendar-views.css                             (themes/linux/calendar-views.css)
     ../skin/linux/calendar/checkbox-images.png                            (themes/linux/images/checkbox-images.png)
     ../skin/linux/calendar/ok-cancel.png                                  (themes/linux/images/ok-cancel.png)
     ../skin/linux/calendar/today-pane.css                                 (themes/linux/today-pane.css)
     ../skin/linux/calendar/widgets/calendar-widgets.css                   (themes/linux/widgets/calendar-widgets.css)
     ../skin/linux/calendar/calendar-occurrence-prompt.png                 (themes/linux/images/calendar-occurrence-prompt.png)
+    ../skin/linux/calendar/calendar-event-dialog.png                      (themes/linux/icons/calendar-event-dialog.png)
+    ../skin/linux/calendar/calendar-task-dialog.png                       (themes/linux/icons/calendar-task-dialog.png)
 
 # OS X theme files
     ../skin/osx/calendar/cal-icon32.png                                 (themes/osx/images/cal-icon32.png)
     ../skin/osx/calendar/cal-icon24.png                                 (themes/osx/images/cal-icon24.png)
     ../skin/osx/calendar/calendar-alarm-dialog.css                      (themes/osx/dialogs/calendar-alarm-dialog.css)
     ../skin/osx/calendar/calendar-daypicker.css                         (themes/osx/calendar-daypicker.css)
     ../skin/osx/calendar/calendar-event-dialog.css                      (themes/osx/dialogs/calendar-event-dialog.css)
     ../skin/osx/calendar/calendar-event-dialog-attendees.png            (themes/osx/dialogs/images/calendar-event-dialog-attendees.png)
@@ -224,8 +228,10 @@ calendar.jar:
     ../skin/windows/calendar/widgets/calendar-widgets.css                   (themes/windows/widgets/calendar-widgets.css)
     ../skin/windows/calendar/calendar-event-dialog-toolbar.png              (themes/windows/dialogs/images/calendar-event-dialog-toolbar.png)
     ../skin/windows/calendar/calendar-event-dialog-toolbar-small.png        (themes/windows/dialogs/images/calendar-event-dialog-toolbar-small.png)
     ../skin/windows/calendar/calendar-occurrence-prompt.png                 (themes/windows/images/calendar-occurrence-prompt.png)
     ../skin/windows/calendar/tasks-actions.png                              (themes/windows/images/tasks-actions.png)
     ../skin/windows/calendar/toolbar-large.png                              (themes/windows/images/toolbar-large.png)
     ../skin/windows/calendar/toolbar-small.png                              (themes/windows/images/toolbar-small.png)
     ../skin/windows/calendar/calendar-occurrence-prompt-aero.png            (themes/windows/images/calendar-occurrence-prompt-aero.png)
+    ../skin/windows/calendar/calendar-event-dialog.png                      (themes/windows/icons/calendar-event-dialog.png)
+    ../skin/windows/calendar/calendar-task-dialog.png                       (themes/windows/icons/calendar-task-dialog.png)
--- a/calendar/base/themes/common/calendar-attendees.css
+++ b/calendar/base/themes/common/calendar-attendees.css
@@ -16,23 +16,23 @@
     max-height: 92px; /* displays up to four rows of attendees*/
     margin: 0px 10px;
 }
 
 .item-attendees-cell {
     padding: 3px 0px;
 }
 
-#calendar-event-dialog .item-attendees-cell {
+#calendar-event-dialog-inner .item-attendees-cell {
     -moz-user-focus: normal;
     margin-bottom: 1px;
     margin-inline-end: 1px;
 }
 
-#calendar-event-dialog .item-attendees-cell:focus {
+#calendar-event-dialog-inner .item-attendees-cell:focus {
     background-color: Highlight;
     color: Highlighttext;
 }
 
 .item-attendees-cell-label {
     border: 0px;
     margin: 0px 3px;
     padding: 0px;
@@ -212,23 +212,23 @@
 .usertype-icon[cutype="ROOM"][disabled="true"] {
     -moz-image-region: rect(16px 64px 32px 48px);
 }
 
 @media (-moz-windows-default-theme) and (-moz-os-version: windows-vista),
        (-moz-windows-default-theme) and (-moz-os-version: windows-win7),
        (-moz-windows-default-theme) and (-moz-os-version: windows-win8),
        (-moz-windows-default-theme) and (-moz-os-version: windows-win10) {
-    #calendar-event-dialog .item-attendees-cell {
+    #calendar-event-dialog-inner .item-attendees-cell {
         background-repeat: no-repeat;
         background-size: 100% 100%;
         --attendees-currentColor: rgb(125, 162, 206);
     }
 
-    #calendar-event-dialog .item-attendees-cell:focus {
+    #calendar-event-dialog-inner .item-attendees-cell:focus {
         color: -moz-FieldText;
         background-color: transparent;
         -moz-border-top-colors: var(--attendees-focusBorder);
         -moz-border-right-colors: var(--attendees-focusBorder);
         -moz-border-left-colors: var(--attendees-focusBorder);
         -moz-border-bottom-colors: var(--attendees-focusBottomBorder);
         background-image: var(--attendees-focusImage);
     }
@@ -247,17 +247,17 @@
                                        var(--attendees-2ndBottomBorderColor);
         --attendees-focusImage: linear-gradient(rgba(131, 183, 249, .28),
                                                 rgba(131, 183, 249, .5));
     }
 }
 
 @media (-moz-windows-default-theme) and (-moz-os-version: windows-win8),
        (-moz-windows-default-theme) and (-moz-os-version: windows-win10) {
-    #calendar-event-dialog .item-attendees-cell {
+    #calendar-event-dialog-inner .item-attendees-cell {
         padding: 1px;
         border: 1px solid transparent;
         --attendees-focusColor: rgb(123, 195, 255);
         --attendees-focusBorder: var(--attendees-focusColor);
         --attendees-focusBottomBorder: var(--attendees-focusColor);
         --attendees-focusImage: linear-gradient(rgb(205, 232, 255),
                                                 rgb(205, 232, 255));
     }
--- a/calendar/base/themes/common/dialogs/calendar-event-dialog.css
+++ b/calendar/base/themes/common/dialogs/calendar-event-dialog.css
@@ -11,21 +11,31 @@ dialog {
 dialog[systemcolors] {
     --eventBorderColor: ThreeDShadow;
     --eventWidgetBorderColor: ThreeDShadow;
     --eventGridStartBorderColor: ThreeDShadow;
 }
 
 #calendar-event-dialog,
 #calendar-task-dialog {
+    min-width: 444px;
+    min-height: 476px;
+}
+
+#calendar-event-dialog,
+#calendar-task-dialog,
+#calendar-event-dialog-inner,
+#calendar-task-dialog-inner {
     padding: 0px;
 }
 
 #calendar-event-dialog .todo-only,
-#calendar-task-dialog  .event-only {
+#calendar-task-dialog .event-only,
+#calendar-event-dialog-inner .todo-only,
+#calendar-task-dialog-inner .event-only {
     display: none;
 }
 
 #yearly-period-of-label,
 label.label {
     text-align: right;
 }
 
@@ -39,16 +49,28 @@ label.label {
 
 @media not all and (-moz-os-version: windows-xp) {
   .cal-event-toolbarbutton .toolbarbutton-icon {
     width: 18px;
     height: 18px;
   }
 }
 
+.icon-holder[type="calendarEvent"],
+.tabmail-tab[type="calendarEvent"] {
+    list-style-image: url(chrome://calendar-common/skin/calendar-event-tab.png);
+    -moz-image-region: auto;
+}
+
+.icon-holder[type="calendarTask"],
+.tabmail-tab[type="calendarTask"] {
+    list-style-image: url(chrome://calendar-common/skin/calendar-task-tab.png);
+    -moz-image-region: auto;
+}
+
 /*--------------------------------------------------------------------
  *   Event dialog tabbox section
  *-------------------------------------------------------------------*/
 
 #event-grid-tabbox {
     margin: 5px 0px;
 }
 
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..664cd8262f1dd88d3a74194ddd8bc9fadc54144f
GIT binary patch
literal 424
zc$@*K0ayNsP)<h;3K|Lk000e1NJLTq000mG000mO0ssI2kdbIM00006bW%=J00000
z003^L2ax~(0bNN%K~#9!m5ohH0$~(|@82m9{10sl3QG!G6p=|<S~g82wy-Y}A%zku
z0%;S5P%X@aa5rsg(XOA61UVMYIOBZSnHe>q$?9@AoO|Er-j}Fd*ZE>}a~DosWjkz@
zXL?qYWcV+`QYyfmuux_vgg2La+-hxyfaz}EpNot_?3@R0{SK$q+71EJZNirc4nm3f
zkv@kr>K(IM+aX}e$Gy*gF2HoPJ)`M*Z#CNmm~ycxMb$LD39TJJ^$;MybiOeuHB?2_
z8>+^pABB2@O+Uap0j?NNh8qiK>l3xQvb0qU#R^RFo=I{mE$7VkOTciQPFLOUf{X=x
zvb<Nq$#A@6{a}TT*CYin9fe(Q9}>=oVmGE2f<FitU^-YFeyxfNkxNNdI$jlITt(=1
zV1SK<GA{<0tf>n>ll7b7yMP%BslX7@3ojU65y}-2q0CzW-X&fHOozUKf9Vslbk-E1
SQt}o60000<MNUMnLSTZPxvD_`
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..58e9daf045109dfd70e17c71b52ec0e26a847ec7
GIT binary patch
literal 661
zc$@*10&4w<P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00079Nkl<Zc-oDR
z-A@uw7{<A7>u=~Xuj|S_*N4juwaq1y%*xSFN|~ctYyp~yGoX|#hKitRr6>YUmgMFl
zh)w(ej5HMHEG?tyVh+uzJ#kKPHZF9Y?YEu1d!FCkm&4iR@r#OeN$?+CYA!F&68pSE
zTP<2yd)~3b2Y2gpE*0>w{(F-`{$zIjY{rq#LE}a|HV*&f7`j^PoiuE35c6$~qJ*`f
z6#A-b$jQk=crFUl%Wew!=W@9iwm!s0+>7ZU8OCig7*rJjD(HVwmY8(tup0RQ`MpZ~
zTv^3LFqDSF{1jW8e$2U481Iw7aGwi)=AjHKFslVv4h~?XQv=1V5@ctcN9OSp3|{UT
z{8|~qVxS#?0V#UbJT%?O1H1QieF+xat>~zg;CpNhqZ1*#bNeV3vl%l%D^|a_@zEiN
zvqgaRnkyh3Cg@aN#r()Km>yIhy8MSRGrtDc8)NeBSxgT<g1bu$Re2U>osA$JCNNeP
zAv)XuW0fdP;II#3Wyz0-M-N}W49&9q<m$!$vdIn;w8#q)ajMa#5F#AgVOR_rd=0ta
z?Nj1~@-l2TJI#=6n&7##fC;9*?NHv2g)!>rz$cF#dYJ&0J{z5<1f;_R+PnEo5L(=#
z^mO-N(lvnYW;Hw$5jIZ=NQVg?OD-b%Rs*A=6jMvv6jikpZEYs_7uM4t8ImO(CaACA
z;)hp{S9O(Gj$=<qhGa>H32JX<V>{f7DVr99O^Q7s8ImQPQ@4*Epn{sR?1WV-qPOh_
vk|iCsLEVjW{5s+3gi?4C`z6`AK)Qbc-EwQ>k~z1F00000NkvXXu0mjf)BY`p
rename from calendar/base/content/dialogs/calendar-event-dialog.js
rename to calendar/lightning/content/lightning-item-iframe.js
--- a/calendar/base/content/dialogs/calendar-event-dialog.js
+++ b/calendar/lightning/content/lightning-item-iframe.js
@@ -22,26 +22,30 @@ try {
 // from within this file only.
 var gStartTime = null;
 var gEndTime = null;
 var gItemDuration = null;
 var gStartTimezone = null;
 var gEndTimezone = null;
 var gUntilDate = null;
 var gIsReadOnly = false;
-var gPrivacy = null;
 var gAttachMap = {};
-var gPriority = 0;
-var gStatus = "NONE";
 var gConfirmCancel = true;
 var gLastRepeatSelection = 0;
 var gIgnoreUpdate = false;
-var gShowTimeAs = null;
 var gWarning = false;
 var gPreviousCalendarId = null;
+var gTimezonesEnabled = null;
+var gTabInfoObject;
+var gConfig = {
+    priority: 0,
+    privacy: null,
+    status: "NONE",
+    showTimeAs: null
+}
 
 var eventDialogQuitObserver = {
   observe: function(aSubject, aTopic, aData) {
     // Check whether or not we want to veto the quit request (unless another
     // observer already did.
     if (aTopic == "quit-application-requested" &&
         (aSubject instanceof Components.interfaces.nsISupportsPRBool) &&
         !aSubject.data)
@@ -89,18 +93,17 @@ var eventDialogCalendarObserver = {
                 loadDialog(window.calendarItem);
             }
         }
     },
 
     onDeleteItem: function(aDeletedItem) {
         if (this.isObserving && "calendarItem" in window &&
             window.calendarItem && window.calendarItem.id == aDeletedItem.id) {
-            gConfirmCancel = false;
-            document.documentElement.cancelDialog();
+            cancelItem();
         }
     },
 
     onStartBatch: function() {},
     onEndBatch: function() {},
     onLoad: function() {},
     onAddItem: function() {},
     onError: function() {},
@@ -124,116 +127,189 @@ var eventDialogCalendarObserver = {
         }
     }
 };
 
 /**
  * Checks if the given calendar supports notifying attendees. The item is needed
  * since calendars may support notifications for only some types of items.
  *
- * @param aCalendar   The calendar to check
- * @param item        The item to check support for.
+ * @param {calICalendar} aCalendar  The calendar to check
+ * @param {calIItemBase} aItem      The item to check support for
  */
-function canNotifyAttendees(aCalendar, item) {
+function canNotifyAttendees(aCalendar, aItem) {
     try {
         var calendar = aCalendar.QueryInterface(Components.interfaces.calISchedulingSupport);
-        return (calendar.canNotify("REQUEST", item) && calendar.canNotify("CANCEL", item));
+        return (calendar.canNotify("REQUEST", aItem) && calendar.canNotify("CANCEL", aItem));
     } catch (exc) {
         return false;
     }
 }
 
 /**
- * Update menu items that rely on focus
+ * Sends an asynchronous message to the parent context that contains the
+ * iframe. Additional properties of aMessage are generally arguments
+ * that will be passed to the function named in aMessage.command.
+ *
+ * @param {Object} aMessage           The message to pass to the parent context
+ * @param {string} aMessage.command   The name of a function to call
  */
-function goUpdateGlobalEditMenuItems() {
-    goUpdateCommand('cmd_undo');
-    goUpdateCommand('cmd_redo');
-    goUpdateCommand('cmd_cut');
-    goUpdateCommand('cmd_copy');
-    goUpdateCommand('cmd_paste');
-    goUpdateCommand('cmd_selectAll');
+function sendMessage(aMessage) {
+    parent.postMessage(aMessage, "*");
 }
 
 /**
- * Update menu items that rely on the current selection
+ * Receives asynchronous messages from the parent context that contains the iframe.
+ *
+ * @param {MessageEvent} aEvent  Contains the message being received
  */
-function goUpdateSelectEditMenuItems() {
-    goUpdateCommand('cmd_cut');
-    goUpdateCommand('cmd_copy');
-    goUpdateCommand('cmd_delete');
-    goUpdateCommand('cmd_selectAll');
-}
-
-/**
- * Update menu items that relate to undo/redo
- */
-function goUpdateUndoEditMenuItems() {
-    goUpdateCommand('cmd_undo');
-    goUpdateCommand('cmd_redo');
-}
-
-/**
- * Update menu items that depend on clipboard contents
- */
-function goUpdatePasteMenuItems() {
-    goUpdateCommand('cmd_paste');
+function receiveMessage(aEvent) {
+    let validOrigin = gTabmail ? "chrome://messenger" : "chrome://calendar";
+    if (aEvent.origin !== validOrigin) {
+        return;
+    }
+    switch (aEvent.data.command) {
+        case "editAttendees": editAttendees(); break;
+        case "attachURL": attachURL(); break;
+        case "onCommandDeleteItem": onCommandDeleteItem(); break;
+        case "onCommandSave": onCommandSave(aEvent.data.isClosing); break;
+        case "onAccept": onAccept(); break;
+        case "onCancel": onCancel(aEvent.data.iframeId); break;
+        case "editStatus":
+            gConfig.status = aEvent.data.value;
+            updateStatus(gConfig.status);
+            break;
+        case "editShowTimeAs":
+            gConfig.showTimeAs = aEvent.data.value;
+            updateShowTimeAs(gConfig.showTimeAs);
+            break;
+        case "editPriority":
+            gConfig.priority = aEvent.data.value;
+            updatePriority(gConfig.priority);
+            break;
+        case "editPrivacy":
+            gConfig.privacy = aEvent.data.value;
+            updatePrivacy(gConfig.privacy);
+            break;
+        case "rotatePrivacy":
+            gConfig.privacy = rotatePrivacy(gConfig.privacy);
+            updatePrivacy(gConfig.privacy);
+            break;
+        case "rotateStatus":
+            gConfig.status = rotateStatus(gConfig.status,
+                                          cal.isEvent(window.calendarItem),
+                                          aEvent.data.noneCommandIsVisible);
+            updateStatus(gConfig.status);
+            break;
+        case "rotatePriority":
+            if (capSupported("priority")) {
+                gConfig.priority = rotatePriority(gConfig.priority);
+                updatePriority(gConfig.priority);
+            }
+            break;
+        case "rotateShowTimeAs":
+            gConfig.showTimeAs = rotateShowTimeAs(gConfig.showTimeAs);
+            updateShowTimeAs(gConfig.showTimeAs);
+            break;
+        case "toggleTimezoneLinks":
+            gTimezonesEnabled = aEvent.data.checked;
+            updateDateTime();
+            break;
+        case "toggleLink":
+            updateItemURL(aEvent.data.checked);
+            break;
+        case "closingWindowWithTabs":
+            let response = onCancel(aEvent.data.id, true);
+            sendMessage({
+                command: "replyToClosingWindowWithTabs",
+                response: response
+            });
+            break;
+    }
 }
 
 /**
  * Sets up the event dialog from the window arguments, also setting up all
  * dialog controls from the window's item.
  */
 function onLoad() {
     // Set a variable to allow/prevent actions when the dialog is loading.
     onLoad.isLoading = true;
 
+    window.addEventListener("message", receiveMessage, false);
+
+    // Move the args for the window dialog so they are positioned
+    // relative to the iframe, like in the tab.
+    if (!window.arguments) {
+        window.arguments = [parent.arguments[0]];
+        // XXX Should we delete the arguments in the parent context so
+        // they are only accessible in one place?  But they are needed for onLoad there.
+    }
+
     // first of all retrieve the array of
     // arguments this window has been called with.
-    var args = window.arguments[0];
+    let args = window.arguments[0];
+
+    intializeTabOrWindowVariables();
+
+    // Calling onLoad in the outer context is handled in calendar-event-dialog.xul
+    // for the window case, and here for the tab case because there is no onload
+    // event fired for the outer context for tabs.
+    if (gInTab) {
+        sendMessage({ command: "onLoad" });
+    }
+
+    // Needed so we can call switchToTab for the prompt about saving
+    // unsaved changes, to show the tab that the prompt is for.
+    if (gInTab) {
+        gTabInfoObject = gTabmail.currentTabInfo;
+    }
+
+    let cmdTimezone = parent.document.getElementById("cmd_timezone");
+    gTimezonesEnabled = cmdTimezone.getAttribute("checked") == "true";
 
     // The calling entity provides us with an object that is responsible
     // for recording details about the initiated modification. the 'finalize'
     // property is our hook in order to receive a notification in case the
     // operation needs to be terminated prematurely. This function will be
     // called if the calling entity needs to immediately terminate the pending
     // modification. In this case we serialize the item and close the window.
     if (args.job) {
-        // keep this context...
-        var self = this;
+        // keep the iframe id so we can close the right tab...
+        let iframeId = window.frameElement.id;
 
         // store the 'finalize'-functor in the provided job-object.
-        args.job.finalize = function() {
+        args.job.finalize = () => {
             // store any pending modifications...
-            self.onAccept();
-
-            var item = window.calendarItem;
+            this.onAccept();
+
+            let item = window.calendarItem;
 
             // ...and close the window.
-            window.close();
+            sendMessage({ command: "closeWindowOrTab", iframeId: iframeId });
 
             return item;
         }
     }
 
     window.fbWrapper = args.fbWrapper;
 
     // the most important attribute we expect from the
     // arguments is the item we'll edit in the dialog.
-    var item = args.calendarEvent;
-
-    // set the dialog-id to enable the right window-icon to be loaded.
+    let item = args.calendarEvent;
+
+    // set the iframe's top level id for event vs task
     if (!cal.isEvent(item)) {
-        setDialogId(document.documentElement, "calendar-task-dialog");
+        setDialogId(document.documentElement, "calendar-task-dialog-inner");
     }
 
     // new items should have a non-empty title.
     if (item.isMutable && (!item.title || item.title.length <= 0)) {
-        item.title = calGetString("calendar-event-dialog",
-                                  isEvent(item) ? "newEvent" : "newTask");
+        item.title = cal.calGetString("calendar-event-dialog",
+                                      isEvent(item) ? "newEvent" : "newTask");
     }
 
     window.onAcceptCallback = args.onOk;
     window.mode = args.mode
 
     // we store the item in the window to be able
     // to access this from any location. please note
     // that the item is either an occurrence [proxy]
@@ -241,19 +317,19 @@ function onLoad() {
     window.calendarItem = item;
     // store the initial date value for datepickers in New Task dialog
     window.initialStartDateValue = args.initialStartDateValue;
 
     // we store the array of attendees in the window.
     // clone each existing attendee since we still suffer
     // from the 'lost x-properties'-bug.
     window.attendees = [];
-    var attendees = item.getAttendees({});
+    let attendees = item.getAttendees({});
     if (attendees && attendees.length) {
-        for (var attendee of attendees) {
+        for (let attendee of attendees) {
             window.attendees.push(attendee.clone());
         }
     }
 
     window.organizer = null;
     if (item.organizer) {
         window.organizer = item.organizer.clone();
     } else if (item.getAttendees({}).length > 0) {
@@ -269,60 +345,55 @@ function onLoad() {
             window.organizer = organizer;
         }
     }
 
     // we store the recurrence info in the window so it
     // can be accessed from any location. since the recurrence
     // info is a property of the parent item we need to check
     // whether or not this item is a proxy or a parent.
-    var parentItem = item;
+    let parentItem = item;
     if (parentItem.parentItem != parentItem) {
         parentItem = parentItem.parentItem;
     }
 
     window.recurrenceInfo = null;
     if (parentItem.recurrenceInfo) {
         window.recurrenceInfo = parentItem.recurrenceInfo.clone();
     }
 
-    document.documentElement.getButton("accept")
-            .setAttribute("collapsed", "true");
-    document.documentElement.getButton("cancel")
-            .setAttribute("collapsed", "true");
-    document.documentElement.getButton("cancel")
-            .parentNode.setAttribute("collapsed", "true");
-
     // Set initial values for datepickers in New Tasks dialog
     if (isToDo(item)) {
         let initialDatesValue = cal.dateTimeToJsDate(args.initialStartDateValue);
         setElementValue("completed-date-picker", initialDatesValue);
         setElementValue("todo-entrydate", initialDatesValue);
         setElementValue("todo-duedate", initialDatesValue);
     }
     loadDialog(window.calendarItem);
 
-    opener.setCursor("auto");
-
-    if (typeof ToolbarIconColor !== 'undefined') {
+    gMainWindow.setCursor("auto");
+
+    if (typeof ToolbarIconColor !== "undefined") {
         ToolbarIconColor.init();
     }
 
     document.getElementById("item-title").focus();
     document.getElementById("item-title").select();
 
     // This causes the app to ask if the window should be closed when the
     // application is closed.
     Services.obs.addObserver(eventDialogQuitObserver,
                              "quit-application-requested", false);
 
     // Normally, Enter closes a <dialog>. We want this to rather on Ctrl+Enter.
     // Stopping event propagation doesn't seem to work, so just overwrite the
     // function that does this.
-    document.documentElement._hitEnter = function() {};
+    if (!gInTab) {
+        document.documentElement._hitEnter = function() {};
+    }
 
     // set up our calendar event observer
     eventDialogCalendarObserver.observe(item.calendar);
 
     onLoad.isLoading = false;
 }
 
 function onEventDialogUnload() {
@@ -337,16 +408,19 @@ function onEventDialogUnload() {
 /**
  * Handler function to be called when the accept button is pressed.
  *
  * @return      Returns true if the window should be closed
  */
 function onAccept() {
     dispose();
     onCommandSave(true);
+    if (!gWarning) {
+        sendMessage({ command: "closeWindowOrTab" });
+    }
     return !gWarning;
 }
 
 /**
  * Asks the user if the item should be saved and does so if requested. If the
  * user cancels, the window should stay open.
  *
  * XXX Could possibly be consolidated into onCancel()
@@ -354,26 +428,31 @@ function onAccept() {
  * @return    Returns true if the window should be closed.
  */
 function onCommandCancel() {
     // Allow closing if the item has not changed and no warning dialog has to be showed.
     if (!isItemChanged() && !gWarning) {
         return true;
     }
 
+    if (gInTab && gTabInfoObject) {
+        // Switch to the tab that the prompt refers to.
+        gTabmail.switchToTab(gTabInfoObject);
+    }
+
     var promptService = Components.interfaces.nsIPromptService;
 
-    var promptTitle = calGetString("calendar",
-                                   isEvent(window.calendarItem) ?
-                                      "askSaveTitleEvent" :
-                                      "askSaveTitleTask");
-    var promptMessage = calGetString("calendar",
-                                     isEvent(window.calendarItem) ?
-                                        "askSaveMessageEvent" :
-                                        "askSaveMessageTask");
+    var promptTitle = cal.calGetString("calendar",
+                                       isEvent(window.calendarItem) ?
+                                          "askSaveTitleEvent" :
+                                          "askSaveTitleTask");
+    var promptMessage = cal.calGetString("calendar",
+                                         isEvent(window.calendarItem) ?
+                                            "askSaveMessageEvent" :
+                                            "askSaveMessageTask");
 
     var flags = promptService.BUTTON_TITLE_SAVE *
                 promptService.BUTTON_POS_0 +
                 promptService.BUTTON_TITLE_CANCEL *
                 promptService.BUTTON_POS_1 +
                 promptService.BUTTON_TITLE_DONT_SAVE *
                 promptService.BUTTON_POS_2;
 
@@ -396,36 +475,57 @@ function onCommandCancel() {
             return true;
         default: // Cancel
             return false;
     }
 }
 
 /**
  * Handler function to be called when the cancel button is pressed.
+ * aPreventClose is true when closing the main window but leaving the tab open.
  *
- * @return    Returns true if the window should be closed.
+ * @param  {string}  aIframeId      (optional) iframe id of the tab to be closed
+ * @param  {boolean} aPreventClose  (optional) True means don't close, just ask about saving
+ * @return {boolean}                True if the tab or window should be closed
  */
-function onCancel() {
+function onCancel(aIframeId, aPreventClose) {
     // The datepickers need to remove the focus in order to trigger the
     // validation of the values just edited, with the keyboard, but not yet
     // confirmed (i.e. not followed by a click, a tab or enter keys pressure).
     document.documentElement.focus();
 
     if (!gConfirmCancel || (gConfirmCancel && onCommandCancel())) {
         dispose();
         // Don't allow closing the dialog when the user inputs a wrong
         // date then closes the dialog and answers with "Save" in
-        // the "Save Event" dialog.
+        // the "Save Event" dialog.  Don't allow closing the dialog if
+        // the main window is being closed but the tabs in it are not.
+
+        if (!gWarning && aPreventClose != true) {
+            sendMessage({ command: "closeWindowOrTab", iframeId: aIframeId });
+        }
         return !gWarning;
     }
     return false;
 }
 
 /**
+ * Cancels (closes) either the window or the tab, for example when the
+ * item is being deleted.
+ */
+function cancelItem() {
+    gConfirmCancel = false;
+    if (gInTab) {
+        onCancel();
+    } else {
+        sendMessage({ command: "cancelDialog" });
+    }
+}
+
+/**
  * Sets up all dialog controls from the information of the passed item.
  *
  * @param item      The item to parse information out of.
  */
 function loadDialog(item) {
     setElementValue("item-title", item.title);
     setElementValue("item-location", item.getProperty("LOCATION"));
 
@@ -450,29 +550,36 @@ function loadDialog(item) {
         for (var attachment of attachments) {
             addAttachment(attachment);
         }
     } else {
         updateAttachment();
     }
 
     // URL link
-    updateLink();
+    let cmdToggleLink = parent.document.getElementById("cmd_toggle_link");
+    let showLink = cmdToggleLink.getAttribute("checked") == "true";
+    // currently we always show the link for the tab case (if the link
+    // exists), since there is no menu item or toolbar item to show/hide it.
+    if (gInTab) {
+        showLink = true;
+    }
+    updateItemURL(showLink);
 
     // Description
     setElementValue("item-description", item.getProperty("DESCRIPTION"));
 
     // Status
     if (cal.isEvent(item)) {
-        gStatus = item.hasProperty("STATUS") ?
+        gConfig.status = item.hasProperty("STATUS") ?
             item.getProperty("STATUS") : "NONE";
-        if (gStatus == "NONE") {
-            document.getElementById("cmd_status_none").removeAttribute("hidden");
+        if (gConfig.status == "NONE") {
+            sendMessage({ command: "showCmdStatusNone" });
         }
-        updateStatus();
+        updateStatus(gConfig.status);
     } else {
         let todoStatus = document.getElementById("todo-status");
         setElementValue(todoStatus, item.getProperty("STATUS"));
         if (!todoStatus.selectedItem) {
             // No selected item means there was no <menuitem> that matches the
             // value given. Select the "NONE" item by default.
             setElementValue(todoStatus, "NONE");
         }
@@ -495,47 +602,59 @@ function loadDialog(item) {
         if (percentCompleteInteger < 0) {
             percentCompleteInteger = 0;
         } else if (percentCompleteInteger > 100) {
             percentCompleteInteger = 100;
         }
         setElementValue("percent-complete-textbox", percentCompleteInteger);
     }
 
-    // Set Item-Menu label to Event or Task
-    let menuItem = document.getElementById("item-menu");
-    menuItem.setAttribute("label", calGetString("calendar-event-dialog",
-                                          cal.isEvent(item) ? "itemMenuLabelEvent" : "itemMenuLabelTask"));
-    menuItem.setAttribute("accesskey", calGetString("calendar-event-dialog",
-                                          cal.isEvent(item) ? "itemMenuAccesskeyEvent2" : "itemMenuAccesskeyTask2"));
+    // When in a window, set Item-Menu label to Event or Task
+    if (!gInTab) {
+        let isEvent = cal.isEvent(item);
+
+        let labelString = isEvent ? "itemMenuLabelEvent" : "itemMenuLabelTask";
+        let label = cal.calGetString("calendar-event-dialog", labelString);
+
+        let accessKeyString = isEvent ? "itemMenuAccesskeyEvent2" : "itemMenuAccesskeyTask2";
+        let accessKey = cal.calGetString("calendar-event-dialog", accessKeyString);
+        sendMessage({
+            command: "initializeItemMenu",
+            label: label,
+            accessKey: accessKey
+        });
+    }
 
     // Priority
-    gPriority = parseInt(item.priority);
-    updatePriority();
+    gConfig.priority = parseInt(item.priority);
+    updatePriority(gConfig.priority);
 
     // Privacy
-    gPrivacy = item.privacy;
-    updatePrivacy();
+    gConfig.privacy = item.privacy;
+    updatePrivacy(gConfig.privacy);
 
     // load repeat details
     loadRepeat(item);
 
     // load reminder details
     loadReminders(item.getAlarms({}));
 
     // Synchronize link-top-image with keep-duration-button status
     let keepAttribute = document.getElementById("keepduration-button").getAttribute("keep") == "true";
     setBooleanAttribute("link-image-top", "keep", keepAttribute);
 
     updateDateTime();
 
     updateCalendar();
 
     // figure out what the title of the dialog should be and set it
-    updateTitle();
+    // tabs already have their title set
+    if (!gInTab) {
+        updateTitle();
+    }
 
     let notifyCheckbox = document.getElementById("notify-attendees-checkbox");
     let undiscloseCheckbox = document.getElementById("undisclose-attendees-checkbox");
     if (canNotifyAttendees(item.calendar, item)) {
         // visualize that the server will send out mail:
         notifyCheckbox.checked = true;
         // hide undisclosure control as this a client only feature
         undiscloseCheckbox.disabled = true;
@@ -552,18 +671,18 @@ function loadDialog(item) {
         // disable checkbox, if notifyCheckbox is not checked
         undiscloseCheckbox.disabled = (notifyCheckbox.checked == false);
     }
 
     updateAttendees();
     updateRepeat(true);
     updateReminder(true);
 
-    gShowTimeAs = item.getProperty("TRANSP");
-    updateShowTimeAs();
+    gConfig.showTimeAs = item.getProperty("TRANSP");
+    updateShowTimeAs(gConfig.showTimeAs);
 }
 
 /**
  * Enables/disables undiscloseCheckbox on (un)checking notifyCheckbox
  */
 function changeUndiscloseCheckboxStatus() {
     let notifyCheckbox = document.getElementById("notify-attendees-checkbox");
     let undiscloseCheckbox = document.getElementById("undisclose-attendees-checkbox");
@@ -675,20 +794,29 @@ function loadDateTime(item) {
             endTime = endTime.getInTimezone(kDefaultTimezone);
         } else {
             gEndTimezone = kDefaultTimezone;
         }
         if (hasEntryDate && hasDueDate) {
             duration = endTime.subtractDate(startTime);
         }
         setElementValue("cmd_attendees", true, "disabled");
+        sendMessage({
+            command: "updatePanelState",
+            argument: {attendeesCommand: false}
+        });
         setBooleanAttribute("keepduration-button", "disabled", !(hasEntryDate && hasDueDate));
         gStartTime = startTime;
         gEndTime = endTime;
         gItemDuration = duration;
+    } else {
+        sendMessage({
+            command: "updatePanelState",
+            argument: {attendeesCommand: true}
+        });
     }
 }
 
 /**
  * Toggles the "keep" attribute every time the keepduration-button is pressed.
  */
 function toggleKeepDuration() {
     let kdb = document.getElementById("keepduration-button");
@@ -733,26 +861,25 @@ function dateTimeControls2State(aStartDa
         startWidgetId = "todo-entrydate";
         endWidgetId = "todo-duedate";
     }
 
     var saveStartTime = gStartTime;
     var saveEndTime = gEndTime;
     var kDefaultTimezone = calendarDefaultTimezone();
 
-    let timezonesEnabled = document.getElementById('cmd_timezone')
-                                   .getAttribute('checked') == 'true';
     if (gStartTime) {
         // jsDate is always in OS timezone, thus we create a calIDateTime
         // object from the jsDate representation then we convert the timezone
         // in order to keep gStartTime in default timezone.
-        gStartTime = cal.jsDateToDateTime(getElementValue(startWidgetId),
-                                          (timezonesEnabled || allDay) ? gStartTimezone : kDefaultTimezone);
-        if (timezonesEnabled || allDay) {
+        if (gTimezonesEnabled || allDay) {
+            gStartTime = cal.jsDateToDateTime(getElementValue(startWidgetId), gStartTimezone);
             gStartTime = gStartTime.getInTimezone(kDefaultTimezone);
+        } else {
+            gStartTime = cal.jsDateToDateTime(getElementValue(startWidgetId), kDefaultTimezone);
         }
         gStartTime.isDate = allDay;
     }
     if (gEndTime) {
         if (aStartDatepicker) {
             // Change the End date in order to keep the duration.
             gEndTime = gStartTime.clone();
             if (gItemDuration) {
@@ -760,22 +887,22 @@ function dateTimeControls2State(aStartDa
             }
         } else {
             let timezone = gEndTimezone;
             if (timezone.isUTC) {
                 if (gStartTime && !compareObjects(gStartTimezone, gEndTimezone)) {
                     timezone = gStartTimezone;
                 }
             }
-            gEndTime = cal.jsDateToDateTime(getElementValue(endWidgetId),
-                                            (timezonesEnabled || allDay) ? timezone : kDefaultTimezone);
-            if (timezonesEnabled || allDay) {
+            if (gTimezonesEnabled || allDay) {
+                gEndTime = cal.jsDateToDateTime(getElementValue(endWidgetId), timezone);
                 gEndTime = gEndTime.getInTimezone(kDefaultTimezone);
+            } else {
+                gEndTime = cal.jsDateToDateTime(getElementValue(endWidgetId), kDefaultTimezone);
             }
-
             gEndTime.isDate = allDay;
             if (keepAttribute && gItemDuration) {
                 // Keepduration-button links the the Start to the End date. We
                 // have to change the Start date in order to keep the duration.
                 let fduration = gItemDuration.clone();
                 fduration.isNegative = true;
                 gStartTime = gEndTime.clone();
                 gStartTime.addDuration(fduration);
@@ -1138,18 +1265,18 @@ function saveDialog(item) {
         item.addAttachment(att);
     }
 
     // Description
     setItemProperty(item, "DESCRIPTION", getElementValue("item-description"));
 
     // Event Status
     if (isEvent(item)) {
-        if(gStatus && gStatus != "NONE") {
-            item.setProperty("STATUS", gStatus);
+        if (gConfig.status && gConfig.status != "NONE") {
+            item.setProperty("STATUS", gConfig.status);
         } else {
             item.deleteProperty("STATUS");
         }
     } else {
         var status = getElementValue("todo-status");
         if (status != "COMPLETED") {
             item.completedDate = null;
         }
@@ -1159,31 +1286,31 @@ function saveDialog(item) {
     // set the "PRIORITY" property if a valid priority has been
     // specified (any integer value except *null*) OR the item
     // already specifies a priority. in any other case we don't
     // need this property and can safely delete it. we need this special
     // handling since the WCAP provider always includes the priority
     // with value *null* and we don't detect changes to this item if
     // we delete this property.
     if (capSupported("priority") &&
-        (gPriority || item.hasProperty("PRIORITY"))) {
-        item.setProperty("PRIORITY", gPriority);
+        (gConfig.priority || item.hasProperty("PRIORITY"))) {
+        item.setProperty("PRIORITY", gConfig.priority);
     } else {
         item.deleteProperty("PRIORITY");
     }
 
     // Transparency
-    if (gShowTimeAs) {
-        item.setProperty("TRANSP", gShowTimeAs);
+    if (gConfig.showTimeAs) {
+        item.setProperty("TRANSP", gConfig.showTimeAs);
     } else {
         item.deleteProperty("TRANSP");
     }
 
     // Privacy
-    setItemProperty(item, "CLASS", gPrivacy, "privacy");
+    setItemProperty(item, "CLASS", gConfig.privacy, "privacy");
 
     if (item.status == "COMPLETED" && isToDo(item)) {
         var elementValue = getElementValue("completed-date-picker");
         item.completedDate = cal.jsDateToDateTime(elementValue);
     }
 
     saveReminder(item);
 }
@@ -1260,18 +1387,19 @@ function updateTitle() {
     let strName;
     if (cal.isEvent(window.calendarItem)) {
         strName = (window.mode == "new" ? "newEventDialog" : "editEventDialog");
     } else if (cal.isToDo(window.calendarItem)) {
         strName = (window.mode == "new" ? "newTaskDialog" : "editTaskDialog");
     } else {
         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
     }
-    document.title = cal.calGetString("calendar", strName) + ": " +
-                        getElementValue("item-title");
+    let newTitle = cal.calGetString("calendar", strName) + ": " +
+                      getElementValue("item-title");
+    sendMessage({ command: "updateTitle", argument: newTitle });
 }
 
 /**
  * Update the disabled status of the accept button. The button is enabled if all
  * parts of the dialog have options selected that make sense.
  * constraining factors like
  */
 function updateAccept() {
@@ -1288,19 +1416,17 @@ function updateAccept() {
     } else {
         startDate = getElementValue("todo-has-entrydate", "checked") ?
             cal.jsDateToDateTime(getElementValue("todo-entrydate")) : null;
         endDate = getElementValue("todo-has-duedate", "checked") ?
             cal.jsDateToDateTime(getElementValue("todo-duedate")) : null;
     }
 
     if (startDate && endDate) {
-        let timezonesEnabled = document.getElementById('cmd_timezone')
-                                       .getAttribute('checked') == 'true';
-        if (timezonesEnabled) {
+        if (gTimezonesEnabled) {
             var startTimezone = gStartTimezone;
             var endTimezone = gEndTimezone;
             if (endTimezone.isUTC) {
                 if (!compareObjects(gStartTimezone, gEndTimezone)) {
                     endTimezone = gStartTimezone;
                 }
             }
 
@@ -1343,18 +1469,17 @@ function updateAccept() {
 
 /**
  * Enables/disables the commands cmd_accept and cmd_save related to the
  * save operation.
  *
  * @param aEnable           true: enables the command
  */
 function enableAcceptCommand(aEnable) {
-    setElementValue("cmd_accept", !aEnable, "disabled");
-    setElementValue("cmd_save", !aEnable, "disabled");
+    sendMessage({ command: "enableAcceptCommand", argument: aEnable });
 }
 
 // Global variables used to restore start and end date-time when changing the
 // "all day" status in the onUpdateAllday() function.
 var gOldStartTime = null;
 var gOldEndTime = null;
 var gOldStartTimezone = null;
 var gOldEndTimezone = null;
@@ -1497,18 +1622,18 @@ function openNewCardDialog() {
 
 /**
  * Update the transparency status of this dialog, depending on if the event
  * is all-day or not.
  *
  * @param allDay    If true, the event is all-day
  */
 function setShowTimeAs(allDay) {
-    gShowTimeAs = cal.getEventDefaultTransparency(allDay);
-    updateShowTimeAs();
+    gConfig.showTimeAs = cal.getEventDefaultTransparency(allDay);
+    updateShowTimeAs(gConfig.showTimeAs);
 }
 
 function editAttendees() {
     let savedWindow = window;
     let calendar = getCurrentCalendar();
 
     var callback = function(attendees, organizer, startTime, endTime) {
         savedWindow.attendees = attendees;
@@ -1561,382 +1686,153 @@ function editAttendees() {
     if (isAllDay) {
         startTime.isDate = true;
         endTime.isDate = true;
         endTime.day += 1;
     } else {
         startTime.isDate = false;
         endTime.isDate = false;
     }
-
-    let displayTimezone = document.getElementById('cmd_timezone')
-                                  .getAttribute('checked') == 'true';
-
     var args = new Object();
     args.startTime = startTime;
     args.endTime = endTime;
-    args.displayTimezone = displayTimezone;
+    args.displayTimezone = gTimezonesEnabled;
     args.attendees = window.attendees;
     args.organizer = window.organizer && window.organizer.clone();
     args.calendar = calendar;
     args.item = window.calendarItem;
     args.onOk = callback;
     args.fbWrapper = window.fbWrapper;
 
     // open the dialog modally
     openDialog(
         "chrome://calendar/content/calendar-event-dialog-attendees.xul",
         "_blank",
         "chrome,titlebar,modal,resizable",
         args);
 }
 
 /**
- * This function rotates the Privacy of an item to the next value
+ * Rotates the Privacy of an item to the next value
  * following the sequence  -> PUBLIC -> CONFIDENTIAL -> PRIVATE ->.
+ *
+ * @param  {string} aPrivacy  The current/old privacy value
+ * @return {string}           The new privacy value
  */
-function rotatePrivacy() {
+function rotatePrivacy(aPrivacy) {
     const states = ["PUBLIC","CONFIDENTIAL","PRIVATE"];
-    gPrivacy = states[(states.indexOf(gPrivacy) + 1) % states.length];
-    updatePrivacy();
-}
-
-/**
- * This function sets the privacy of an item to the value specified by
- * the attribute "privacy" of the UI-element "target".
- *
- * @param target    the calling UI-element;
- * @param event     the UI-element selection event (only for the popup menu
- *                  event-privacy-menupopup in the Privacy toolbar button).
- */
-function editPrivacy(target, event) {
-    gPrivacy = target.getAttribute("privacy");
-    if (event) {
-        event.stopPropagation();
-    }
-    updatePrivacy();
+    return states[(states.indexOf(aPrivacy) + 1) % states.length];
 }
 
 /**
- * This function updates the UI according to the global field 'gPrivacy' and the
+ * Updates privacy in the UI according to the aValue argument and the
  * selected calendar. If the selected calendar does not support privacy or only
  * certain values, these are removed from the UI. This function should be called
- * any time that gPrivacy is updated.
+ * any time that gConfig.privacy is updated, passing the new value as an argument.
+ *
+ * @param {string} aValue  The new privacy value
  */
-function updatePrivacy() {
-    let calendar = getCurrentCalendar();
-    let hasPrivacy = capSupported("privacy");
-
-    if (hasPrivacy) {
-        var numChilds;
-        var privacyValues = capValues("privacy",
-                                      ["PUBLIC", "CONFIDENTIAL", "PRIVATE"]);
-
-        // Update privacy capabilities (toolbar)
-        var menupopup = document.getElementById("event-privacy-menupopup");
-        if (menupopup) {
-            // Only update the toolbar if the button is actually there
-            numChilds = menupopup.childNodes.length;
-            for (var i = 0; i < numChilds; i++) {
-                var node = menupopup.childNodes[i];
-                if (node.hasAttribute("privacy")) {
-                    var currentPrivacyValue = node.getAttribute("privacy");
-                    // Collapsed state
-
-                    // Hide the toolbar if the value is unsupported or is for a
-                    // specific provider and doesn't belong to the current provider.
-                    if (!privacyValues.includes(currentPrivacyValue) ||
-                        (currentProvider && currentProvider != calendar.type)) {
-                        node.setAttribute("collapsed", "true");
-                    } else {
-                        node.removeAttribute("collapsed");
-                    }
-
-                    // Checked state
-                    if (gPrivacy == currentPrivacyValue) {
-                        node.setAttribute("checked", "true");
-                    } else {
-                        node.removeAttribute("checked");
-                    }
-                }
-            }
+function updatePrivacy(aValue) {
+    sendMessage({
+        command: "updatePanelState",
+        argument: {
+            privacy: aValue,
+            hasPrivacy: capSupported("privacy"),
+            calendarType: getCurrentCalendar().type,
+            privacyValues: capValues("privacy",
+                            ["PUBLIC", "CONFIDENTIAL", "PRIVATE"])
         }
-
-        // Update privacy capabilities (menu)
-        menupopup = document.getElementById("options-privacy-menupopup");
-        numChilds = menupopup.childNodes.length;
-        for (var i = 0; i < numChilds; i++) {
-            var node = menupopup.childNodes[i];
-            var currentProvider = node.getAttribute("provider");
-            if (node.hasAttribute("privacy")) {
-                var currentPrivacyValue = node.getAttribute("privacy");
-                // Collapsed state
-
-                // Hide the menu if the value is unsupported or is for a
-                // specific provider and doesn't belong to the current provider.
-                if (!privacyValues.includes(currentPrivacyValue) ||
-                    (currentProvider && currentProvider != calendar.type)) {
-                    node.setAttribute("collapsed", "true");
-                } else {
-                    node.removeAttribute("collapsed");
-                }
-
-                // Checked state
-                if (gPrivacy == currentPrivacyValue) {
-                    node.setAttribute("checked", "true");
-                } else {
-                    node.removeAttribute("checked");
-                }
-            }
-        }
-
-        // Update privacy capabilities (statusbar)
-        var privacyPanel = document.getElementById("status-privacy");
-        var hasAnyPrivacyValue = false;
-        numChilds = privacyPanel.childNodes.length;
-        for (var i = 0; i < numChilds; i++) {
-            var node = privacyPanel.childNodes[i];
-            var currentProvider = node.getAttribute("provider");
-            if (node.hasAttribute("privacy")) {
-                var currentPrivacyValue = node.getAttribute("privacy");
-
-                // Hide the panel if the value is unsupported or is for a
-                // specific provider and doesn't belong to the current provider,
-                // or is not the items privacy value
-                if (!privacyValues.includes(currentPrivacyValue) ||
-                    (currentProvider && currentProvider != calendar.type) ||
-                    gPrivacy != currentPrivacyValue) {
-                    node.setAttribute("collapsed", "true");
-                } else {
-                    node.removeAttribute("collapsed");
-                    hasAnyPrivacyValue = true;
-                }
-            }
-        }
-
-        // Don't show the status panel if no valid privacy value is selected
-        if (!hasAnyPrivacyValue) {
-            privacyPanel.setAttribute("collapsed", "true");
-        } else {
-            privacyPanel.removeAttribute("collapsed");
-        }
-
-    } else {
-        setElementValue("button-privacy", !hasPrivacy && "true", "disabled");
-        setElementValue("options-privacy-menu", !hasPrivacy && "true", "disabled");
-        setElementValue("status-privacy", !hasPrivacy && "true", "collapsed");
+    });
+}
+
+/**
+ * Rotates the Priority of an item to the next value
+ * following the sequence -> Not specified -> Low -> Normal -> High ->.
+ *
+ * @param  {number} aPriority  The current/old priority
+ * @return {number}            The new priority
+ */
+function rotatePriority(aPriority) {
+    if (aPriority <= 0 || aPriority > 9) { // not specified
+        return 9;
+    } else if (aPriority >= 1 && aPriority <= 4) { // high
+        return 0;
+    } else if (aPriority == 5) {                   // normal
+        return 1;
+    } else if (aPriority >= 6 && aPriority <= 9) { // low
+        return 5;
     }
 }
 
 /**
- * This function rotates the Priority of an item to the next value
- * following the sequence -> Not specified -> Low -> Normal -> High ->.
- */
-function rotatePriority() {
-    let hasPriority = capSupported("priority");
-    if (hasPriority) {
-        if (gPriority <= 0 || gPriority > 9) {         // not specified
-            gPriority = 9;
-        } else if (gPriority >= 1 && gPriority <= 4) { // high
-            gPriority = 0;
-        } else if (gPriority == 5) {                   // normal
-            gPriority = 1;
-        } else if (gPriority >= 6 && gPriority <= 9) { // low
-            gPriority = 5;
-        }
-        updatePriority();
-    }
-}
-
-/**
- * Handler function to change the priority from the dialog elements
+ * Update the dialog controls related to priority.
  *
- * @param target    A XUL node with a value attribute which should be the new
- *                    priority.
- */
-function editPriority(target) {
-    gPriority = parseInt(target.getAttribute("value"));
-    updatePriority();
-}
-
-/**
- * Update the dialog controls related to priority.
+ * @param {string} aValue  The new priority value
  */
-function updatePriority() {
-    // Set up capabilities
-    var hasPriority = capSupported("priority");
-    if (document.getElementById("button-priority")) {
-        setElementValue("button-priority", !hasPriority && "true", "disabled");
-    }
-    setElementValue("options-priority-menu", !hasPriority && "true", "disabled");
-    setElementValue("status-priority", !hasPriority && "true", "collapsed");
-
-    if (hasPriority) {
-        var priorityLevel = "none";
-        if (gPriority >= 1 && gPriority <= 4) {
-            priorityLevel = "high";
-        } else if (gPriority == 5) {
-            priorityLevel = "normal";
-        } else if (gPriority >= 6 && gPriority <= 9) {
-            priorityLevel = "low";
+ function updatePriority(aValue) {
+    sendMessage({
+        command: "updatePanelState",
+        argument: {
+            priority: aValue,
+            hasPriority: capSupported("priority")
         }
-
-        var priorityNone = document.getElementById("cmd_priority_none");
-        var priorityLow = document.getElementById("cmd_priority_low");
-        var priorityNormal = document.getElementById("cmd_priority_normal");
-        var priorityHigh = document.getElementById("cmd_priority_high");
-
-        priorityNone.setAttribute("checked",
-                                  priorityLevel == "none" ? "true" : "false");
-        priorityLow.setAttribute("checked",
-                                 priorityLevel == "low" ? "true" : "false");
-        priorityNormal.setAttribute("checked",
-                                    priorityLevel == "normal" ? "true" : "false");
-        priorityHigh.setAttribute("checked",
-                                  priorityLevel == "high" ? "true" : "false");
-
-        // Status bar panel
-        var priorityPanel = document.getElementById("status-priority");
-        if (priorityLevel == "none") {
-            // If the priority is none, don't show the status bar panel
-            priorityPanel.setAttribute("collapsed", "true");
-        } else {
-            priorityPanel.removeAttribute("collapsed");
-            var numChilds = priorityPanel.childNodes.length;
-            var foundPriority = false;
-            for (var i = 0; i < numChilds; i++) {
-                var node = priorityPanel.childNodes[i];
-                if (foundPriority) {
-                    node.setAttribute("collapsed", "true");
-                } else {
-                    node.removeAttribute("collapsed");
-                }
-                if (node.getAttribute("value") == priorityLevel) {
-                    foundPriority = true;
-                }
-            }
-        }
-    }
+    });
 }
 
 /**
  * Rotate the Status of an item to the next value following
  * the sequence -> NONE -> TENTATIVE -> CONFIRMED -> CANCELLED ->.
+ *
+ * @param  {string}  aStatus                The current/old status
+ * @param  {boolean} aIsEvent               Is the item an event (not a task)
+ * @param  {boolean} aNoneCommandIsVisible  Is the "none" command visible
+ * @return {number}                         The new priority
  */
-function rotateStatus() {
+function rotateStatus(aStatus, aIsEvent, aNoneCommandIsVisible) {
     let states = ["TENTATIVE","CONFIRMED","CANCELLED"];
-    let noneCmd = document.getElementById("cmd_status_none");
-    // If control for status "NONE" is visible, allow rotating to it.
-    if (cal.isEvent(window.calendarItem) && !noneCmd.hasAttribute("hidden")) {
+    // If control for status "NONE" ("cmd_status_none") is visible,
+    // allow rotating to it.
+    if (aIsEvent && aNoneCommandIsVisible) {
         states.unshift("NONE");
     }
-    gStatus = states[(states.indexOf(gStatus) + 1) % states.length];
-    updateStatus();
-}
-
-/**
- * Handler function to change the status from the dialog elements
- *
- * @param target    A XUL node with a value attribute which should be the new
- *                    status.
- */
-function editStatus(target) {
-    gStatus = target.getAttribute("value");
-    updateStatus();
+    return states[(states.indexOf(aStatus) + 1) % states.length];
 }
 
 /**
  * Update the dialog controls related to status.
+ *
+ * @param {string} aValue  The new status value
  */
-function updateStatus() {
-    let found = false;
-    const statusLabels = ["status-status-tentative-label",
-                          "status-status-confirmed-label",
-                          "status-status-cancelled-label"];
-    setBooleanAttribute("status-status", "collapsed", true);
-    [ "cmd_status_none",
-      "cmd_status_tentative",
-      "cmd_status_confirmed",
-      "cmd_status_cancelled" ].forEach(
-          function(element, index, array) {
-              let node = document.getElementById(element);
-              let matches = (node.getAttribute("value") == gStatus);
-              found = found || matches;
-
-              node.setAttribute("checked", matches ? "true" : "false");
-
-              if (index > 0) {
-                  setBooleanAttribute(statusLabels[index-1], "hidden", !matches);
-                  if (matches) {
-                      setBooleanAttribute("status-status", "collapsed", false);
-                  }
-              }
-          }
-      );
-    if (!found) {
-        // The current Status value is invalid. Change the status to not
-        // specified and update the status again.
-        gStatus = "NONE";
-        updateStatus();
-    }
+function updateStatus(aValue) {
+    sendMessage({ command: "updatePanelState", argument: { status: aValue } });
 }
 
 /**
- * Toggles the transparency (Show Time As property) of an item
+ * Toggles the transparency ("Show Time As" property) of an item
  * from BUSY (Opaque) to FREE (Transparent).
+ *
+ * @param  {string} aShowTimeAs  The current/old value
+ * @return {string}              The new value
  */
-function rotateShowTimeAs() {
+function rotateShowTimeAs(aShowTimeAs) {
     const states = ["OPAQUE", "TRANSPARENT"];
-    gShowTimeAs = states[(states.indexOf(gShowTimeAs) + 1) % states.length];
-    updateShowTimeAs();
-}
-
-/**
- * Handler function to change the transparency from the dialog elements
- *
- * @param target    A XUL node with a value attribute which should be the new
- *                    transparency.
- */
-function editShowTimeAs(target) {
-    gShowTimeAs = target.getAttribute("value");
-    updateShowTimeAs();
+    return states[(states.indexOf(aShowTimeAs) + 1) % states.length];
 }
 
 /**
  * Update the dialog controls related to transparency.
+ *
+ * @param {string} aValue  The new transparency value
  */
-function updateShowTimeAs() {
+function updateShowTimeAs(aValue) {
     if (cal.isEvent(window.calendarItem)) {
-        var showAsBusy = document.getElementById("cmd_showtimeas_busy");
-        var showAsFree = document.getElementById("cmd_showtimeas_free");
-
-        showAsBusy.setAttribute("checked",
-                                gShowTimeAs == "OPAQUE" ? "true" : "false");
-        showAsFree.setAttribute("checked",
-                                gShowTimeAs == "TRANSPARENT" ? "true" : "false");
-
-        setBooleanAttribute("status-freebusy",
-                            "collapsed",
-                            gShowTimeAs != "OPAQUE" && gShowTimeAs != "TRANSPARENT");
-        setBooleanAttribute("status-freebusy-free-label", "hidden", gShowTimeAs == "OPAQUE");
-        setBooleanAttribute("status-freebusy-busy-label", "hidden", gShowTimeAs == "TRANSPARENT");
+        sendMessage({ command: "updatePanelState", argument: { showTimeAs: aValue } });
     }
 }
 
-/**
- * Toggles the command that allows to enable the timezone
- * links in the dialog.
- */
-function toggleTimezoneLinks() {
-    let cmdTimezone = document.getElementById('cmd_timezone');
-    let isChecked = cmdTimezone.getAttribute("checked") == "true";
-    cmdTimezone.setAttribute("checked", isChecked ? "false" : "true");
-    updateDateTime();
-}
-
 function loadCloudProviders() {
     let cloudFileEnabled = Preferences.get("mail.cloud_files.enabled", false)
     let cmd = document.getElementById("cmd_attach_cloud");
 
     if (!cloudFileEnabled) {
         // If cloud file support is disabled, just hide the attach item
         cmd.hidden = true;
         return;
@@ -2432,46 +2328,48 @@ function updateCalendar() {
     // TODO: the code above decided about whether or not the item is readonly.
     // below we enable/disable all controls based on this decision.
     // unfortunately some controls need to be disabled based on some other
     // criteria. this is why we enable all controls in case the item is *not*
     // readonly and run through all those updateXXX() functions to disable
     // them again based on the specific logic build into those function. is this
     // really a good idea?
     if (gIsReadOnly) {
-        var disableElements = document.getElementsByAttribute("disable-on-readonly", "true");
-        for (var i = 0; i < disableElements.length; i++) {
-            disableElements[i].setAttribute('disabled', 'true');
+        let disableElements = document.getElementsByAttribute("disable-on-readonly", "true");
+        for (let element of disableElements) {
+            element.setAttribute("disabled", "true");
 
             // we mark link-labels with the hyperlink attribute, since we need
             // to remove their class in case they get disabled. TODO: it would
             // be better to create a small binding for those link-labels
             // instead of adding those special stuff.
-            if (disableElements[i].hasAttribute('hyperlink')) {
-                disableElements[i].removeAttribute('class');
-                disableElements[i].removeAttribute('onclick');
+            if (element.hasAttribute("hyperlink")) {
+                element.removeAttribute("class");
+                element.removeAttribute("onclick");
             }
         }
 
-        var collapseElements = document.getElementsByAttribute("collapse-on-readonly", "true");
-        for (var i = 0; i < collapseElements.length; i++) {
-            collapseElements[i].setAttribute('collapsed', 'true');
+        let collapseElements = document.getElementsByAttribute("collapse-on-readonly", "true");
+        for (let element of collapseElements) {
+            element.setAttribute("collapsed", "true");
         }
     } else {
-        var enableElements = document.getElementsByAttribute("disable-on-readonly", "true");
-        for (var i = 0; i < enableElements.length; i++) {
-            enableElements[i].removeAttribute('disabled');
-            if (enableElements[i].hasAttribute('hyperlink')) {
-                enableElements[i].setAttribute('class', 'text-link');
+        sendMessage({ command: "removeDisableAndCollapseOnReadonly" });
+
+        let enableElements = document.getElementsByAttribute("disable-on-readonly", "true");
+        for (let element of enableElements) {
+            element.removeAttribute("disabled");
+            if (element.hasAttribute("hyperlink")) {
+                element.setAttribute("class", "text-link");
             }
         }
 
-        var collapseElements = document.getElementsByAttribute("collapse-on-readonly", "true");
-        for (var i = 0; i < collapseElements.length; i++) {
-            collapseElements[i].removeAttribute('collapsed');
+        let collapseElements = document.getElementsByAttribute("collapse-on-readonly", "true");
+        for (let element of collapseElements) {
+            element.removeAttribute("collapsed");
         }
 
         // Task completed date
         if (item.completedDate) {
             updateToDoStatus(item.status, cal.dateTimeToJsDate(item.completedDate));
         } else {
             updateToDoStatus(item.status);
         }
@@ -2480,19 +2378,19 @@ function updateCalendar() {
         item = window.calendarItem;
         if (item.parentItem != item) {
             disableElement("item-repeat");
             disableElement("repeat-until-datepicker");
             var repeatDetails = document.getElementById("repeat-details");
             var numChilds = repeatDetails.childNodes.length;
             for (var i = 0; i < numChilds; i++) {
                 var node = repeatDetails.childNodes[i];
-                node.setAttribute('disabled', 'true');
-                node.removeAttribute('class');
-                node.removeAttribute('onclick');
+                node.setAttribute("disabled", "true");
+                node.removeAttribute("class");
+                node.removeAttribute("onclick");
             }
         }
 
         // If the item is a proxy occurrence/instance, a few things aren't
         // valid.
         if (item.parentItem != item) {
             disableElement("item-calendar");
 
@@ -3036,131 +2934,47 @@ function onCommandDeleteItem() {
                                     null,
                                     promptTitle,
                                     promptMessage);
         if (!answerDelete) {
             return;
         }
     }
 
-    if (window.mode != "new") {
+    if (window.mode == "new") {
+        cancelItem();
+    } else {
         let deleteListener = {
             // when deletion of item is complete, close the dialog
             onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDetail) {
                 // Check if the current window has a calendarItem first, because in case of undo
                 // window refers to the main window and we would get a 'calendarItem is undefined' warning.
                 if ("calendarItem" in window) {
                     if (aId == window.calendarItem.id && Components.isSuccessCode(aStatus)) {
-                        gConfirmCancel = false;
-                        document.documentElement.cancelDialog();
+                        cancelItem();
                     } else {
                         eventDialogCalendarObserver.observe(window.calendarItem.calendar);
                     }
                 }
             }
         };
 
         eventDialogCalendarObserver.cancel();
         if (window.calendarItem.parentItem.recurrenceInfo && window.calendarItem.recurrenceId) {
             // if this is a single occurrence of a recurring item
             let newItem = window.calendarItem.parentItem.clone();
             newItem.recurrenceInfo.removeOccurrenceAt(window.calendarItem.recurrenceId);
 
-            window.opener.doTransaction("modify", newItem, newItem.calendar,
-                                        window.calendarItem.parentItem, deleteListener);
+            gMainWindow.doTransaction("modify", newItem, newItem.calendar,
+                                      window.calendarItem.parentItem, deleteListener);
         } else {
-            window.opener.doTransaction("delete", window.calendarItem, window.calendarItem.calendar,
-                                        null, deleteListener);
+            gMainWindow.doTransaction("delete", window.calendarItem, window.calendarItem.calendar,
+                                      null, deleteListener);
         }
-    } else {
-        gConfirmCancel = false;
-        document.documentElement.cancelDialog();
-    }
-}
-
-/**
- * Handler function to toggle toolbar visibility.
- *
- * @param aToolbarId        The id of the XUL toolbar node to toggle.
- * @param aMenuitemId       The corresponding menuitem in the view menu.
- */
-function onCommandViewToolbar(aToolbarId, aMenuItemId) {
-    var toolbar = document.getElementById(aToolbarId);
-    var menuItem = document.getElementById(aMenuItemId);
-
-    if (!toolbar || !menuItem) {
-        return;
     }
-
-    var toolbarCollapsed = toolbar.collapsed;
-
-    // toggle the checkbox
-    menuItem.setAttribute('checked', toolbarCollapsed);
-
-    // toggle visibility of the toolbar
-    toolbar.collapsed = !toolbarCollapsed;
-
-    document.persist(aToolbarId, 'collapsed');
-    document.persist(aMenuItemId, 'checked');
-}
-
-/**
- * DialogToolboxCustomizeDone() is called after the customize toolbar dialog
- * has been closed by the user. We need to restore the state of all buttons
- * and commands of all customizable toolbars.
- *
- * @param aToolboxChanged       If true, the toolbox has changed.
- */
-function DialogToolboxCustomizeDone(aToolboxChanged) {
-
-    var menubar = document.getElementById("event-menubar");
-    for (var i = 0; i < menubar.childNodes.length; ++i) {
-        menubar.childNodes[i].removeAttribute("disabled");
-    }
-
-    // make sure our toolbar buttons have the correct enabled state restored to them...
-    document.commandDispatcher.updateCommands('itemCommands');
-
-    // Enable the toolbar context menu items
-    document.getElementById("cmd_customize").removeAttribute("disabled");
-
-    // Update privacy items to make sure the toolbarbutton's menupopup is set
-    // correctly
-    updatePrivacy();
-}
-
-/**
- * Handler function to start the customize toolbar dialog for the event dialog's
- * toolbar.
- */
-function onCommandCustomize() {
-    // install the callback that handles what needs to be
-    // done after a toolbar has been customized.
-    var toolbox = document.getElementById("event-toolbox");
-    toolbox.customizeDone = DialogToolboxCustomizeDone;
-
-    var menubar = document.getElementById("event-menubar");
-    for (var i = 0; i < menubar.childNodes.length; ++i) {
-        menubar.childNodes[i].setAttribute("disabled", true);
-    }
-
-    // Disable the toolbar context menu items
-    document.getElementById("cmd_customize").setAttribute("disabled", "true");
-
-    var id = "event-toolbox";
-    var wintype = document.documentElement.getAttribute("windowtype");
-    wintype = wintype.replace(/:/g, "");
-
-    window.openDialog("chrome://global/content/customizeToolbar.xul",
-                      "CustomizeToolbar" + wintype,
-                      "chrome,all,dependent",
-                      document.getElementById(id), // toolbar dom node
-                      false,                       // is mode toolbar yes/no?
-                      null,                        // callback function
-                      "dialog");                   // name of this mode
 }
 
 /**
  * Prompts the user to change the start timezone.
  */
 function editStartTimezone() {
     editTimezone("timezone-starttime",
                  gStartTime.getInTimezone(gStartTimezone),
@@ -3303,23 +3117,20 @@ function editTimezone(aElementId,aDateTi
  * - 'gStartTime'
  * - 'gEndTime'
  * - 'window.calendarItem' (used to decide about event/task)
  */
 function updateDateTime() {
     gIgnoreUpdate = true;
 
     let item = window.calendarItem;
-    let timezonesEnabled = document.getElementById('cmd_timezone')
-                                   .getAttribute('checked') == 'true';
-
     // Convert to default timezone if the timezone option
     // is *not* checked, otherwise keep the specific timezone
     // and display the labels in order to modify the timezone.
-    if (timezonesEnabled) {
+    if (gTimezonesEnabled) {
         if (isEvent(item)) {
           var startTime = gStartTime.getInTimezone(gStartTimezone);
           var endTime = gEndTime.getInTimezone(gEndTimezone);
 
           setElementValue("event-all-day", startTime.isDate, "checked");
 
           // In the case where the timezones are different but
           // the timezone of the endtime is "UTC", we convert
@@ -3486,59 +3297,100 @@ function updateTimezone() {
                 }
                 element.removeAttribute('disabled');
             }
         } else {
             element.setAttribute('collapsed', 'true');
         }
     }
 
-    let timezonesEnabled = document.getElementById('cmd_timezone')
-                                   .getAttribute('checked') == 'true';
     // convert to default timezone if the timezone option
     // is *not* checked, otherwise keep the specific timezone
     // and display the labels in order to modify the timezone.
-    if (timezonesEnabled) {
+    if (gTimezonesEnabled) {
         updateTimezoneElement(gStartTimezone,
                               'timezone-starttime',
                               gStartTime);
         updateTimezoneElement(gEndTimezone,
                               'timezone-endtime',
                               gEndTime);
     } else {
         document.getElementById('timezone-starttime')
                 .setAttribute('collapsed', 'true');
         document.getElementById('timezone-endtime')
                 .setAttribute('collapsed', 'true');
     }
 }
 
 /**
- * This function updates dialog controls related to item attachments
+ * Updates dialog controls related to item attachments
  */
 function updateAttachment() {
-    var hasAttachments = capSupported("attachments");
+    let hasAttachments = capSupported("attachments");
     setElementValue("cmd_attach_url", !hasAttachments && "true", "disabled");
+    sendMessage({
+        command: "updatePanelState",
+        argument: { attachUrlCommand: hasAttachments }
+    });
 }
 
 /**
- * Toggles the visibility of the related link (rfc2445 URL property)
+ * Updates the related link on the dialog (rfc2445 URL property).  The
+ * argument passed in may be overridden for various reasons.
+ *
+ * @param {boolean} aShowLink  Show the link (true) or not (false)
  */
-function toggleLink() {
-    var linkCommand = document.getElementById("cmd_toggle_link");
-    var row = document.getElementById("event-grid-link-row");
-    var separator = document.getElementById("event-grid-link-separator");
-
-    var isHidden = row.hidden;
-    row.hidden = !isHidden;
-    separator.hidden = !isHidden;
-
-    linkCommand.setAttribute("checked", isHidden ? "true" : "false");
-
-    updateLink();
+function updateItemURL(aShowLink) {
+    /**
+     * Hides or shows the related link.
+     *
+     * @param {boolean} aShow  To show (true) or to hide (false) the link
+     */
+    function hideOrShow(aShow) {
+        setElementValue("event-grid-link-row", !aShow && "true", "hidden");
+        let separator = document.getElementById("event-grid-link-separator");
+        if (separator) {
+            // The separator is not there in the summary dialog
+            setElementValue("event-grid-link-separator", !aShow && "true", "hidden");
+        }
+    }
+    let itemUrlString = window.calendarItem.getProperty("URL") || "";
+    if (!itemUrlString.length) {
+        // Disable if there is no url
+        sendMessage({ command: "disableLinkCommand" });
+    }
+
+    if (aShowLink && itemUrlString.length) {
+        let handler;
+        let uri;
+        try {
+            uri = makeURL(itemUrlString);
+            handler = Services.io.getProtocolHandler(uri.scheme);
+        } catch (e) {
+            // No protocol handler for the given protocol, or invalid uri
+            hideOrShow(false);
+            return;
+        }
+
+        // Only show if its either an internal protcol handler, or its external
+        // and there is an external app for the scheme
+        handler = cal.wrapInstance(handler, Components.interfaces.nsIExternalProtocolHandler);
+        hideOrShow(!handler ||
+                   handler.externalAppExistsForScheme(uri.scheme));
+
+        setTimeout(() => {
+          // HACK the url-link doesn't crop when setting the value in onLoad
+          setElementValue("url-link", itemUrlString);
+          setElementValue("url-link", itemUrlString, "href");
+        }, 0);
+    } else {
+        // Hide if there is no url, or the menuitem was chosen so that the url
+        // should be hidden.
+        hideOrShow(false);
+    }
 }
 
 /**
  * This function updates dialog controls related to attendees.
  */
 function updateAttendees() {
     // sending email invitations currently only supported for events
     let attendeeTab = document.getElementById("event-grid-tab-attendees");
@@ -3764,18 +3616,18 @@ function sendMailToAttendees(aAttendees)
     sendMailTo(toList, emailSubject, null, identity);
 }
 
 /**
  * Make sure all fields that may have calendar specific capabilities are updated
  */
 function updateCapabilities() {
     updateAttachment();
-    updatePriority();
-    updatePrivacy();
+    updatePriority(gConfig.priority);
+    updatePrivacy(gConfig.privacy);
     updateReminderDetails();
     updateCategoryMenulist();
 }
 
 /**
  * find out if the User already changed values in the Dialog
  *
  * @return:    true if the values in the Dialog have changed. False otherwise.
new file mode 100644
--- /dev/null
+++ b/calendar/lightning/content/lightning-item-iframe.xul
@@ -0,0 +1,684 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!-- XXX some of these css files may not be needed here.
+    widget-bindings.css definitely is needed here -->
+<?xml-stylesheet type="text/css" href="chrome://global/skin/global.css"?>
+<?xml-stylesheet type="text/css" href="chrome://calendar-common/skin/calendar-alarms.css"?>
+<?xml-stylesheet type="text/css" href="chrome://calendar-common/skin/calendar-attendees.css"?>
+<?xml-stylesheet type="text/css" href="chrome://calendar/content/widgets/calendar-widget-bindings.css"?>
+<?xml-stylesheet type="text/css" href="chrome://calendar/skin/calendar-event-dialog.css"?>
+<?xml-stylesheet type="text/css" href="chrome://calendar/content/calendar-event-dialog.css"?>
+<?xml-stylesheet type="text/css" href="chrome://calendar/content/datetimepickers/datetimepickers.css"?>
+<?xml-stylesheet type="text/css" href="chrome://messenger/skin/primaryToolbar.css"?>
+<?xml-stylesheet type="text/css" href="chrome://messenger/skin/messenger.css"?>
+
+
+<!DOCTYPE window [
+    <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+    <!ENTITY % globalDTD SYSTEM "chrome://calendar/locale/global.dtd">
+    <!ENTITY % calendarDTD SYSTEM "chrome://calendar/locale/calendar.dtd">
+    <!ENTITY % eventDialogDTD SYSTEM "chrome://calendar/locale/calendar-event-dialog.dtd">
+    %brandDTD;
+    %globalDTD;
+    %calendarDTD;
+    %eventDialogDTD;
+]>
+
+<!-- Vbox id is changed during excution to allow different treatment.
+     document.loadOverlay() will not work on this one. -->
+<window id="calendar-event-dialog-inner"
+      onload="onLoad();"
+      onunload="onEventDialogUnload();"
+      onresize="rearrangeAttendees();"
+      xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <!-- Javascript includes -->
+  <script type="application/javascript"
+          src="chrome://lightning/content/lightning-item-iframe.js"/>
+  <script type="application/javascript"
+          src="chrome://calendar/content/calendar-dialog-utils.js"/>
+  <script type="application/javascript"
+          src="chrome://calendar/content/calendar-ui-utils.js"/>
+  <script type="application/javascript"
+          src="chrome://calendar/content/calUtils.js"/>
+  <script type="application/javascript"
+          src="chrome://calendar/content/calApplicationUtils.js"/>
+  <script type="application/javascript"
+          src="chrome://global/content/globalOverlay.js"/>
+  <script type="application/javascript"
+          src="chrome://global/content/printUtils.js"/>
+  <script type="application/javascript"
+          src="chrome://calendar/content/calendar-statusbar.js"/>
+  <script type="application/javascript"
+          src="chrome://messenger/content/toolbarIconColor.js"/>
+
+  <commandset id="">
+    <command id="cmd_recurrence"
+             oncommand="editRepeat();"/>
+    <command id="cmd_attendees"
+             oncommand="editAttendees();"/>
+    <command id="cmd_email"
+             oncommand="sendMailToAttendees(window.attendees);"/>
+    <command id="cmd_email_undecided"
+             oncommand="sendMailToUndecidedAttendees(window.attendees);"/>
+    <command id="cmd_attach_url"
+             disable-on-readonly="true"
+             oncommand="attachURL()"/>
+    <command id="cmd_attach_cloud"
+             disable-on-readonly="true"/>
+    <command id="cmd_openAttachment"
+             oncommand="openAttachment()"/>
+    <command id="cmd_copyAttachment"
+             oncommand="copyAttachment()"/>
+    <command id="cmd_deleteAttachment"
+             disable-on-readonly="true"
+             oncommand="deleteAttachment()"/>
+    <command id="cmd_deleteAllAttachments"
+             disable-on-readonly="true"
+             oncommand="deleteAllAttachments()"/>
+  </commandset>
+
+  <notificationbox id="event-dialog-notifications" notificationside="top"/>
+
+  <grid id="event-grid"
+        flex="1"
+        style="padding-top: 8px; padding-bottom: 10px; padding-inline-start: 8px; padding-inline-end: 10px;">
+    <columns id="event-grid-columns">
+        <column id="event-description-column"/>
+        <column id="event-controls-column" flex="1"/>
+    </columns>
+
+    <rows id="event-grid-rows">
+      <!-- Title -->
+      <row id="event-grid-title-row"
+           align="center">
+        <label value="&event.title.textbox.label;"
+               accesskey="&event.title.textbox.accesskey;"
+               control="item-title"
+               disable-on-readonly="true"/>
+        <textbox id="item-title"
+                 disable-on-readonly="true"
+                 flex="1"
+                 oninput="updateTitle()"/>
+      </row>
+
+      <!-- Location -->
+      <row id="event-grid-location-row"
+         align="center">
+        <label value="&event.location.label;"
+               accesskey="&event.location.accesskey;"
+               control="item-location"
+               disable-on-readonly="true"/>
+        <textbox id="item-location"
+                 disable-on-readonly="true"/>
+      </row>
+
+      <!-- Category & Calendar -->
+      <row id="event-grid-category-color-row"
+           align="center">
+        <hbox id="event-grid-category-labels-box">
+          <label value="&event.categories.label;"
+                 accesskey="&event.categories.accesskey;"
+                 control="item-categories"
+                 id="item-categories-label"
+                 disable-on-readonly="true"/>
+          <label value="&event.calendar.label;"
+                 accesskey="&event.calendar.accesskey;"
+                 id="item-calendar-aux-label"
+                 control="item-calendar"
+                 disable-on-readonly="true"/>
+        </hbox>
+        <hbox id="event-grid-category-box" align="center">
+          <menulist id="item-categories"
+                    type="panel-menulist"
+                    disable-on-readonly="true"
+                    flex="1">
+            <panel id="item-categories-panel"
+                   type="category-panel"
+                   onpopuphiding="updateCategoryMenulist()"/>
+          </menulist>
+          <label value="&event.calendar.label;"
+                 accesskey="&event.calendar.accesskey;"
+                 control="item-calendar"
+                 id="item-calendar-label"
+                 disable-on-readonly="true"/>
+          <menulist id="item-calendar"
+                    disable-on-readonly="true"
+                    flex="1"
+                    oncommand="updateCalendar();"/>
+        </hbox>
+      </row>
+
+      <separator class="groove" id="event-grid-basic-separator"/>
+
+      <!-- All-Day -->
+      <row id="event-grid-allday-row"
+           align="center">
+        <spacer/>
+        <checkbox id="event-all-day"
+                  class="event-only"
+                  disable-on-readonly="true"
+                  label="&event.alldayevent.label;"
+                  accesskey="&event.alldayevent.accesskey;"
+                  oncommand="onUpdateAllDay();"/>
+      </row>
+
+      <!-- StartDate -->
+      <row id="event-grid-startdate-row">
+        <hbox id="event-grid-startdate-label-box"
+              align="center">
+          <label value="&event.from.label;"
+                 accesskey="&event.from.accesskey;"
+                 control="event-starttime"
+                 class="event-only"
+                 disable-on-readonly="true"/>
+          <label value="&task.from.label;"
+                 accesskey="&task.from.accesskey;"
+                 control="todo-has-entrydate"
+                 class="todo-only"
+                 disable-on-readonly="true"/>
+        </hbox>
+        <hbox id="event-grid-startdate-picker-box">
+          <datetimepicker id="event-starttime"
+                          class="event-only"
+                          disable-on-readonly="true"
+                          onchange="dateTimeControls2State(true);"/>
+          <checkbox id="todo-has-entrydate"
+                    class="todo-only checkbox-no-label"
+                    disable-on-readonly="true"
+                    oncommand="updateEntryDate();"/>
+          <datetimepicker id="todo-entrydate"
+                          class="todo-only"
+                          disable-on-readonly="true"
+                          onchange="dateTimeControls2State(true);"/>
+          <vbox>
+            <hbox>
+              <image id="link-image-top" class="keepduration-link-image" keep="true"/>
+            </hbox>
+            <spacer flex="1"/>
+            <toolbarbutton id="keepduration-button"
+                           accesskey="&event.dialog.keepDurationButton.accesskey;"
+                           oncommand="toggleKeepDuration();"
+                           persist="keep"
+                           keep="false"
+                           tooltiptext="&event.dialog.keepDurationButton.tooltip;"/>
+          </vbox>
+          <hbox align="center">
+            <label id="timezone-starttime"
+                   class="text-link"
+                   collapsed="true"
+                   crop="end"
+                   disable-on-readonly="true"
+                   flex="1"
+                   hyperlink="true"
+                   onclick="showTimezonePopup(event, gStartTime.getInTimezone(gStartTimezone), editStartTimezone)"/>
+          </hbox>
+        </hbox>
+      </row>
+
+      <!-- EndDate -->
+      <row id="event-grid-enddate-row">
+        <hbox id="event-grid-enddate-label-box"
+              align="center">
+          <label value="&event.to.label;"
+                 accesskey="&event.to.accesskey;"
+                 control="event-endtime"
+                 class="event-only"
+                 disable-on-readonly="true"/>
+          <label value="&task.to.label;"
+                 accesskey="&task.to.accesskey;"
+                 control="todo-has-duedate"
+                 class="todo-only"
+                 disable-on-readonly="true"/>
+        </hbox>
+        <vbox>
+          <hbox id="event-grid-enddate-picker-box">
+            <datetimepicker id="event-endtime"
+                            class="event-only"
+                            disable-on-readonly="true"
+                            onchange="dateTimeControls2State(false);"/>
+            <checkbox id="todo-has-duedate"
+                      class="todo-only checkbox-no-label"
+                      disable-on-readonly="true"
+                      oncommand="updateDueDate();"/>
+            <datetimepicker id="todo-duedate"
+                            class="todo-only"
+                            disable-on-readonly="true"
+                            onchange="dateTimeControls2State(false);"/>
+            <vbox pack="end">
+              <image id="link-image-bottom" class="keepduration-link-image"/>
+            </vbox>
+            <hbox align="center">
+              <label id="timezone-endtime"
+                     class="text-link"
+                     collapsed="true"
+                     crop="end"
+                     disable-on-readonly="true"
+                     flex="1"
+                     hyperlink="true"
+                     onclick="showTimezonePopup(event, gEndTime.getInTimezone(gEndTimezone), editEndTimezone)"/>
+            </hbox>
+          </hbox>
+        </vbox>
+      </row>
+
+      <row id="event-grid-todo-status-row"
+           class="todo-only"
+           align="center">
+        <label id="todo-status-label"
+               value="&task.status.label;"
+               accesskey="&task.status.accesskey;"
+               control="todo-status"
+               disable-on-readonly="true"/>
+        <hbox id="event-grid-todo-status-picker-box"
+              align="center">
+          <menulist id="todo-status"
+                    class="todo-only"
+                    disable-on-readonly="true"
+                    oncommand="updateToDoStatus(this.value);">
+            <menupopup id="todo-status-menupopup">
+              <menuitem id="todo-status-none-menuitem"
+                        label="&newevent.todoStatus.none.label;"
+                        value="NONE"/>
+              <menuitem id="todo-status-needsaction-menuitem"
+                        label="&newevent.status.needsaction.label;"
+                        value="NEEDS-ACTION"/>
+              <menuitem id="todo-status-inprogress-menuitem"
+                        label="&newevent.status.inprogress.label;"
+                        value="IN-PROCESS"/>
+              <menuitem id="todo-status-completed-menuitem"
+                        label="&newevent.status.completed.label;"
+                        value="COMPLETED"/>
+              <menuitem id="todo-status-canceled-menuitem"
+                        label="&newevent.todoStatus.cancelled.label;"
+                        value="CANCELLED"/>
+            </menupopup>
+          </menulist>
+            <datepicker id="completed-date-picker"
+                        class="todo-only"
+                        disable-on-readonly="true"
+                        disabled="true"
+                        value=""/>
+            <textbox id="percent-complete-textbox"
+                     type="number"
+                     min="0"
+                     max="100"
+                     disable-on-readonly="true"
+                     size="3"
+                     oninput="updateToDoStatus('percent-changed')"
+                     onselect="updateToDoStatus('percent-changed')"/>
+            <label id="percent-complete-label"
+                   class="todo-only"
+                   disable-on-readonly="true"
+                   value="&newtodo.percentcomplete.label;"/>
+        </hbox>
+      </row>
+
+      <separator id="event-grid-recurrence-separator" class="groove"/>
+
+      <!-- Recurrence -->
+      <row id="event-grid-recurrence-row"
+           align="center">
+        <label value="&event.repeat.label;"
+               accesskey="&event.repeat.accesskey;"
+               control="item-repeat"
+               disable-on-readonly="true"/>
+        <hbox id="event-grid-recurrence-picker-box"
+              align="center"
+              flex="1">
+          <menulist id="item-repeat"
+                    disable-on-readonly="true"
+                    oncommand="updateRepeat(null, true)">
+            <menupopup id="item-repeat-menupopup">
+              <menuitem id="repeat-none-menuitem"
+                        label="&event.repeat.does.not.repeat.label;"
+                        selected="true"
+                        value="none"/>
+              <menuitem id="repeat-daily-menuitem"
+                        label="&event.repeat.daily.label;"
+                        value="daily"/>
+              <menuitem id="repeat-weekly-menuitem"
+                        label="&event.repeat.weekly.label;"
+                        value="weekly"/>
+              <menuitem id="repeat-weekday-menuitem"
+                        label="&event.repeat.every.weekday.label;"
+                        value="every.weekday"/>
+              <menuitem id="repeat-biweekly-menuitem"
+                        label="&event.repeat.bi.weekly.label;"
+                        value="bi.weekly"/>
+              <menuitem id="repeat-monthly-menuitem"
+                        label="&event.repeat.monthly.label;"
+                        value="monthly"/>
+              <menuitem id="repeat-yearly-menuitem"
+                        label="&event.repeat.yearly.label;"
+                        value="yearly"/>
+              <menuseparator id="item-repeat-separator"/>
+              <menuitem id="repeat-custom-menuitem"
+                        label="&event.repeat.custom.label;"
+                        value="custom"/>
+            </menupopup>
+          </menulist>
+          <deck id="repeat-deck" selectedIndex="-1">
+            <hbox id="repeat-untilDate" align="center">
+                <label value="&event.until.label;"
+                       accesskey="&event.until.accesskey;"
+                       control="repeat-until-datepicker"
+                       disable-on-readonly="true"/>
+                <datepicker-forever id="repeat-until-datepicker" flex="1"
+                                    disable-on-readonly="true"
+                                    onchange="checkUntilDate();"
+                                    oncommand="checkUntilDate();"
+                                    value=""/>
+            </hbox>
+            <vbox id="repeat-details" flex="1">
+                <label class="text-link"
+                       crop="right"
+                       disable-on-readonly="true"
+                       hyperlink="true"
+                       flex="1"
+                       onclick="updateRepeat()"/>
+            </vbox>
+          </deck>
+        </hbox>
+      </row>
+
+      <separator id="event-grid-alarm-separator"
+                 class="groove"/>
+
+      <!-- Reminder (Alarm) -->
+      <row id="event-grid-alarm-row"
+           align="center">
+        <label value="&event.reminder.label;"
+               accesskey="&event.reminder.accesskey;"
+               control="item-alarm"
+               disable-on-readonly="true"/>
+        <hbox id="event-grid-alarm-picker-box"
+              align="center">
+          <menulist id="item-alarm"
+                    disable-on-readonly="true"
+                    oncommand="updateReminder()">
+            <menupopup id="item-alarm-menupopup">
+              <menuitem id="reminder-none-menuitem"
+                        label="&event.reminder.none.label;"
+                        selected="true"
+                        value="none"/>
+              <menuseparator id="reminder-none-separator"/>
+              <menuitem id="reminder-0minutes-menuitem"
+                        label="&event.reminder.0minutes.before.label;"
+                        length="0"
+                        origin="before"
+                        relation="START"
+                        unit="minutes"/>
+              <menuitem id="reminder-5minutes-menuitem"
+                        label="&event.reminder.5minutes.before.label;"
+                        length="5"
+                        origin="before"
+                        relation="START"
+                        unit="minutes"/>
+              <menuitem id="reminder-15minutes-menuitem"
+                        label="&event.reminder.15minutes.before.label;"
+                        length="15"
+                        origin="before"
+                        relation="START"
+                        unit="minutes"/>
+              <menuitem id="reminder-30minutes-menuitem"
+                        label="&event.reminder.30minutes.before.label;"
+                        length="30"
+                        origin="before"
+                        relation="START"
+                        unit="minutes"/>
+              <menuseparator id="reminder-minutes-separator"/>
+              <menuitem id="reminder-1hour-menuitem"
+                        label="&event.reminder.1hour.before.label;"
+                        length="1"
+                        origin="before"
+                        relation="START"
+                        unit="hours"/>
+              <menuitem id="reminder-2hours-menuitem"
+                        label="&event.reminder.2hours.before.label;"
+                        length="2"
+                        origin="before"
+                        relation="START"
+                        unit="hours"/>
+              <menuitem id="reminder-12hours-menuitem"
+                        label="&event.reminder.12hours.before.label;"
+                        length="12"
+                        origin="before"
+                        relation="START"
+                        unit="hours"/>
+              <menuseparator id="reminder-hours-separator"/>
+              <menuitem id="reminder-1day-menuitem"
+                        label="&event.reminder.1day.before.label;"
+                        length="1"
+                        origin="before"
+                        relation="START"
+                        unit="days"/>
+              <menuitem id="reminder-2days-menuitem"
+                        label="&event.reminder.2days.before.label;"
+                        length="2"
+                        origin="before"
+                        relation="START"
+                        unit="days"/>
+              <menuitem id="reminder-1week-menuitem"
+                        label="&event.reminder.1week.before.label;"
+                        length="7"
+                        origin="before"
+                        relation="START"
+                        unit="days"/>
+              <menuseparator id="reminder-custom-separator"/>
+              <menuitem id="reminder-custom-menuitem"
+                        label="&event.reminder.custom.label;"
+                        value="custom"/>
+            </menupopup>
+          </menulist>
+          <hbox id="reminder-details">
+            <hbox id="reminder-icon-box"
+                  class="alarm-icons-box"
+                  align="center"/>
+            <!-- TODO oncommand? onkeypress? -->
+            <label id="reminder-multiple-alarms-label"
+                   hidden="true"
+                   value="&event.reminder.multiple.label;"
+                   class="text-link"
+                   disable-on-readonly="true"
+                   flex="1"
+                   hyperlink="true"
+                   onclick="updateReminder()"/>
+            <label id="reminder-single-alarms-label"
+                   hidden="true"
+                   class="text-link"
+                   disable-on-readonly="true"
+                   flex="1"
+                   hyperlink="true"
+                   onclick="updateReminder()"/>
+          </hbox>
+        </hbox>
+      </row>
+
+      <separator id="event-grid-tabbox-separator"
+                 class="groove"/>
+
+      <!-- Multi purpose tab box -->
+      <tabbox id="event-grid-tabbox"
+              selectedIndex="0"
+              flex="1">
+        <tabs id="event-grid-tabs">
+          <tab id="event-grid-tab-description"
+               label="&event.description.label;"
+               accesskey="&event.description.accesskey;"/>
+          <tab id="event-grid-tab-attachments"
+               label="&event.attachments.label;"
+                accesskey="&event.attachments.accesskey;"/>
+          <tab id="event-grid-tab-attendees"
+               label="&event.attendees.label;"
+               accesskey="&event.attendees.accesskey;"
+               collapsed="true"/>
+        </tabs>
+        <tabpanels id="event-grid-tabpanels"
+                   flex="1">
+          <tabpanel id="event-grid-tabpanel-description">
+            <textbox id="item-description"
+                     disable-on-readonly="true"
+                     flex="1"
+                     multiline="true"
+                     rows="12"/>
+          </tabpanel>
+          <tabpanel id="event-grid-tabpanel-attachements">
+            <vbox flex="1">
+              <listbox id="attachment-link"
+                       context="attachment-popup"
+                       rows="3"
+                       flex="1"
+                       disable-on-readonly="true"
+                       onkeypress="attachmentLinkKeyPress(event)"
+                       onclick="attachmentClick(event);"
+                       ondblclick="attachmentDblClick(event);"/>
+            </vbox>
+          </tabpanel>
+          <tabpanel id="event-grid-tabpanel-attendees"
+                    collapsed="true">
+            <vbox flex="1">
+              <hbox id="item-organizer-row"
+                    collapsed="true"
+                    align="top"
+                    class="item-attendees-row">
+                <label value="&read.only.organizer.label;"/>
+                <hbox class="item-organizer-cell">
+                  <img class="itip-icon"/>
+                  <label id="item-organizer"
+                         class="item-attendees-cell-label"
+                         crop="right"/>
+                </hbox>
+              </hbox>
+              <hbox flex="1">
+                <vbox id="item-attendees-box"
+                      dialog-type="event"
+                      flex="1"
+                      context="attendee-popup"
+                      onclick="attendeeClick(event)"
+                      disable-on-readonly="true"/>
+              </hbox>
+              <hbox id="notify-options" align="center">
+                <checkbox id="notify-attendees-checkbox"
+                          label="&event.attendees.notify.label;"
+                          accesskey="&event.attendees.notify.accesskey;"
+                          oncommand="changeUndiscloseCheckboxStatus();"
+                          pack="start"/>
+                <checkbox id="undisclose-attendees-checkbox"
+                          label="&event.attendees.notifyundisclosed.label;"
+                          accesskey="&event.attendees.notifyundisclosed.accesskey;"
+                          tooltiptext="&event.attendees.notifyundisclosed.tooltip;"
+                          pack="start"/>
+              </hbox>
+            </vbox>
+          </tabpanel>
+        </tabpanels>
+      </tabbox>
+
+      <separator id="event-grid-link-separator"
+                 class="groove"
+                 hidden="true"/>
+      <row id="event-grid-link-row"
+           align="center"
+           hidden="true">
+        <label value="&event.url.label;"
+               control="url-link"/>
+        <label id="url-link"
+               onclick="launchBrowser(this.getAttribute('href'), event)"
+               oncommand="launchBrowser(this.getAttribute('href'), event)"
+               class="text-link"
+               crop="end"/>
+      </row>
+    </rows>
+  </grid>
+
+
+  <popupset id="event-dialog-popupset">
+    <menupopup id="attendee-popup">
+      <menuitem id="attendee-popup-invite-menuitem"
+                label="&event.invite.attendees.label;"
+                accesskey="&event.invite.attendees.accesskey;"
+                command="cmd_attendees"
+                disable-on-readonly="true"/>
+      <menuitem id="attendee-popup-removeallattendees-menuitem"
+                label="&event.remove.attendees.label2;"
+                accesskey="&event.remove.attendees.accesskey;"
+                oncommand="removeAllAttendees()"
+                disable-on-readonly="true"
+                crop="end"/>
+      <menuitem id="attendee-popup-removeattendee-menuitem"
+                label="&event.remove.attendee.label;"
+                accesskey="&event.remove.attendee.accesskey;"
+                oncommand="removeAttendee(event.target.attendee)"
+                crop="end"/>
+      <menuseparator id="attendee-popup-first-separator"/>
+      <menuitem id="attendee-popup-sendemail-menuitem"
+                label="&event.email.attendees.label;"
+                accesskey="&event.email.attendees.accesskey;"
+                command="cmd_email"/>
+      <menuitem id="attendee-popup-sendtentativeemail-menuitem"
+                label="&event.email.tentative.attendees.label;"
+                accesskey="&event.email.tentative.attendees.accesskey;"
+                command="cmd_email_undecided"/>
+      <menuseparator id="attendee-popup-second-separator"/>
+      <menuitem id="attendee-popup-emailattendee-menuitem"
+                oncommand="sendMailToAttendees([event.target.attendee])"
+                crop="end"/>
+    </menupopup>
+    <menupopup id="attachment-popup">
+      <menuitem id="attachment-popup-open"
+                label="&event.attachments.popup.open.label;"
+                accesskey="&event.attachments.popup.open.accesskey;"
+                command="cmd_openAttachment"/>
+      <menuitem id="attachment-popup-copy"
+                label="&calendar.copylink.label;"
+                accesskey="&calendar.copylink.accesskey;"
+                command="cmd_copyAttachment"/>
+      <menuitem id="attachment-popup-delete"
+                label="&event.attachments.popup.remove.label;"
+                accesskey="&event.attachments.popup.remove.accesskey;"
+                command="cmd_deleteAttachment"/>
+      <menuitem id="attachment-popup-deleteAll"
+                label="&event.attachments.popup.removeAll.label;"
+                accesskey="&event.attachments.popup.removeAll.accesskey;"
+                command="cmd_deleteAllAttachments"/>
+      <menuseparator/>
+      <menuitem id="attachment-popup-attachPage"
+                label="&event.attachments.popup.attachPage.label;"
+                accesskey="&event.attachments.popup.attachPage.accesskey;"
+                command="cmd_attach_url"/>
+    </menupopup>
+    <menupopup id="timezone-popup"
+               position="after_start"
+               oncommand="chooseRecentTimezone(event)">
+      <menuitem id="timezone-popup-defaulttz"/>
+      <menuseparator id="timezone-popup-menuseparator"/>
+      <menuitem id="timezone-custom-menuitem"
+                label="&event.timezone.custom.label;"
+                value="custom"
+                oncommand="this.parentNode.editTimezone()"/>
+    </menupopup>
+  </popupset>
+
+  <!-- attendee box template -->
+  <vbox id="item-attendees-box-template"
+        hidden="true">
+    <hbox flex="1" class="item-attendees-row" equalsize="always" hidden="true">
+      <box class="item-attendees-cell"
+           hidden="true"
+           flex="1"
+           context="attendee-popup"
+           ondblclick="attendeeDblClick(event)"
+           onclick="attendeeClick(event)">
+        <img class="itip-icon"/>
+        <label class="item-attendees-cell-label"
+               crop="end"
+               flex="1"/>
+      </box>
+      <box hidden="true" flex="1"/>
+    </hbox>
+  </vbox>
+</window>
new file mode 100644
--- /dev/null
+++ b/calendar/lightning/content/lightning-item-panel.js
@@ -0,0 +1,851 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// XXX Need to determine which of these we really need here.
+Components.utils.import("resource://calendar/modules/calUtils.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://calendar/modules/calRecurrenceUtils.jsm");
+Components.utils.import("resource:///modules/mailServices.js");
+Components.utils.import("resource://gre/modules/PluralForm.jsm");
+Components.utils.import("resource://gre/modules/Preferences.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+try {
+    Components.utils.import("resource:///modules/cloudFileAccounts.js");
+} catch (e) {
+    // This will fail on Seamonkey, but thats ok since the pref for cloudfiles
+    // is false, which means the UI will not be shown
+}
+
+// gTabmail is null if we are in a dialog window and not in a tab.
+var gTabmail = document.getElementById("tabmail") || null;
+
+if (!gTabmail) {
+    // In a dialog window the following menu item functions need to be
+    // defined.  In a tab they are defined elsewhere.  To prevent errors in
+    // the log they are defined here (before the onLoad function is called).
+    /**
+     * Update menu items that rely on focus.
+     */
+    window.goUpdateGlobalEditMenuItems = () => {
+        goUpdateCommand("cmd_undo");
+        goUpdateCommand("cmd_redo");
+        goUpdateCommand("cmd_cut");
+        goUpdateCommand("cmd_copy");
+        goUpdateCommand("cmd_paste");
+        goUpdateCommand("cmd_selectAll");
+    }
+    /**
+     * Update menu items that rely on the current selection.
+     */
+    window.goUpdateSelectEditMenuItems = () => {
+        goUpdateCommand("cmd_cut");
+        goUpdateCommand("cmd_copy");
+        goUpdateCommand("cmd_delete");
+        goUpdateCommand("cmd_selectAll");
+    }
+    /**
+     * Update menu items that relate to undo/redo.
+     */
+    window.goUpdateUndoEditMenuItems = () => {
+        goUpdateCommand("cmd_undo");
+        goUpdateCommand("cmd_redo");
+    }
+    /**
+     * Update menu items that depend on clipboard contents.
+     */
+    window.goUpdatePasteMenuItems = () => {
+        goUpdateCommand("cmd_paste");
+    }
+}
+
+// Stores the ids of the iframes of currently open event/task tabs, used
+// when window is closed to prompt for saving changes.
+var gItemTabIds = [];
+var gItemTabIdsCopy;
+
+// gConfig is used when switching tabs to restore the state of
+// toolbar, statusbar, and menubar for the current tab.
+var gConfig = {
+    privacy: null,
+    hasPrivacy: null,
+    calendarType: null,
+    privacyValues: null,
+    priority: null,
+    hasPriority: null,
+    status: null,
+    showTimeAs: null,
+    // whether cmd_attendees is enabled or disabled
+    attendeesCommand: null,
+    attachUrlCommand: null,
+    timezonesEnabled: false
+}
+
+/**
+ * Receive an asynchronous message from the iframe.
+ *
+ * @param {MessageEvent} aEvent  Contains the message being received
+ */
+function receiveMessage(aEvent) {
+    if (aEvent.origin !== "chrome://lightning") {
+        return;
+    }
+    switch (aEvent.data.command) {
+        case "onLoad":
+            onLoad();
+            break;
+        case "initializeItemMenu":
+            initializeItemMenu(aEvent.data.label, aEvent.data.accessKey);
+            break;
+        case "disableLinkCommand":
+            let linkCommand = document.getElementById("cmd_toggle_link");
+            if (linkCommand) {
+                setElementValue(linkCommand, "true", "disabled");
+            }
+            break;
+        case "cancelDialog":
+            document.documentElement.cancelDialog();
+            break;
+        case "closeWindowOrTab":
+            closeWindowOrTab(aEvent.data.iframeId);
+            break;
+        case "showCmdStatusNone":
+            document.getElementById("cmd_status_none").removeAttribute("hidden");
+            break;
+        case "updateTitle":
+            updateTitle(aEvent.data.argument);
+            break;
+        case "updatePanelState":
+            updateItemTabState(aEvent.data.argument);
+            Object.assign(gConfig, aEvent.data.argument);
+            break;
+        case "enableAcceptCommand":
+            enableAcceptCommand(aEvent.data.argument);
+            break;
+        case "replyToClosingWindowWithTabs":
+            handleWindowClose(aEvent.data.response);
+            break;
+        case "removeDisableAndCollapseOnReadonly":
+            removeDisableAndCollapseOnReadonly();
+            break;
+    }
+}
+
+window.addEventListener("message", receiveMessage, false);
+
+/**
+ * Send an asynchronous message to an iframe.  Additional properties of
+ * aMessage are generally arguments that will be passed to the function
+ * named in aMessage.command.  If aIframeId is omitted, the message will
+ * be sent to the iframe of the current tab.
+ *
+ * @param {Object} aMessage          Contains the message being sent
+ * @param {string} aMessage.command  The name of a function to call
+ * @param {string} aIframeId         (optional) id of an iframe to send the message to
+ */
+function sendMessage(aMessage, aIframeId) {
+    let iframeId;
+    if (gTabmail) {
+        if (aIframeId) {
+            iframeId = aIframeId;
+        } else {
+            iframeId = gTabmail.currentTabInfo.iframe.id;
+        }
+    } else {
+        iframeId = "lightning-item-panel-iframe";
+    }
+    let iframe = document.getElementById(iframeId);
+    iframe.contentWindow.postMessage(aMessage, "*");
+}
+
+/**
+ * When the user closes the window, this function handles prompting them
+ * to save any unsaved changes for any open item tabs, before closing the
+ * window, or not if 'cancel' was clicked.  Requires sending and receiving
+ * async messages from the iframes of all open item tabs.
+ *
+ * @param {boolean} aResponse  The response from the tab's iframe
+ */
+function handleWindowClose(aResponse) {
+    if (!aResponse) {
+        // Cancel was clicked, just leave the window open. We're done.
+        return;
+    } else if (gItemTabIdsCopy.length > 0) {
+        // There are more unsaved changes in tabs to prompt the user about.
+        let nextId = gItemTabIdsCopy.shift();
+        sendMessage({ command: "closingWindowWithTabs", id: nextId }, nextId);
+    } else {
+        // Close the window, there are no more unsaved changes in tabs.
+        window.removeEventListener("close", windowCloseListener, false);
+        window.close();
+    }
+}
+
+/**
+ * Listener function for window close.  We prevent the window from
+ * closing, then for each open tab we prompt the user to save any
+ * unsaved changes with handleWindowClose.
+ *
+ * @param {Object} aEvent  The window close event
+ */
+function windowCloseListener(aEvent) {
+    aEvent.preventDefault();
+    gItemTabIdsCopy = gItemTabIds.slice();
+    handleWindowClose(true);
+}
+
+/**
+ * Load handler for the outer parent context that contains the iframe.
+ */
+function onLoad() {
+    gConfig.timezonesEnabled = getTimezoneCommandState();
+
+    if (!gTabmail) {
+        gTabmail = document.getElementById("tabmail") || null;
+    }
+    if (gTabmail) {
+        // tab case
+        // Add a listener to detect close events, prompt user about saving changes.
+        window.addEventListener("close", windowCloseListener, false);
+    } else {
+        // window case
+        // hide the ok and cancel dialog buttons
+        document.documentElement.getButton("accept")
+                .setAttribute("collapsed", "true");
+        document.documentElement.getButton("cancel")
+                .setAttribute("collapsed", "true");
+        document.documentElement.getButton("cancel")
+                .parentNode.setAttribute("collapsed", "true");
+
+        // set the dialog-id for task vs event CSS selection, etc.
+        if (!cal.isEvent(window.arguments[0].calendarEvent)) {
+            setDialogId(document.documentElement, "calendar-task-dialog");
+        }
+    }
+}
+
+/**
+ * Updates the UI.  Called when a user makes a change and when an
+ * event/task tab is shown.  When a tab is shown aArg contains the gConfig
+ * data for that event/task.  We pass the full tab state object to the
+ * update functions and they just use the properties they need from it.
+ *
+ * @param {Object} aArg  Its properties hold data about the event/task
+ */
+function updateItemTabState(aArg) {
+    const lookup = {
+        privacy: updatePrivacy,
+        priority: updatePriority,
+        status: updateStatus,
+        showTimeAs: updateShowTimeAs,
+        attendeesCommand: updateAttendeesCommand,
+        attachUrlCommand: updateAttachment,
+        timezonesEnabled: updateTimezoneCommand
+    };
+    for (let key of Object.keys(aArg)) {
+        if (lookup[key]) {
+            lookup[key](aArg);
+        }
+    }
+}
+
+/**
+ * When in a window, set Item-Menu label to Event or Task.
+ *
+ * @param {string} aLabel      The new name for the menu
+ * @param {string} aAccessKey  The access key for the menu
+ */
+function initializeItemMenu (aLabel, aAccessKey) {
+    let menuItem = document.getElementById("item-menu");
+    menuItem.setAttribute("label", aLabel);
+    menuItem.setAttribute("accesskey", aAccessKey);
+}
+
+/**
+ * Handler for when dialog is accepted.
+ */
+function onAccept() {
+    sendMessage({ command: "onAccept" });
+    return false;
+}
+
+/**
+ * Handler for when dialog is canceled.
+ *
+ * @param {string} aIframeId  The id of the iframe
+ */
+function onCancel(aIframeId) {
+    sendMessage({ command: "onCancel", iframeId: aIframeId }, aIframeId);
+    // We return false to prevent closing of a window until we
+    // can ask the user about saving any unsaved changes.
+    return false;
+}
+
+/**
+ * Closes tab or window. Called after prompting to save any unsaved changes.
+ *
+ * @param {string} aIframeId  The id of the iframe
+ */
+function closeWindowOrTab(iframeId) {
+    if (gTabmail) {
+        if (iframeId) {
+            // Find the tab associated with this iframeId, and close it.
+            let myTabInfo = gTabmail.tabInfo.filter((x) => "iframe" in x && x.iframe.id == iframeId)[0];
+            myTabInfo.allowTabClose = true;
+            gTabmail.closeTab(myTabInfo);
+        } else {
+            gTabmail.currentTabInfo.allowTabClose = true;
+            gTabmail.removeCurrentTab();
+        }
+    } else {
+        window.close();
+    }
+}
+
+/**
+ * Handler for saving the event or task.
+ *
+ * @param {boolean} aIsClosing  Is the tab or window closing
+ */
+function onCommandSave(aIsClosing) {
+    sendMessage({ command:"onCommandSave", isClosing: aIsClosing });
+}
+
+/**
+ * Handler for deleting the event or task.
+ */
+function onCommandDeleteItem() {
+    sendMessage({ command:"onCommandDeleteItem" });
+}
+
+/**
+ * Update the title of the tab or window.
+ *
+ * @param {string} aNewTitle  The new title
+ */
+function updateTitle(aNewTitle) {
+    if (gTabmail) {
+        gTabmail.currentTabInfo.title = aNewTitle;
+        gTabmail.setTabTitle(gTabmail.currentTabInfo);
+    } else {
+        document.title = aNewTitle;
+    }
+}
+
+/**
+ * Handler for edit attendees command.
+ */
+function editAttendees() {
+    sendMessage({ command: "editAttendees" });
+}
+
+/**
+ * Handler for rotate privacy command.
+ */
+function rotatePrivacy() {
+    sendMessage({ command: "rotatePrivacy" });
+}
+
+/**
+ * Sets the privacy of an item to the value specified by
+ * the attribute "privacy" of the UI-element aTarget.
+ * aEvent is used for the popup menu event-privacy-menupopup
+ * in the Privacy toolbar button.
+ *
+ * @param aTarget  The calling UI-element
+ * @param aEvent   The UI-element selection event
+ */
+function editPrivacy(aTarget, aEvent) {
+    if (aEvent) {
+        aEvent.stopPropagation();
+    }
+    sendMessage({
+        command: "editPrivacy",
+        value: aTarget.getAttribute("privacy")
+    });
+}
+
+/**
+ * Updates the UI according to the privacy setting and the selected
+ * calendar. If the selected calendar does not support privacy or only
+ * certain values, these are removed from the UI. This function should
+ * be called any time that privacy setting is updated.
+ *
+ * @param {Object}    aArg                Contains privacy properties
+ * @param {string}    aArg.privacy        The new privacy value
+ * @param {boolean}   aArg.hasPrivacy     Whether privacy is supported
+ * @param {string}    aArg.calendarType   The type of calendar
+ * @param {string[]}  aArg.privacyValues  The possible privacy values
+ */
+function updatePrivacy(aArg) {
+    if (aArg.hasPrivacy) {
+        let numChilds;
+
+        // Update privacy capabilities (toolbar)
+        let menupopup = document.getElementById("event-privacy-menupopup");
+        if (menupopup) {
+            // Only update the toolbar if the button is actually there
+            for (let node of menupopup.childNodes) {
+                let currentProvider = node.getAttribute("provider");
+                if (node.hasAttribute("privacy")) {
+                    let currentPrivacyValue = node.getAttribute("privacy");
+                    // Collapsed state
+
+                    // Hide the toolbar if the value is unsupported or is for a
+                    // specific provider and doesn't belong to the current provider.
+                    if (!aArg.privacyValues.includes(currentPrivacyValue) ||
+                        (currentProvider && currentProvider != aArg.calendarType)) {
+                        node.setAttribute("collapsed", "true");
+                    } else {
+                        node.removeAttribute("collapsed");
+                    }
+
+                    // Checked state
+                    if (aArg.privacy == currentPrivacyValue) {
+                        node.setAttribute("checked", "true");
+                    } else {
+                        node.removeAttribute("checked");
+                    }
+                }
+            }
+        }
+
+        // Update privacy capabilities (menu) but only if we are not in a tab.
+        if (!gTabmail) {
+            menupopup = document.getElementById("options-privacy-menupopup");
+            for (let node of menupopup.childNodes) {
+                let currentProvider = node.getAttribute("provider");
+                if (node.hasAttribute("privacy")) {
+                    let currentPrivacyValue = node.getAttribute("privacy");
+                    // Collapsed state
+
+                    // Hide the menu if the value is unsupported or is for a
+                    // specific provider and doesn't belong to the current provider.
+                    if (!aArg.privacyValues.includes(currentPrivacyValue) ||
+                        (currentProvider && currentProvider != aArg.calendarType)) {
+                        node.setAttribute("collapsed", "true");
+                    } else {
+                        node.removeAttribute("collapsed");
+                    }
+
+                    // Checked state
+                    if (aArg.privacy == currentPrivacyValue) {
+                        node.setAttribute("checked", "true");
+                    } else {
+                        node.removeAttribute("checked");
+                    }
+                }
+            }
+        }
+
+        // Update privacy capabilities (statusbar)
+        let privacyPanel = document.getElementById("status-privacy");
+        let hasAnyPrivacyValue = false;
+        for (let node of privacyPanel.childNodes) {
+            let currentProvider = node.getAttribute("provider");
+            if (node.hasAttribute("privacy")) {
+                let currentPrivacyValue = node.getAttribute("privacy");
+
+                // Hide the panel if the value is unsupported or is for a
+                // specific provider and doesn't belong to the current provider,
+                // or is not the items privacy value
+                if (!aArg.privacyValues.includes(currentPrivacyValue) ||
+                    (currentProvider && currentProvider != aArg.calendarType) ||
+                    aArg.privacy != currentPrivacyValue) {
+                    node.setAttribute("collapsed", "true");
+                } else {
+                    node.removeAttribute("collapsed");
+                    hasAnyPrivacyValue = true;
+                }
+            }
+        }
+
+        // Don't show the status panel if no valid privacy value is selected
+        if (!hasAnyPrivacyValue) {
+            privacyPanel.setAttribute("collapsed", "true");
+        } else {
+            privacyPanel.removeAttribute("collapsed");
+        }
+    } else {
+        // aArg.hasPrivacy is false
+        setElementValue("button-privacy", "true", "disabled");
+        setElementValue("status-privacy", "true", "collapsed");
+        // in the tab case the menu item does not exist
+        let privacyMenuItem = document.getElementById("options-privacy-menu");
+        if (privacyMenuItem) {
+            setElementValue("options-privacy-menu", "true", "disabled");
+        }
+    }
+}
+
+/**
+ * Handler for rotate priority command.
+ */
+function rotatePriority() {
+    sendMessage({ command: "rotatePriority" });
+}
+
+/**
+ * Handler to change the priority.
+ *
+ * @param {nsIDOMNode} aTarget  Its value attribute contains the new priority
+ */
+function editPriority(aTarget) {
+    sendMessage({
+        command: "editPriority",
+        value: parseInt(aTarget.getAttribute("value"))
+    });
+}
+
+/**
+ * Updates the dialog controls related to priority.
+ *
+ * @param {Object}  aArg              Contains priority properties
+ * @param {string}  aArg.priority     The new priority value
+ * @param {boolean} aArg.hasPriority  Whether priority is supported
+ */
+function updatePriority(aArg) {
+    // Set up capabilities
+    if (document.getElementById("button-priority")) {
+        setElementValue("button-priority", !aArg.hasPriority && "true", "disabled");
+    }
+    if (!gTabmail && document.getElementById("options-priority-menu")) {
+        setElementValue("options-priority-menu", !aArg.hasPriority && "true", "disabled");
+    }
+    setElementValue("status-priority", !aArg.hasPriority && "true", "collapsed");
+
+    if (aArg.hasPriority) {
+        let priorityLevel = "none";
+        if (aArg.priority >= 1 && aArg.priority <= 4) {
+            priorityLevel = "high";
+        } else if (aArg.priority == 5) {
+            priorityLevel = "normal";
+        } else if (aArg.priority >= 6 && aArg.priority <= 9) {
+            priorityLevel = "low";
+        }
+
+        let priorityNone = document.getElementById("cmd_priority_none");
+        let priorityLow = document.getElementById("cmd_priority_low");
+        let priorityNormal = document.getElementById("cmd_priority_normal");
+        let priorityHigh = document.getElementById("cmd_priority_high");
+
+        priorityNone.setAttribute("checked",
+                                  priorityLevel == "none" ? "true" : "false");
+        priorityLow.setAttribute("checked",
+                                 priorityLevel == "low" ? "true" : "false");
+        priorityNormal.setAttribute("checked",
+                                    priorityLevel == "normal" ? "true" : "false");
+        priorityHigh.setAttribute("checked",
+                                  priorityLevel == "high" ? "true" : "false");
+
+        // Status bar panel
+        let priorityPanel = document.getElementById("status-priority");
+        if (priorityLevel == "none") {
+            // If the priority is none, don't show the status bar panel
+            priorityPanel.setAttribute("collapsed", "true");
+        } else {
+            priorityPanel.removeAttribute("collapsed");
+            let foundPriority = false;
+            for (let node of priorityPanel.childNodes) {
+                if (foundPriority) {
+                    node.setAttribute("collapsed", "true");
+                } else {
+                    node.removeAttribute("collapsed");
+                }
+                if (node.getAttribute("value") == priorityLevel) {
+                    foundPriority = true;
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Handler for rotate status command.
+ */
+function rotateStatus() {
+    let noneCmd = document.getElementById("cmd_status_none");
+    let isVisible = !noneCmd.hasAttribute("hidden");
+    sendMessage({
+        command: "rotateStatus",
+        noneCommandIsVisible: isVisible
+    });
+}
+
+/**
+ * Handler to change the status from the dialog elements.
+ *
+ * @param {nsIDOMNode} aTarget  Its value attribute contains the new status
+ */
+function editStatus(aTarget) {
+    sendMessage({
+        command: "editStatus",
+        value: aTarget.getAttribute("value")
+    });
+}
+
+/**
+ * Update the dialog controls related to status.
+ *
+ * @param {Object} aArg         Contains the new status value
+ * @param {string} aArg.status  The new status value
+ */
+function updateStatus(aArg) {
+    const statusLabels = ["status-status-tentative-label",
+                          "status-status-confirmed-label",
+                          "status-status-cancelled-label"];
+    const commands = ["cmd_status_none",
+                      "cmd_status_tentative",
+                      "cmd_status_confirmed",
+                      "cmd_status_cancelled"];
+    let found = false;
+    setBooleanAttribute("status-status", "collapsed", true);
+    commands.forEach((aElement, aIndex, aArray) => {
+        let node = document.getElementById(aElement);
+        let matches = (node.getAttribute("value") == aArg.status);
+        found = found || matches;
+
+        node.setAttribute("checked", matches ? "true" : "false");
+
+        if (aIndex > 0) {
+            setBooleanAttribute(statusLabels[aIndex-1], "hidden", !matches);
+            if (matches) {
+                setBooleanAttribute("status-status", "collapsed", false);
+            }
+        }
+    });
+    if (!found) {
+        // The current Status value is invalid. Change the status to
+        // "not specified" and update the status again.
+        sendMessage({ command: "editStatus", value: "NONE" });
+    }
+}
+
+/**
+ * Handler for rotate transparency command.
+ */
+function rotateShowTimeAs() {
+    sendMessage({ command: "rotateShowTimeAs" });
+}
+
+/**
+ * Handler to change the transparency from the dialog elements.
+ *
+ * @param {nsIDOMNode} aTarget  Its value attribute contains the new transparency
+ */
+function editShowTimeAs(aTarget) {
+    sendMessage({
+        command: "editShowTimeAs",
+        value: aTarget.getAttribute("value")
+    });
+}
+
+/**
+ * Update the dialog controls related to transparency.
+ *
+ * @param {Object} aArg             Contains the new transparency value
+ * @param {string} aArg.showTimeAs  The new transparency value
+ */
+function updateShowTimeAs(aArg) {
+    let showAsBusy = document.getElementById("cmd_showtimeas_busy");
+    let showAsFree = document.getElementById("cmd_showtimeas_free");
+
+    showAsBusy.setAttribute("checked",
+                            aArg.showTimeAs == "OPAQUE" ? "true" : "false");
+    showAsFree.setAttribute("checked",
+                            aArg.showTimeAs == "TRANSPARENT" ? "true" : "false");
+
+    setBooleanAttribute("status-freebusy",
+                        "collapsed",
+                        aArg.showTimeAs != "OPAQUE" && aArg.showTimeAs != "TRANSPARENT");
+    setBooleanAttribute("status-freebusy-free-label", "hidden", aArg.showTimeAs == "OPAQUE");
+    setBooleanAttribute("status-freebusy-busy-label", "hidden", aArg.showTimeAs == "TRANSPARENT");
+}
+
+/**
+ * Get the timezone button state.
+ *
+ * @return {boolean}  True is active/checked and false is inactive/unchecked
+ */
+function getTimezoneCommandState() {
+    let cmdTimezone = document.getElementById("cmd_timezone");
+    return cmdTimezone.getAttribute("checked") == "true";
+}
+
+/**
+ * Set the timezone button state.  Used to keep the toolbar button in
+ * sync when switching tabs.
+ *
+ * @param {Object}  aArg                   Contains timezones property
+ * @param {boolean} aArg.timezonesEnabled  Are timezones enabled?
+ */
+function updateTimezoneCommand(aArg) {
+    let cmdTimezone = document.getElementById("cmd_timezone");
+    cmdTimezone.setAttribute("checked", aArg.timezonesEnabled);
+    gConfig.timezonesEnabled = aArg.timezonesEnabled;
+}
+
+/**
+ * Toggles the command that allows enabling the timezone links in the dialog.
+ */
+function toggleTimezoneLinks() {
+    let cmdTimezone = document.getElementById("cmd_timezone");
+    let currentState = getTimezoneCommandState();
+    cmdTimezone.setAttribute("checked", currentState ? "false" : "true");
+    gConfig.timezonesEnabled = !currentState;
+    sendMessage({ command: "toggleTimezoneLinks", checked: !currentState });
+}
+
+/**
+ * Toggles the visibility of the related link (rfc2445 URL property).
+ */
+function toggleLink() {
+    let linkCommand = document.getElementById("cmd_toggle_link");
+    let checked = linkCommand.getAttribute("checked") == "true";
+
+    linkCommand.setAttribute("checked", checked ? "false" : "true");
+    sendMessage({ command: "toggleLink", checked: !checked });
+}
+
+/**
+ * Prompts the user to attach an url to this item.
+ */
+function attachURL() {
+    sendMessage({ command: "attachURL" });
+}
+
+/**
+ * Updates dialog controls related to item attachments.
+ *
+ * @param {Object}  aArg                   Container
+ * @param {boolean} aArg.attachUrlCommand  Enable the attach url command?
+ */
+function updateAttachment(aArg) {
+    setElementValue("cmd_attach_url", !aArg.attachUrlCommand && "true", "disabled");
+}
+
+/**
+ * Updates attendees command enabled/disabled state.
+ *
+ * @param {Object}  aArg                   Container
+ * @param {boolean} aArg.attendeesCommand  Enable the attendees command?
+ */
+function updateAttendeesCommand(aArg) {
+    setElementValue("cmd_attendees", !aArg.attendeesCommand, "disabled");
+}
+
+/**
+ * Enables/disables the commands cmd_accept and cmd_save related to the
+ * save operation.
+ *
+ * @param {boolean} aEnable  Enable the commands?
+ */
+function enableAcceptCommand(aEnable) {
+    setElementValue("cmd_accept", !aEnable, "disabled");
+    setElementValue("cmd_save", !aEnable, "disabled");
+}
+
+/**
+ * Enable and un-collapse all elements that are disable-on-readonly and
+ * collapse-on-readonly.
+ */
+function removeDisableAndCollapseOnReadonly() {
+    let enableElements = document.getElementsByAttribute("disable-on-readonly", "true");
+    for (let element of enableElements) {
+        element.removeAttribute("disabled");
+    }
+    let collapseElements = document.getElementsByAttribute("collapse-on-readonly", "true");
+    for (let element of collapseElements) {
+        element.removeAttribute("collapsed");
+    }
+}
+
+/**
+ * Handler to toggle toolbar visibility.
+ *
+ * @param {string} aToolbarId   The id of the toolbar node to toggle
+ * @param {string} aMenuitemId  The corresponding menuitem in the view menu
+ */
+function onCommandViewToolbar(aToolbarId, aMenuItemId) {
+    let toolbar = document.getElementById(aToolbarId);
+    let menuItem = document.getElementById(aMenuItemId);
+
+    if (!toolbar || !menuItem) {
+        return;
+    }
+
+    let toolbarCollapsed = toolbar.collapsed;
+
+    // toggle the checkbox
+    menuItem.setAttribute("checked", toolbarCollapsed);
+
+    // toggle visibility of the toolbar
+    toolbar.collapsed = !toolbarCollapsed;
+
+    document.persist(aToolbarId, "collapsed");
+    document.persist(aMenuItemId, "checked");
+}
+
+/**
+ * Called after the customize toolbar dialog has been closed by the
+ * user. We need to restore the state of all buttons and commands of
+ * all customizable toolbars.
+ *
+ * @param {boolean} aToolboxChanged  When true the toolbox has changed
+ */
+function dialogToolboxCustomizeDone(aToolboxChanged) {
+
+    let menubar = document.getElementById("event-menubar");
+    // XXX After we disable certain menu items in a tab (see below),
+    // we need to re-enable them.
+    if (menubar) {
+        for (let i = 0; i < menubar.childNodes.length; ++i) {
+            menubar.childNodes[i].removeAttribute("disabled");
+        }
+    }
+
+    // make sure our toolbar buttons have the correct enabled state restored to them...
+    document.commandDispatcher.updateCommands("itemCommands");
+
+    // Enable the toolbar context menu items
+    document.getElementById("cmd_customize").removeAttribute("disabled");
+
+    // Update privacy items to make sure the toolbarbutton's menupopup is set
+    // correctly
+    updatePrivacy(gConfig);
+}
+
+/**
+ * Handler to start the customize toolbar dialog for the event dialog's toolbar.
+ */
+function onCommandCustomize() {
+    // install the callback that handles what needs to be
+    // done after a toolbar has been customized.
+    let toolboxId = "event-toolbox";
+
+    let toolbox = document.getElementById(toolboxId);
+    toolbox.customizeDone = dialogToolboxCustomizeDone;
+
+    let menubar = document.getElementById("event-menubar");
+    // XXX We need to disable certain menu items when in a tab.
+    if (menubar) {
+        for (let i = 0; i < menubar.childNodes.length; ++i) {
+            menubar.childNodes[i].setAttribute("disabled", true);
+        }
+    }
+
+    // Disable the toolbar context menu items
+    document.getElementById("cmd_customize").setAttribute("disabled", "true");
+
+    let wintype = document.documentElement.getAttribute("windowtype");
+    wintype = wintype.replace(/:/g, "");
+
+    window.openDialog("chrome://global/content/customizeToolbar.xul",
+                      "CustomizeToolbar" + wintype,
+                      "chrome,all,dependent",
+                      document.getElementById(toolboxId), // toolbox dom node
+                      false,                              // is mode toolbar yes/no?
+                      null,                               // callback function
+                      "dialog");                          // name of this mode
+}
new file mode 100644
--- /dev/null
+++ b/calendar/lightning/content/lightning-item-panel.xul
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!-- lightning-toolbar.dtd is only needed for the app menu button -->
+<!DOCTYPE overlay [
+    <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+    <!ENTITY % globalDTD SYSTEM "chrome://calendar/locale/global.dtd">
+    <!ENTITY % calendarDTD SYSTEM "chrome://calendar/locale/calendar.dtd">
+    <!ENTITY % eventDialogDTD SYSTEM "chrome://calendar/locale/calendar-event-dialog.dtd">
+    <!ENTITY % toolbarDTD SYSTEM "chrome://lightning/locale/lightning-toolbar.dtd">
+    %brandDTD;
+    %globalDTD;
+    %calendarDTD;
+    %eventDialogDTD;
+    %toolbarDTD;
+]>
+
+<?xul-overlay href="chrome://lightning/content/lightning-item-toolbar.xul"?>
+
+<overlay id="ltnCalendarItemPanelContentOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <tabpanels id="tabpanelcontainer">
+    <vbox id="lightningItemPanel" collapsed="true">
+
+      <!-- The id of the inner vbox and the iframe are set dynamically
+           when a tab is created. -->
+      <vbox flex="1"
+            id="dummy-calendar-event-dialog-tab"
+            class="calendar-event-dialog-tab">
+
+        <stringbundleset id="stringbundleset">
+          <stringbundle id="languageBundle"
+                        src="chrome://global/locale/languageNames.properties"/>
+        </stringbundleset>
+
+        <script type="application/javascript"
+                src="chrome://global/content/globalOverlay.js"/>
+
+        <!-- Command updater -->
+        <commandset id="globalEditMenuItems"
+                    commandupdater="true"
+                    events="focus"
+                    oncommandupdate="goUpdateGlobalEditMenuItems()"/>
+        <commandset id="selectEditMenuItems"
+                    commandupdater="true"
+                    events="select"
+                    oncommandupdate="goUpdateSelectEditMenuItems()"/>
+        <commandset id="undoEditMenuItems"
+                    commandupdater="true"
+                    events="undo"
+                    oncommandupdate="goUpdateUndoEditMenuItems()"/>
+        <commandset id="clipboardEditMenuItems"
+                    commandupdater="true"
+                    events="clipboard"
+                    oncommandupdate="goUpdatePasteMenuItems()"/>
+
+        <!-- Commands -->
+        <commandset id="itemCommands">
+
+          <!-- Item menu -->
+          <command id="cmd_item_new_event"
+                   oncommand="openNewEvent()"/>
+          <command id="cmd_item_new_task"
+                   oncommand="openNewTask()"/>
+          <command id="cmd_item_new_message"
+                   oncommand="openNewMessage()"/>
+          <command id="cmd_item_new_card"
+                   oncommand="openNewCardDialog()"/>
+          <command id="cmd_item_close"
+                   oncommand="cancelDialog()"/>
+          <command id="cmd_save"
+                   disable-on-readonly="true"
+                   oncommand="onCommandSave()"/>
+          <command id="cmd_item_delete"
+                   disable-on-readonly="true"
+                   oncommand="onCommandDeleteItem()"/>
+          <command id="cmd_printSetup"
+                   oncommand="PrintUtils.showPageSetup()"/>
+          <command id="cmd_print"
+                   disabled="true"
+                   oncommand="calPrint()"/>
+
+          <!-- Edit menu -->
+          <command id="cmd_undo"
+                   disabled="true"
+                   oncommand="goDoCommand('cmd_undo')"/>
+          <command id="cmd_redo"
+                   disabled="true"
+                   oncommand="goDoCommand('cmd_redo')"/>
+          <command id="cmd_cut"
+                   disabled="true"
+                   oncommand="goDoCommand('cmd_cut')"/>
+          <command id="cmd_copy"
+                   disabled="true"
+                   oncommand="goDoCommand('cmd_copy')"/>
+          <command id="cmd_paste"
+                   disabled="true"
+                   oncommand="goDoCommand('cmd_paste')"/>
+          <command id="cmd_selectAll"
+                   disabled="true"
+                   oncommand="goDoCommand('cmd_selectAll')"/>
+
+          <!-- View menu -->
+          <command id="cmd_toolbar"
+                   oncommand="onCommandViewToolbar('event-toolbar',
+                                                   'view-toolbars-event-menuitem')"/>
+          <command id="cmd_customize"
+                   oncommand="onCommandCustomize()"/>
+          <command id="cmd_toggle_link"
+                   persist="checked"
+                   oncommand="toggleLink()"/>
+
+          <!-- status -->
+          <command id="cmd_status_none"
+                   oncommand="editStatus(event.target)"
+                   hidden="true"
+                   value="NONE"/>
+          <command id="cmd_status_tentative"
+                   oncommand="editStatus(event.target)"
+                   value="TENTATIVE"/>
+          <command id="cmd_status_confirmed"
+                   oncommand="editStatus(event.target)"
+                   value="CONFIRMED"/>
+          <command id="cmd_status_cancelled"
+                   oncommand="editStatus(event.target)"
+                   value="CANCELLED"/>
+
+          <!-- priority -->
+          <command id="cmd_priority_none"
+                   oncommand="editPriority(event.target)"
+                   value="0"/>
+          <command id="cmd_priority_low"
+                   oncommand="editPriority(event.target)"
+                   value="9"/>
+          <command id="cmd_priority_normal"
+                   oncommand="editPriority(event.target)"
+                   value="5"/>
+          <command id="cmd_priority_high"
+                   oncommand="editPriority(event.target)"
+                   value="1"/>
+
+          <!-- freebusy -->
+          <command id="cmd_showtimeas_busy"
+                   oncommand="editShowTimeAs(event.target)"
+                   value="OPAQUE"/>
+          <command id="cmd_showtimeas_free"
+                   oncommand="editShowTimeAs(event.target)"
+                   value="TRANSPARENT"/>
+
+          <!-- attendees -->
+          <command id="cmd_attendees"
+                   oncommand="editAttendees();"/>
+
+          <!-- accept, attachments, timezone -->
+          <command id="cmd_accept"
+                   disable-on-readonly="true"
+                   oncommand="onAccept();"/>
+          <command id="cmd_attach_url"
+                   disable-on-readonly="true"
+                   oncommand="attachURL()"/>
+          <command id="cmd_timezone"
+                   persist="checked"
+                   checked="false"
+                   oncommand="toggleTimezoneLinks()"/>
+        </commandset>
+
+        <keyset id="calendar-event-dialog-keyset">
+          <key id="new-event-key"
+               modifiers="accel"
+               key="&event.dialog.new.event.key2;"
+               command="cmd_item_new_event"/>
+          <key id="new-task-key"
+               modifiers="accel"
+               key="&event.dialog.new.task.key2;"
+               command="cmd_item_new_task"/>
+          <key id="new-message-key"
+               modifiers="accel"
+               key="&event.dialog.new.message.key2;"
+               command="cmd_item_new_message"/>
+          <key id="close-key"
+               modifiers="accel"
+               key="&event.dialog.close.key;"
+               command="cmd_item_close"/>
+          <key id="save-key"
+               modifiers="accel"
+               key="&event.dialog.save.key;"
+               command="cmd_save"/>
+          <key id="saveandclose-key"
+               modifiers="accel"
+               key="&event.dialog.saveandclose.key;"
+               command="cmd_accept"/>
+          <key id="saveandclose-key2"
+               modifiers="accel"
+               keycode="VK_RETURN"
+               command="cmd_accept"/>
+          <key id="print-key"
+               modifiers="accel"
+               key="&event.dialog.print.key;"
+               command="cmd_print"/>
+          <key id="undo-key"
+               modifiers="accel"
+               key="&event.dialog.undo.key;"
+               command="cmd_undo"/>
+          <key id="redo-key"
+               modifiers="accel"
+               key="&event.dialog.redo.key;"
+               command="cmd_redo"/>
+          <key id="cut-key"
+               modifiers="accel"
+               key="&event.dialog.cut.key;"
+               command="cmd_cut"/>
+          <key id="copy-key"
+               modifiers="accel"
+               key="&event.dialog.copy.key;"
+               command="cmd_copy"/>
+          <key id="paste-key"
+               modifiers="accel"
+               key="&event.dialog.paste.key;"
+               command="cmd_paste"/>
+          <key id="select-all-key"
+               modifiers="accel"
+               key="&event.dialog.select.all.key;"
+               command="cmd_selectAll"/>
+        </keyset>
+
+        <toolbox id="event-toolbox"
+                 class="mail-toolbox"
+                 mode="full"
+                 defaultmode="full"
+#ifdef XP_MACOSX
+                 iconsize="small"
+                 defaulticonsize="small"
+#endif
+                 labelalign="end"
+                 defaultlabelalign="end">
+          <!-- more toolbarpalette items are added with an overlay -->
+          <toolbarpalette id="event-toolbarpalette">
+            <toolbarbutton id="calendar-item-appmenu-button"
+                           class="toolbarbutton-1 button-appmenu"
+                           label="&lightning.toolbar.appmenuButton.label;"
+                           tooltiptext="&lightning.toolbar.appmenuButton1.tooltip;"/>
+          </toolbarpalette>
+          <!-- toolboxid is set here since we move the toolbar around for tabs -->
+          <toolbar id="event-tab-toolbar"
+                   toolboxid="event-toolbox"
+                   class="chromeclass-toolbar inline-toolbar"
+                   customizable="true"
+                   labelalign="end"
+                   defaultlabelalign="end"
+                   context="event-dialog-toolbar-context-menu"
+                   defaultset="button-save,button-attendees,button-privacy,button-url,button-priority,button-status,button-freebusy,button-delete,spring,calendar-item-appmenu-button"/>
+          <toolbarset id="custom-toolbars"/>
+        </toolbox>
+
+        <iframe id="lightning-item-panel-iframe" flex="1"/>
+
+      </vbox>
+    </vbox>
+  </tabpanels>
+
+  <popupset id="calendar-popupset">
+    <menupopup id="event-dialog-toolbar-context-menu">
+      <menuitem id="CustomizeDialogToolbar"
+                label="&event.menu.view.toolbars.customize.label;"
+                command="cmd_customize"/>
+    </menupopup>
+  </popupset>
+
+</overlay>
+
new file mode 100644
--- /dev/null
+++ b/calendar/lightning/content/lightning-item-toolbar.xul
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE overlay [
+    <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
+    <!ENTITY % globalDTD SYSTEM "chrome://calendar/locale/global.dtd">
+    <!ENTITY % calendarDTD SYSTEM "chrome://calendar/locale/calendar.dtd">
+    <!ENTITY % eventDialogDTD SYSTEM "chrome://calendar/locale/calendar-event-dialog.dtd">
+    %brandDTD;
+    %globalDTD;
+    %calendarDTD;
+    %eventDialogDTD;
+]>
+
+<overlay id="ltnCalendarItemPanelContentOverlay"
+         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <toolbarpalette id="event-toolbarpalette">
+    <!-- this is "save and close" -->
+    <toolbarbutton id="button-save"
+                   mode="dialog"
+                   class="cal-event-toolbarbutton toolbarbutton-1"
+                   label="&event.toolbar.save.label;"
+                   tooltiptext="&event.toolbar.save.tooltip;"
+                   command="cmd_accept"/>
+    <toolbarbutton id="button-attendees"
+                   mode="dialog"
+                   class="cal-event-toolbarbutton toolbarbutton-1 event-only"
+                   disable-on-readonly="true"
+                   label="&event.toolbar.attendees.label;"
+                   tooltiptext="&event.toolbar.attendees.tooltip;"
+                   command="cmd_attendees"/>
+    <toolbarbutton id="button-privacy"
+                   mode="dialog"
+                   class="cal-event-toolbarbutton toolbarbutton-1"
+                   type="menu-button"
+                   disable-on-readonly="true"
+                   label="&event.toolbar.privacy.label;"
+                   tooltiptext="&event.toolbar.privacy.tooltip;"
+                   oncommand="rotatePrivacy()">
+      <menupopup id="event-privacy-menupopup">
+        <menuitem id="event-privacy-public-menuitem"
+                  name="event-privacy-group"
+                  label="&event.menu.options.privacy.public.label;"
+                  type="radio"
+                  privacy="PUBLIC"
+                  oncommand="editPrivacy(this, event)"/>
+        <menuitem id="event-privacy-confidential-menuitem"
+                  name="event-privacy-group"
+                  label="&event.menu.options.privacy.confidential.label;"
+                  type="radio"
+                  privacy="CONFIDENTIAL"
+                  oncommand="editPrivacy(this, event)"/>
+        <menuitem id="event-privacy-private-menuitem"
+                  name="event-privacy-group"
+                  label="&event.menu.options.privacy.private.label;"
+                  type="radio"
+                  privacy="PRIVATE"
+                  oncommand="editPrivacy(this, event)"/>
+      </menupopup>
+    </toolbarbutton>
+    <toolbarbutton id="button-url"
+                   type="menu-button"
+                   mode="dialog"
+                   class="cal-event-toolbarbutton toolbarbutton-1"
+                   label="&event.attachments.menubutton.label;"
+                   tooltiptext="&event.toolbar.attachments.tooltip;"
+                   command="cmd_attach_url"
+                   disable-on-readonly="true">
+      <menupopup id="button-attach-menupopup">
+        <menuitem id="button-attach-url"
+                  label="&event.attachments.url.label;"
+                  command="cmd_attach_url"/>
+      </menupopup>
+    </toolbarbutton>
+    <toolbarbutton id="button-delete"
+                   mode="dialog"
+                   class="cal-event-toolbarbutton toolbarbutton-1"
+                   label="&event.toolbar.delete.label;"
+                   tooltiptext="&event.toolbar.delete.tooltip;"
+                   command="cmd_item_delete"
+                   disable-on-readonly="true"/>
+    <toolbarbutton id="button-priority"
+                   mode="dialog"
+                   class="cal-event-toolbarbutton toolbarbutton-1"
+                   type="menu-button"
+                   disable-on-readonly="true"
+                   label="&event.menu.options.priority2.label;"
+                   tooltiptext="&event.toolbar.priority.tooltip;"
+                   oncommand="rotatePriority()">
+      <menupopup id="event-priority-menupopup">
+        <menuitem id="event-priority-none-menuitem"
+                  name="event-priority-group"
+                  label="&event.menu.options.priority.notspecified.label;"
+                  type="radio"
+                  command="cmd_priority_none"/>
+        <menuitem id="event-priority-low-menuitem"
+                  name="event-priority-group"
+                  label="&event.menu.options.priority.low.label;"
+                  type="radio"
+                  command="cmd_priority_low"/>
+        <menuitem id="event-priority-normal-menuitem"
+                  name="event-priority-group"
+                  label="&event.menu.options.priority.normal.label;"
+                  type="radio"
+                  command="cmd_priority_normal"/>
+        <menuitem id="event-priority-high-menuitem"
+                  name="event-priority-group"
+                  label="&event.menu.options.priority.high.label;"
+                  type="radio"
+                  command="cmd_priority_high"/>
+      </menupopup>
+    </toolbarbutton>
+    <toolbarbutton id="button-status"
+                   mode="dialog"
+                   class="cal-event-toolbarbutton toolbarbutton-1 event-only"
+                   type="menu-button"
+                   disable-on-readonly="true"
+                   label="&newevent.status.label;"
+                   tooltiptext="&event.toolbar.status.tooltip;"
+                   oncommand="rotateStatus()">
+      <menupopup id="event-status-menupopup">
+        <menuitem id="event-status-none-menuitem"
+                  name="event-status-group"
+                  label="&newevent.eventStatus.none.label;"
+                  type="radio"
+                  command="cmd_status_none"/>
+        <menuitem id="event-status-tentative-menuitem"
+                  name="event-status-group"
+                  label="&newevent.status.tentative.label;"
+                  type="radio"
+                  command="cmd_status_tentative"/>
+        <menuitem id="event-status-confirmed-menuitem"
+                  name="event-status-group"
+                  label="&newevent.status.confirmed.label;"
+                  type="radio"
+                  command="cmd_status_confirmed"/>
+        <menuitem id="event-status-cancelled-menuitem"
+                  name="event-status-group"
+                  label="&newevent.eventStatus.cancelled.label;"
+                  type="radio"
+                  command="cmd_status_cancelled"/>
+      </menupopup>
+    </toolbarbutton>
+    <toolbarbutton id="button-freebusy"
+                   mode="dialog"
+                   class="cal-event-toolbarbutton toolbarbutton-1 event-only"
+                   type="menu-button"
+                   disable-on-readonly="true"
+                   label="&event.menu.options.show.time.label;"
+                   tooltiptext="&event.toolbar.freebusy.tooltip;"
+                   oncommand="rotateShowTimeAs()">
+      <menupopup id="event-freebusy-menupopup">
+        <menuitem id="event-freebusy-busy-menuitem"
+                  name="event-freebusy-group"
+                  label="&event.menu.options.show.time.busy.label;"
+                  type="radio"
+                  command="cmd_showtimeas_busy"/>
+        <menuitem id="event-freebusy-free-menuitem"
+                  name="event-freebusy-group"
+                  label="&event.menu.options.show.time.free.label;"
+                  type="radio"
+                  command="cmd_showtimeas_free"/>
+      </menupopup>
+    </toolbarbutton>
+    <toolbarbutton id="button-timezones"
+                   mode="dialog"
+                   type="checkbox"
+                   class="cal-event-toolbarbutton toolbarbutton-1"
+                   label="&event.menu.options.timezone2.label;"
+                   tooltiptext="&event.menu.options.timezone2.label;"
+                   command="cmd_timezone"/>
+  </toolbarpalette>
+</overlay>
--- a/calendar/lightning/content/lightning.js
+++ b/calendar/lightning/content/lightning.js
@@ -145,16 +145,19 @@ pref("calendar.network.multirealm", fals
 
 // Disable use of system colors in minimonth and calendar views
 pref("calendar.view.useSystemColors", false);
 
 // Maximum number of iterations allowed when searching for the next matching
 // occurrence of a repeating item in calFilter
 pref("calendar.filter.maxiterations", 50);
 
+// Edit events and tasks in a tab rather than a window.
+pref("calendar.item.editInTab", false);
+
 // Backend to use. false: libical, true: ical.js
 #ifdef NIGHTLY_BUILD
 pref("calendar.icaljs", true);
 #else
 pref("calendar.icaljs", false);
 #endif
 
 // Calendar integration notification
--- a/calendar/lightning/content/messenger-overlay-sidebar.js
+++ b/calendar/lightning/content/messenger-overlay-sidebar.js
@@ -126,28 +126,227 @@ var calendarTabType = {
       },
 
       supportsCommand: (aCommand, aTab) => calendarController2.supportsCommand(aCommand),
       isCommandEnabled: (aCommand, aTab) => calendarController2.isCommandEnabled(aCommand),
       doCommand: (aCommand, aTab) => calendarController2.doCommand(aCommand),
       onEvent: (aEvent, aTab) => calendarController2.onEvent(aEvent)
     }
   },
-
-  /* because calendar does some direct menu manipulation, we need to change
-   *  to the mail mode to clean up after those hacks.
+  /**
+   * Because calendar does some direct menu manipulation, we need to
+   * change to the mail mode to clean up after those hacks.
+   *
+   * @param {Object} aTab  A tab info object
    */
   saveTabState: function(aTab) {
     ltnSwitch2Mail();
   }
 };
 
+/**
+ * For details about tab info objects and the tabmail interface see:
+ * comm-central/mail/base/content/mailTabs.js
+ * comm-central/mail/base/content/tabmail.xml
+ */
+var calendarItemTabType = {
+    name: "calendarItem",
+    perTabPanel: "vbox",
+    idNumber: 0,
+    modes: {
+        calendarEvent: {
+            type: "calendarEvent"
+        },
+        calendarTask: {
+            type: "calendarTask"
+        }
+    },
+    /**
+     * Opens an event tab or a task tab.
+     *
+     * @param {Object} aTab   A tab info object
+     * @param {Object} aArgs  Contains data about the event/task
+     */
+    openTab: function(aTab, aArgs) {
+        // Create a clone to use for this tab. Remove the cloned toolbox
+        // and move the original toolbox into its place. There is only
+        // one toolbox/toolbar so its settings are the same for all item tabs.
+        let original = document.getElementById("lightningItemPanel").firstChild;
+        let clone = original.cloneNode(true);
+
+        clone.querySelector("toolbox").remove();
+        moveEventToolbox(clone);
+        clone.setAttribute("id", "calendarItemTab" + this.idNumber);
+
+        if (aTab.mode.type == "calendarTask") {
+            // For task tabs, css class hides event-specific toolbar buttons.
+            clone.setAttribute("class", "calendar-task-dialog-tab");
+        }
+
+        aTab.panel.appendChild(clone);
+
+        // Set up the iframe and store the iframe's id.
+        aTab.iframe = aTab.panel.querySelector("iframe");
+        let iframeId = "calendarItemTabIframe" + this.idNumber;
+        aTab.iframe.setAttribute("id", iframeId);
+        aTab.iframe.setAttribute("src", aArgs.url);
+        gItemTabIds.push(iframeId);
+
+        // Generate and set the tab title.
+        let strName;
+        if (aTab.mode.type == "calendarEvent") {
+            strName = aArgs.calendarEvent.title ? "editEventDialog" : "newEventDialog";
+        } else if (aTab.mode.type == "calendarTask") {
+            strName = aArgs.calendarEvent.title ? "editTaskDialog" : "newTaskDialog";
+        } else {
+            throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+        }
+        // name is "New Event", "Edit Task", etc.
+        let name = cal.calGetString("calendar", strName);
+        aTab.title = name + ": " + (aArgs.calendarEvent.title || name);
+
+        // allowTabClose prevents the tab from being closed until we ask
+        // the user if they want to save any unsaved changes.
+        aTab.allowTabClose = false;
+
+        // Put the arguments where they can be accessed easily
+        // from the iframe. (window.arguments[0])
+        aTab.iframe.contentWindow.arguments = [aArgs];
+
+        this.idNumber += 1;
+    },
+    /**
+     * Saves a tab's state when it is deactivated / hidden.  The opposite of showTab.
+     *
+     * @param {Object} aTab  A tab info object
+     */
+    saveTabState: function(aTab) {
+        // save state
+        aTab.itemTabConfig = {};
+        Object.assign(aTab.itemTabConfig, gConfig);
+
+        // clear statusbar
+        let statusbar = document.getElementById("status-bar");
+        let items = statusbar.getElementsByClassName("event-dialog");
+        for (let item of items) {
+            item.setAttribute("collapsed", true);
+        }
+        // move toolbox to the place where it can be accessed later
+        let to = document.getElementById("lightningItemPanel").firstChild;
+        moveEventToolbox(to);
+    },
+    /**
+     * Called when a tab is activated / shown.  The opposite of saveTabState.
+     *
+     * @param {Object} aTab  A tab info object
+     */
+    showTab: function(aTab) {
+        // move toolbox into place then load state
+        moveEventToolbox(aTab.panel.firstChild);
+        Object.assign(gConfig, aTab.itemTabConfig);
+        updateItemTabState(gConfig);
+    },
+    /**
+     * Called when there is a request to close a tab.  Using aTab.allowTabClose
+     * we first prevent the tab from closing so we can prompt the user
+     * about saving changes, then we allow the tab to close.
+     *
+     * @param {Object} aTab  A tab info object
+     */
+    tryCloseTab: function(aTab) {
+        if (aTab.allowTabClose) {
+            return true;
+        } else {
+            onCancel(aTab.iframe.id);
+            return false;
+        }
+    },
+    /**
+     * Closes a tab.
+     *
+     * @param {Object} aTab  A tab info object
+     */
+    closeTab: function(aTab) {
+        // Remove the iframe id from the array where they are stored.
+        let index = gItemTabIds.indexOf(aTab.iframe.id);
+        if (index != -1) {
+            gItemTabIds.splice(index, 1);
+        }
+        aTab.itemTabConfig = null;
+    },
+    /**
+     * Called when quitting the application (and/or closing the window).
+     * Saves an open tab's state to be able to restore it later.
+     *
+     * @param {Object} aTab  A tab info object
+     */
+    persistTab: function(aTab) {
+        let args = aTab.iframe.contentWindow.arguments[0];
+        // Serialize args, with manual handling of some properties.
+        // persistTab is called even for new events/tasks in tabs that
+        // were closed and never saved (for 'undo close tab'
+        // functionality), thus we confirm we have the expected values.
+        if (args && args.calendar && args.calendar.id &&
+            args.calendarEvent && args.calendarEvent.id) {
+
+            let calendarId = args.calendar.id;
+            let itemId = args.calendarEvent.id;
+            // Handle null args.initialStartDateValue, just for good measure.
+            // Note that this is not the start date for the event or task.
+            let hasDateValue = args.initialStartDateValue &&
+                               args.initialStartDateValue.icalString;
+            let initialStartDate = hasDateValue
+                ? args.initialStartDateValue.icalString : null;
+
+            args.calendar = null;
+            args.calendarEvent = null;
+            args.initialStartDateValue = null;
+
+            return {
+                calendarId: calendarId,
+                itemId: itemId,
+                initialStartDate: initialStartDate,
+                args: args,
+                tabType: aTab.mode.type
+            };
+        }
+    },
+    /**
+     * Called when starting the application (and/or opening the window).
+     * Restores a tab that was open when the application was quit previously.
+     *
+     * @param {Object} aTabmail  The tabmail interface
+     * @param {Object} aState    The state of the tab to restore
+     */
+    restoreTab: function(aTabmail, aState) {
+        // Sometimes restoreTab is called for tabs that were never saved
+        // and never meant to be persisted or restored. See persistTab.
+        if (aState.args && aState.calendarId && aState.itemId) {
+            aState.args.initialStartDateValue = aState.initialStartDate
+                ? cal.createDateTime(aState.initialStartDate) : getDefaultStartDate();
+
+            aState.args.calendar = getCalendarManager().getCalendarById(aState.calendarId);
+            if (aState.args.calendar) {
+                // using wrappedJSObject is a hack that is needed to prevent a proxy error
+                let pcal = cal.async.promisifyCalendar(aState.args.calendar.wrappedJSObject);
+                pcal.getItem(aState.itemId).then((item) => {
+                    if (item[0]) {
+                        aState.args.calendarEvent = item[0];
+                        aTabmail.openTab(aState.tabType, aState.args);
+                    }
+                });
+            }
+        }
+    }
+};
+
 window.addEventListener("load", function(e) {
     let tabmail = document.getElementById('tabmail');
     tabmail.registerTabType(calendarTabType);
+    tabmail.registerTabType(calendarItemTabType);
     tabmail.registerTabMonitor(calendarTabMonitor);
 }, false);
 
 
 function ltnOnLoad(event) {
 
     // nuke the onload, or we get called every time there's
     // any load that occurs
@@ -618,16 +817,32 @@ function InitViewCalendarPaneMenu() {
                         !calSidebar.getAttribute("collapsed"));
 
     if (document.getElementById("appmenu_ltnViewCalendarPane")) {
         setBooleanAttribute("appmenu_ltnViewCalendarPane", "checked",
                             !calSidebar.getAttribute("collapsed"));
     }
 }
 
+
+/**
+ * Move the event toolbox, containing the toolbar, into view for a tab
+ * or back to its hiding place where it is accessed again for other tabs.
+ *
+ * @param {nsIDOMNode} aDestination  Destination where the toolbox will be moved
+ */
+function moveEventToolbox(aDestination) {
+    let toolbox = document.getElementById("event-toolbox");
+    // the <toolbarpalette> has to be copied manually
+    let palette = toolbox.palette;
+    let iframe = aDestination.querySelector("iframe");
+    aDestination.insertBefore(toolbox, iframe);
+    toolbox.palette = palette;
+}
+
 /**
  * Checks if Lightning's binary component was successfully loaded.
  */
 function checkCalendarBinaryComponent() {
     // Don't even get started if we are running ical.js or the binary component
     // was successfully loaded.
     if ("@mozilla.org/calendar/datetime;1" in Components.classes ||
         Preferences.get("calendar.icaljs", false)) {
@@ -667,8 +882,9 @@ function checkCalendarBinaryComponent() 
             text = ltnGetString("lightning", "binaryComponentUnknown", args);
         }
 
         let title = ltnGetString("lightning", "binaryComponentTitle", [extbrand]);
         openAddonsMgr("addons://detail/" + encodeURIComponent(LIGHTNING_GUID));
         Services.prompt.alert(window, title, text);
     });
 }
+
--- a/calendar/lightning/content/messenger-overlay-sidebar.xul
+++ b/calendar/lightning/content/messenger-overlay-sidebar.xul
@@ -5,24 +5,29 @@
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 
 <!DOCTYPE overlay
 [
   <!ENTITY % dtd1 SYSTEM "chrome://lightning/locale/lightning.dtd" > %dtd1;
   <!ENTITY % dtd2 SYSTEM "chrome://calendar/locale/menuOverlay.dtd" > %dtd2;
   <!ENTITY % dtd3 SYSTEM "chrome://calendar/locale/calendar.dtd" > %dtd3;
   <!ENTITY % dtd4 SYSTEM "chrome://lightning/locale/lightning-toolbar.dtd" > %dtd4;
-  <!ENTITY % messengerDTD SYSTEM "chrome://messenger/locale/messenger.dtd"> %messengerDTD;
+  <!ENTITY % messengerDTD SYSTEM "chrome://messenger/locale/messenger.dtd" > %messengerDTD;
+  <!ENTITY % eventDialogDTD SYSTEM "chrome://calendar/locale/calendar-event-dialog.dtd" > %eventDialogDTD;
 ]>
 
 <?xml-stylesheet href="chrome://lightning/skin/lightning.css" type="text/css"?>
 
 <?xml-stylesheet href="chrome://calendar/content/calendar-view-bindings.css" type="text/css"?>
 <?xml-stylesheet href="chrome://calendar/content/datetimepickers/datetimepickers.css" type="text/css"?>
 
+<?xml-stylesheet href="chrome://calendar/skin/calendar-event-dialog.css" type="text/css"?>
+<?xml-stylesheet href="chrome://calendar/content/calendar-event-dialog.css" type="text/css"?>
+<?xml-stylesheet href="chrome://calendar-common/skin/dialogs/calendar-event-dialog.css" type="text/css"?>
+
 <?xul-overlay href="chrome://calendar/content/calendar-calendars-list.xul"?>
 <?xul-overlay href="chrome://calendar/content/calendar-common-sets.xul"?>
 <?xul-overlay href="chrome://calendar/content/calendar-views.xul"?>
 
 <?xul-overlay href="chrome://lightning/content/lightning-toolbar.xul"?>
 <?xul-overlay href="chrome://lightning/content/lightning-menus.xul"?>
 
 <overlay id="ltnSidebarOverlay"
@@ -55,16 +60,19 @@
   <script type="application/javascript" src="chrome://calendar/content/calendar-task-editing.js"/>
 
   <script type="application/javascript" src="chrome://calendar/content/calendar-extract.js"/>
 
   <script type="application/javascript" src="chrome://lightning/content/lightning-utils.js"/>
   <script type="application/javascript" src="chrome://lightning/content/messenger-overlay-sidebar.js"/>
   <script type="application/javascript" src="chrome://calendar/content/calendar-invitations-manager.js"/>
 
+  <!-- NEEDED FOR EVENT/TASK IN A TAB -->
+  <script type="application/javascript" src="chrome://lightning/content/lightning-item-panel.js"/>
+
   <window id="messengerWindow">
     <!-- Be sure to keep these sets, since they will be overlayed by
          calendar/base/content/calendar-common-sets.xul -->
     <commandset id="calendar_commands">
       <command id="agenda_delete_event_command" oncommand="agendaListbox.deleteSelectedItem(false);"/>
       <command id="agenda_edit_event_command" oncommand="agendaListbox.editSelectedItem(event);"/>
       <command id="switch2calendar"
                oncommand="document.getElementById('tabmail').openTab('calendar', { title: document.getElementById('calendar-tab-button').getAttribute('title') })"/>
@@ -205,16 +213,89 @@
               class="calendar-sidebar-splitter"
               oncommand="TodayPane.onCommandTodaySplitter();">
       <grippy/>
     </splitter>
     <modevbox id="today-pane-panel" />
   </hbox>
 
   <statusbar id="status-bar">
+    <!-- event/task in tab statusbarpanels -->
+    <statusbarpanel id="status-text"
+                    class="event-dialog"
+                    flex="1"/>
+    <statusbarpanel id="status-privacy"
+                    class="event-dialog"
+                    align="center"
+                    flex="1"
+                    collapsed="true"
+                    pack="start">
+      <label value="&event.statusbarpanel.privacy.label;"/>
+      <hbox id="status-privacy-public-box" privacy="PUBLIC">
+        <label value="&event.menu.options.privacy.public.label;"/>
+      </hbox>
+      <hbox id="status-privacy-confidential-box" privacy="CONFIDENTIAL">
+        <label value="&event.menu.options.privacy.confidential.label;"/>
+      </hbox>
+      <hbox id="status-privacy-private-box" privacy="PRIVATE">
+        <label value="&event.menu.options.privacy.private.label;"/>
+      </hbox>
+    </statusbarpanel>
+    <statusbarpanel id="status-priority"
+                    class="event-dialog"
+                    align="center"
+                    flex="1"
+                    collapsed="true"
+                    pack="start">
+      <label value="&event.priority2.label;"/>
+      <image id="image-priority-low"
+             class="cal-statusbar-1"
+             collapsed="true"
+             value="low"/>
+      <image id="image-priority-normal"
+             class="cal-statusbar-1"
+             collapsed="true"
+             value="normal"/>
+      <image id="image-priority-high"
+             class="cal-statusbar-1"
+             collapsed="true"
+             value="high"/>
+    </statusbarpanel>
+    <statusbarpanel id="status-status"
+                    class="event-dialog"
+                    align="center"
+                    flex="1"
+                    collapsed="true"
+                    pack="start">
+      <label value="&task.status.label;"/>
+      <label id="status-status-tentative-label"
+             value="&newevent.status.tentative.label;"
+             hidden="true"/>
+      <label id="status-status-confirmed-label"
+             value="&newevent.status.confirmed.label;"
+             hidden="true"/>
+      <label id="status-status-cancelled-label"
+             value="&newevent.eventStatus.cancelled.label;"
+             hidden="true"/>
+    </statusbarpanel>
+    <statusbarpanel id="status-freebusy"
+                    class="event-only event-dialog"
+                    align="center"
+                    flex="1"
+                    collapsed="true"
+                    pack="start">
+      <label value="&event.statusbarpanel.freebusy.label;"/>
+      <label id="status-freebusy-free-label"
+             value="&event.freebusy.legend.free;"
+             hidden="true"/>
+      <label id="status-freebusy-busy-label"
+             value="&event.freebusy.legend.busy;"
+             hidden="true"/>
+    </statusbarpanel>
+    <!-- end event/task in tab statusbarpanels -->
     <statusbarpanel id="calendar-show-todaypane-panel"
                     pack="center">
       <toolbarbutton id="calendar-status-todaypane-button"
                      todaypane="true"
                      type="checkbox"
                      label="&todaypane.statusButton.label;"
                      tooltiptext="&calendar.todaypane.button.tooltip;"
                      observes="calendar_toggle_todaypane_command"
--- a/calendar/lightning/jar.mn
+++ b/calendar/lightning/jar.mn
@@ -2,16 +2,17 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 lightning.jar:
 % override chrome://messagebody/skin/imip.css chrome://lightning/skin/imip.css
 % override chrome://messagebody/skin/calendar-event-dialog-attendees.png chrome://calendar/skin/calendar-event-dialog-attendees.png
 % overlay chrome://messenger/content/messenger.xul chrome://lightning/content/lightning-migration.xul
+% overlay chrome://messenger/content/messenger.xul chrome://lightning/content/lightning-item-panel.xul
 % overlay chrome://messenger/content/msgAccountCentral.xul chrome://lightning/content/messenger-overlay-accountCentral.xul
 % overlay chrome://messenger/content/messenger.xul chrome://lightning/content/messenger-overlay-sidebar.xul
 % overlay chrome://messenger/content/messageWindow.xul chrome://lightning/content/imip-bar-overlay.xul
 % overlay chrome://messenger/content/messageWindow.xul chrome://lightning/content/messenger-overlay-messageWindow.xul
 % overlay chrome://lightning/content/messenger-overlay-sidebar.xul chrome://lightning/content/imip-bar-overlay.xul
 % overlay chrome://communicator/content/pref/preferences.xul chrome://lightning/content/suite-overlay-preferences.xul application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
 % overlay about:addons chrome://lightning/content/suite-overlay-addons.xul application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
 % overlay chrome://mozapps/content/extensions/extensions.xul chrome://lightning/content/suite-overlay-addons.xul application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
@@ -52,16 +53,21 @@ lightning.jar:
     content/lightning/messenger-overlay-sidebar.js         (content/messenger-overlay-sidebar.js)
     content/lightning/messenger-overlay-sidebar.xul        (content/messenger-overlay-sidebar.xul)
     content/lightning/messenger-overlay-preferences.js     (content/messenger-overlay-preferences.js)
     content/lightning/messenger-overlay-preferences.xul    (content/messenger-overlay-preferences.xul)
     content/lightning/suite-overlay-addons.xul             (content/suite-overlay-addons.xul)
     content/lightning/suite-overlay-preferences.xul        (content/suite-overlay-preferences.xul)
     content/lightning/suite-overlay-sidebar.js             (content/suite-overlay-sidebar.js)
     content/lightning/suite-overlay-sidebar.xul            (content/suite-overlay-sidebar.xul)
+    content/lightning/lightning-item-toolbar.xul           (content/lightning-item-toolbar.xul)
+*   content/lightning/lightning-item-panel.xul             (content/lightning-item-panel.xul)
+    content/lightning/lightning-item-panel.js              (content/lightning-item-panel.js)
+    content/lightning/lightning-item-iframe.xul            (content/lightning-item-iframe.xul)
+    content/lightning/lightning-item-iframe.js             (content/lightning-item-iframe.js)
 % skin lightning classic/1.0 chrome/skin/linux/lightning/
 % skin lightning classic/1.0 chrome/skin/osx/lightning/ os=Darwin
 % skin lightning classic/1.0 chrome/skin/windows/lightning/ os=WINNT
 % skin lightning-common classic/1.0 chrome/skin/lightning-common/
 % style chrome://global/content/customizeToolbar.xul chrome://lightning/skin/lightning-toolbar.css
 % style chrome://calendar/content/calendar-event-dialog.xul chrome://communicator/skin/communicator.css application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
 % style chrome://global/content/customizeToolbar.xul chrome://lightning-common/skin/lightning.css application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
 % style chrome://global/content/customizeToolbar.xul chrome://calendar-common/skin/dialogs/calendar-event-dialog.css application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
--- a/calendar/lightning/themes/linux/lightning.css
+++ b/calendar/lightning/themes/linux/lightning.css
@@ -100,17 +100,16 @@ radio[pane=paneLightning] {
     -moz-image-region: rect(0px 80px 16px 64px);
 }
 
 .icon-holder[type="tasks"][selected="true"],
 .tabmail-tab[type="tasks"][selected="true"] {
     -moz-image-region: rect(16px 80px 32px 64px);
 }
 
-
 /* Lightning sidebar in calendar and task mode */
 #ltnSidebar {
   background-color: -moz-field;
   border-bottom: 1px solid ThreeDShadow;
 }
 
 /* Write button */
 #newMsgButton-mail-menuitem {
--- a/calendar/test/mozmill/testLocalICS.js
+++ b/calendar/test/mozmill/testLocalICS.js
@@ -44,24 +44,25 @@ var testLocalICS = function () {
   modalDialog.wait_for_modal_dialog("Calendar:NewCalendarWizard", TIMEOUT_MODAL_DIALOG);
   
   // create new event
   controller.doubleClick(new elementslib.Lookup(controller.window.document,
     calUtils.getEventBoxPath(controller, "day", calUtils.CANVAS_BOX, undefined, 1, hour)), 1, 1);
   controller.waitFor(function() {return mozmill.utils.getWindows("Calendar:EventDialog").length > 0}, sleep);
   let event = new mozmill.controller.MozMillController(mozmill.utils
     .getWindows("Calendar:EventDialog")[0]);
-  
+
   // title
-  let titleTextBox = new elementslib.Lookup(event.window.document, '/id("calendar-event-dialog")/'
+  let iframe = event.window.document.getElementById("lightning-item-panel-iframe");
+  let titleTextBox = new elementslib.Lookup(iframe.contentDocument, '/id("calendar-event-dialog-inner")/'
     + 'id("event-grid")/id("event-grid-rows")/id("event-grid-title-row")/'
     + 'id("item-title")/anon({"class":"textbox-input-box"})/anon({"anonid":"input"})');
   event.waitForElement(titleTextBox);
   event.type(titleTextBox, title);
-  
+
   // set calendar
   let itemCalendar = new elementslib.ID(event.window.document, "item-calendar")
   event.select(itemCalendar, undefined, calendar);
   // HACK - Wait for the value to be selected. This is needed for platforms
   // like mac where selecting the menuitem is an asynchronous process, it might
   // be fixed in a later version of mozmill.
   event.waitFor(() => itemCalendar.getNode().value == calendar);
   
--- a/calendar/test/mozmill/testTodayPane.js
+++ b/calendar/test/mozmill/testTodayPane.js
@@ -24,17 +24,17 @@ var testTodayPane = function () {
   let panels = '/id("messengerWindow")/id("tabmail-container")/id("tabmail")/'
     + 'id("tabpanelcontainer")/';
   let miniMonth = panels + 'id("calendarTabPanel")/id("calendarContent")/id("ltnSidebar")/'
     + 'id("minimonth-pane")/';
   let dayView = panels + 'id("calendarTabPanel")/id("calendarContent")/id("calendarDisplayDeck")/'
     + 'id("calendar-view-box")/id("view-deck")/id("day-view")/';
   let dayPath = dayView + 'anon({"anonid":"mainbox"})/anon({"anonid":"labelbox"})/'
     + 'anon({"anonid":"labeldaybox"})/{"flex":"1"}';
-  let eventName = '/id("calendar-event-dialog")/id("event-grid")/id("event-grid-rows")/'
+  let eventName = '/id("calendar-event-dialog-inner")/id("event-grid")/id("event-grid-rows")/'
     + 'id("event-grid-title-row")/id("item-title")/anon({"class":"textbox-input-box"})/'
     + 'anon({"anonid":"input"})';
 
   // open calendar view
   controller.click(new elementslib.ID(controller.window.document, "calendar-tab-button"));
   controller.waitThenClick(new elementslib.ID(controller.window.document, "calendar-day-view-button"));
 
   // go to today and verify date
@@ -55,53 +55,56 @@ var testTodayPane = function () {
     view.scrollToMinute(60 * startHour);
 
   controller.doubleClick(new elementslib.Lookup(controller.window.document, dayView
     + 'anon({"anonid":"mainbox"})/anon({"anonid":"scrollbox"})/anon({"anonid":"daybox"})/'
     + '{"class":"calendar-event-column-even"}/anon({"anonid":"boxstack"})/'
     + 'anon({"anonid":"bgbox"})/[' + startHour + ']'), 1, 1);
   controller.waitFor(function() {return mozmill.utils.getWindows("Calendar:EventDialog").length > 0}, WAIT_FOR_WINDOW_TIMEOUT);
   let event = new mozmill.controller.MozMillController(mozmill.utils.getWindows("Calendar:EventDialog")[0]);
+  let iframe = event.window.document.getElementById("lightning-item-panel-iframe");
 
-  event.waitForElement(new elementslib.Lookup(event.window.document, eventName));
-  event.type(new elementslib.Lookup(event.window.document, eventName),"Today's Event");
+  event.waitForElement(new elementslib.Lookup(iframe.contentDocument, eventName));
+  event.type(new elementslib.Lookup(iframe.contentDocument, eventName),"Today's Event");
   event.click(new elementslib.ID(event.window.document, "button-save"));
   controller.waitFor(function() {return mozmill.utils.getWindows("Calendar:EventDialog").length == 0});
 
   // reset view
   view.scrollToMinute(60 * 8);
 
   // go to tomorrow and add an event
   controller.click(new elementslib.ID(controller.window.document, "next-view-button"));
   controller.doubleClick(new elementslib.Lookup(controller.window.document, dayView
     + 'anon({"anonid":"mainbox"})/anon({"anonid":"scrollbox"})/anon({"anonid":"daybox"})/'
     + '{"class":"calendar-event-column-even"}/anon({"anonid":"boxstack"})/'
     + 'anon({"anonid":"bgbox"})/[9]'), 1, 1);
   controller.waitFor(function() {return mozmill.utils.getWindows("Calendar:EventDialog").length > 0}, WAIT_FOR_WINDOW_TIMEOUT);
   event = new mozmill.controller.MozMillController(mozmill.utils.getWindows("Calendar:EventDialog")[0]);
+  iframe = event.window.document.getElementById("lightning-item-panel-iframe");
 
-  event.waitForElement(new elementslib.Lookup(event.window.document, eventName));
-  event.type(new elementslib.Lookup(event.window.document, eventName),"Tomorrow's Event");
+  event.waitForElement(new elementslib.Lookup(iframe.contentDocument, eventName));
+  event.type(new elementslib.Lookup(iframe.contentDocument, eventName),"Tomorrow's Event");
   event.click(new elementslib.ID(event.window.document, "button-save"));
   controller.waitFor(function() {return mozmill.utils.getWindows("Calendar:EventDialog").length == 0});
 
   // go 5 days forward and add an event
   for(let i = 0; i < 5; i++)
     controller.click(new elementslib.ID(controller.window.document, "next-view-button"));
   controller.sleep(WAIT_FOR_WINDOW_TIMEOUT);
 
   controller.doubleClick(new elementslib.Lookup(controller.window.document, dayView
     + 'anon({"anonid":"mainbox"})/anon({"anonid":"scrollbox"})/anon({"anonid":"daybox"})/'
     + '{"class":"calendar-event-column-even"}/anon({"anonid":"boxstack"})/'
     + 'anon({"anonid":"bgbox"})/[9]'), 1, 1);
   controller.waitFor(function() {return mozmill.utils.getWindows("Calendar:EventDialog").length > 0}, WAIT_FOR_WINDOW_TIMEOUT);
   event = new mozmill.controller.MozMillController(mozmill.utils.getWindows("Calendar:EventDialog")[0]);
+  iframe = event.window.document.getElementById("lightning-item-panel-iframe");
 
-  event.waitForElement(new elementslib.Lookup(event.window.document, eventName));
-  event.type(new elementslib.Lookup(event.window.document, eventName),"Future's Event");
+  event.waitForElement(new elementslib.Lookup(iframe.contentDocument, eventName));
+  event.type(new elementslib.Lookup(iframe.contentDocument, eventName),"Future's Event");
   event.click(new elementslib.ID(event.window.document, "button-save"));
   controller.waitFor(function() {return mozmill.utils.getWindows("Calendar:EventDialog").length == 0});
 
   // go to mail tab
   controller.click(new elementslib.Lookup(controller.window.document, '/id("messengerWindow")/'
     + 'id("navigation-toolbox")/id("tabs-toolbar")/id("tabcontainer")/{"first-tab":"true","type":"folder"}/'
     + 'anon({"class":"tab-stack"})/{"class":"tab-background"}/{"class":"tab-background-middle"}'));
   controller.sleep(WAIT_FOR_WINDOW_TIMEOUT);