Bug 807956 - Event window: Early end date warning locks event edit window. (2nd patch) r=philipp
authorDecathlon <bv1578@gmail.com>
Mon, 11 Feb 2013 15:51:12 +0100
changeset 14849 db8918e7990795c2259c6f6cfe08fa8dbee0ad68
parent 14848 61c46ff57276dfa23155b94c346cef480fdcc44f
child 14850 13c3733f053f99a2071e2f10cabdb0f5637c26e7
push id867
push userbugzilla@standard8.plus.com
push dateMon, 01 Apr 2013 20:44:27 +0000
treeherdercomm-beta@797726b8d244 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilipp
bugs807956
Bug 807956 - Event window: Early end date warning locks event edit window. (2nd patch) r=philipp
calendar/base/content/dialogs/calendar-event-dialog.js
calendar/resources/content/datetimepickers/datetimepickers.xml
--- a/calendar/base/content/dialogs/calendar-event-dialog.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog.js
@@ -633,28 +633,30 @@ function dateTimeControls2State(aStartDa
             gStartTime = saveStartTime;
             gEndTime = saveEndTime;
             warning = true;
         }
     }
 
     updateDateTime();
     updateTimezone();
+    updateAccept();
 
     if (warning) {
+        // Disable the "Save" and "Save and Close" commands as long as the
+        // warning dialog is showed.
+        enableAcceptCommand(false);
         gWarning = true;
-        var callback = function func() {
-            enableAcceptCommand(false);
-            Services.prompt.alert(
-                null,
-                document.title,
-                calGetString("calendar", "warningEndBeforeStart"));
+        let callback = function func() {
+            Services.prompt.alert(null,
+                                  document.title,
+                                  cal.calGetString("calendar", "warningEndBeforeStart"));
             gWarning = false;
-            enableAcceptCommand(true);
-        }
+            updateAccept();
+        };
         setTimeout(callback, 1);
     }
 }
 
 /**
  * Updates the entry date checkboxes, used for example when choosing an alarm:
  * the entry date needs to be checked in that case.
  */
@@ -1151,27 +1153,25 @@ function updateAccept() {
         enableAccept = false;
     }
 
     enableAcceptCommand(enableAccept);
 
     return enableAccept;
 }
 
-/* Enables/disables the cmd_accept command related to the save operation
+/**
+ * Enables/disables the commands cmd_accept and cmd_save related to the
+ * save operation.
  *
  * @param aEnable           true: enables the command
  */
 function enableAcceptCommand(aEnable) {
-    let accept = document.getElementById("cmd_accept");
-    if (aEnable) {
-        accept.removeAttribute('disabled');
-    } else {
-        accept.setAttribute('disabled', 'true');
-    }
+    setElementValue("cmd_accept", !aEnable, "disabled");
+    setElementValue("cmd_save", !aEnable, "disabled");
 }
 
 // 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;
@@ -3232,17 +3232,17 @@ function updateAttendees() {
                 continue;
             }
         }
 
         let attendeeList = document.getElementById("attendee-list");
         let callback = function func() {
             attendeeList.setAttribute('value', attendeeNames.join(', '));
             attendeeList.setAttribute('tooltiptext', attendeeEmails.join(', '));
-        }
+        };
         setTimeout(callback, 1);
     } else {
         attendeeRow.setAttribute('collapsed', 'true');
         attendeeRow2.setAttribute('collapsed', 'true');
     }
 }
 
 /**
@@ -3493,28 +3493,31 @@ function capValues(aCap, aDefault) {
 function checkUntilDate() {
     let repeatUntilDate = getElementValue("repeat-until-datepicker");
     if (repeatUntilDate == "forever") {
         updateRepeat();
         // "forever" is never earlier than another date.
         return;
     }
 
+    // The "time" part of the until date will be correctly assigned in the
+    // updateRepeat() function, but here we need to check only the date.
     let untilDate = cal.jsDateToDateTime(repeatUntilDate, gStartTime.timezone);
     let startDate = gStartTime.clone();
     startDate.isDate = true;
     if (untilDate.compare(startDate) < 0) {
         // Restore the previous date. Since we are checking an until date,
         // a null value for gUntilDate means repeat "forever".
         setElementValue("repeat-until-datepicker",
                         gUntilDate ? gUntilDate.getInTimezone(cal.floating()).jsDate
                                    : "forever");
         gWarning = true;
         let callback = function() {
-            // Disable the "Save" button until the warning dialog is showed
+            // Disable the "Save" and "Save and Close" commands as long as the
+            // warning dialog is showed.
             enableAcceptCommand(false);
 
             Services.prompt.alert(
                 null,
                 document.title,
                 calGetString("calendar", "warningUntilBeforeStart"));
             enableAcceptCommand(true);
             gWarning = false;
--- a/calendar/resources/content/datetimepickers/datetimepickers.xml
+++ b/calendar/resources/content/datetimepickers/datetimepickers.xml
@@ -234,17 +234,17 @@
          node that interferes with navigation to interior nodes.] -->
     <resources>
       <stylesheet src="chrome://calendar/content/widgets/calendar-widget-bindings.css"/>
     </resources>               
     <content>
       <xul:hbox flex="1" id="hbox" class="datepicker-box-class">
         <xul:menulist editable="true" sizetopopup="false"
                       class="datepicker-text-class"
-                      onchange="this.kDatePicker.parseTextBoxDate(true);"
+                      onchange="this.kDatePicker.parseTextBoxDate(true, event);"
                       onkeypress="if (event.keyCode == 13) this.kDatePicker.parseTextBoxDate(true);"
                       xbl:inherits="disabled">
           <xul:menupopup popupanchor="bottomright" popupalign="topright"
                          anonid="datepopup"
                          onpopupshowing="this.parentNode.kDatePicker.onPopup();"
                          onpopuphiding="this.firstChild.hidePopupList();">
             <xul:minimonth/>
           </xul:menupopup>
@@ -335,18 +335,24 @@
             // select all to remove cursor since can't type while popped-up
             this.select();
           ]]>
         </body>
       </method>
 
       <method name="parseTextBoxDate">
         <parameter name="aRefresh"/>
+        <parameter name="aEvent"/>
         <body>
           <![CDATA[
+            // Stop the "change" event propagation. It will be properly
+            // fired inside the update method.
+            if (aEvent) {
+                aEvent.stopPropagation();
+            }
             this.update(this.parseDateTime(this.kTextBox.value), aRefresh);
             this.lastDateParseIncludedTime = false;
           ]]>
         </body>
       </method>
 
       <method name="select">
         <body>
@@ -389,17 +395,17 @@
 
   </binding>
 
   <binding id="datepicker-forever" extends="chrome://calendar/content/datetimepickers/datetimepickers.xml#datepicker">
     <content>
       <xul:hbox flex="1" id="hbox" class="datepicker-box-class">
         <xul:menulist anonid="foreverMenulist" editable="true" sizetopopup="false"
                       class="datepicker-text-class"
-                      onchange="this.kDatePicker.parseTextBoxDate(true);"
+                      onchange="this.kDatePicker.parseTextBoxDate(true, event);"
                       onkeypress="if (event.keyCode == 13) this.kDatePicker.parseTextBoxDate(true);"
                       xbl:inherits="disabled">
           <xul:menupopup popupanchor="bottomright" popupalign="topright"
                          anonid="datepopup"
                          onpopupshowing="this.parentNode.kDatePicker.onPopup();"
                          onpopuphiding="this.firstChild.hidePopupList();">
             <xul:minimonth/>
             <xul:menuseparator/>
@@ -419,22 +425,28 @@
           this.mForeverStr = calGetString("calendar-event-dialog", "eventRecurrenceForeverLabel");
           document.getAnonymousElementByAttribute(this, "anonid", "menuitemForever")
               .setAttribute("label", this.mForeverStr);
         ]]>
       </constructor>
 
       <method name="parseTextBoxDate">
         <parameter name="aRefresh"/>
+        <parameter name="aEvent"/>
         <body>
           <![CDATA[
             if (this.kTextBox.value.toLowerCase() == this.mForeverStr.toLowerCase()) {
                 this.mValue = "forever";
                 this.kTextBox.value = this.mForeverStr;
             } else {
+                // Stop the "change" event propagation. It will be properly
+                // fired inside the update method.
+                if (aEvent) {
+                    aEvent.stopPropagation();
+                }
                 let date = this.parseDateTime(this.kTextBox.value);
                 if (date) {
                     this.update(date, aRefresh);
                 } else {
                     // Invalid date, revert to previous date.
                     this.kTextBox.value = (this.mValue == "forever") ? this.mForeverStr
                                                                      : this.formatDate(this.mValue);
                 }
@@ -536,17 +548,17 @@
          So navigate parents to textbox in order to call parseTextBoxTime.
          [this comment is outside the <content> so it won't become a
          node that interferes with navigation to interior nodes.] -->
     <content>
       <xul:hbox flex="1" id="hbox" class="timepicker-box-class">
         <xul:menulist editable="true" sizetopopup="false"
                       id="timepicker-text"
                       class="timepicker-text-class"
-                      onchange="this.kTimePicker.parseTextBoxTime(true);"
+                      onchange="this.kTimePicker.parseTextBoxTime(true, event);"
                       onkeypress="if (event.keyCode == 13) this.kTimePicker.parseTextBoxTime(true);"
                       xbl:inherits="disabled">
           <xul:menupopup popupalign="topright" popupanchor="bottomright"
                          onpopupshowing="onPopup(this)"
                          onpopuphiding="onHide(this)">
             <xul:timepicker-grids />
           </xul:menupopup>
         </xul:menulist>
@@ -569,36 +581,47 @@
         ]]>
       </constructor>
       
       <method name="update">
         <parameter name="aValue"/>
         <parameter name="aRefresh"/>
         <body>
           <![CDATA[
+            let timeChanged = false;
             if (aValue != null) {
+              if (this.mValue) {
+                timeChanged = this.mValue.getHours() != aValue.getHours() ||
+                              this.mValue.getMinutes() != aValue.getMinutes();
+              }
               this.mValue = aValue;
             }
             // set textBox.value property, not attribute
             this.kTextBox.value = this.formatTime(this.mValue);
 
-            if (aValue != null && aRefresh) {
-              var event = document.createEvent('Events');
+            if (aValue != null && aRefresh && timeChanged) {
+              let event = document.createEvent('Events');
               event.initEvent("change", true, true);
               this.dispatchEvent(event);;
             }
           ]]>
         </body>
       </method>
 
       <method name="parseTextBoxTime">
         <parameter name="aRefresh"/>
+        <parameter name="aEvent"/>
         <body>
           <![CDATA[
-            var time = this.parseTime(this.kTextBox.value);
+            // Stop the "change" event propagation. It will be properly
+            // fired inside the update method.
+            if (aEvent) {
+              aEvent.stopPropagation();
+            }
+            let time = this.parseTime(this.kTextBox.value);
             this.update(time, aRefresh);
             return time;
           ]]>
         </body>
       </method>
 
       <method name="onPopup">
         <parameter name="aPopup" />
@@ -1424,33 +1447,31 @@
             var dateTime = new Date(newDate.getFullYear(),
                                     newDate.getMonth(),
                                     newDate.getDate(),
                                     tempTime.getHours(),
                                     tempTime.getMinutes(),
                                     tempTime.getSeconds());
             this.mValue = dateTime;
             this.kTimePicker.update(dateTime, false);
-            this.fireEvent("change");
           ]]>
         </body>
       </method>
 
       <!-- Time was changed by gui: update value -->
       <method name="onTimePick">
         <body>
           <![CDATA[
             var dateTime = new Date(this.mValue);
             var newTime = this.kTimePicker.value;
             dateTime.setHours(newTime.getHours());
             dateTime.setMinutes(newTime.getMinutes());
             dateTime.setSeconds(newTime.getSeconds());
             this.mValue = dateTime;
             this.kDatePicker.update(dateTime, false);
-            this.fireEvent("change");
           ]]>
         </body>
       </method>
 
     </implementation>
 
     <!-- ::::::::::::::::: HANDLERS ::::::::::::::::::::::::: -->