Bug 1343707 - Make datetimepopup.xml binding attach lazily. r=mconley draft
authorScott Wu <scottcwwu@gmail.com>
Fri, 03 Mar 2017 13:58:53 +0800
changeset 499692 527a29f4057407eb745961857041635c27a2ac73
parent 499512 ff04d410e74b69acfab17ef7e73e7397602d5a68
child 549420 8ee611074fcfd0176853dc13181c505ac2136a16
push id49482
push userbmo:scwwu@mozilla.com
push dateThu, 16 Mar 2017 03:24:14 +0000
reviewersmconley
bugs1343707
milestone55.0a1
Bug 1343707 - Make datetimepopup.xml binding attach lazily. r=mconley MozReview-Commit-ID: C7LnrxIbU3K
browser/base/content/browser.css
toolkit/content/widgets/datetimepopup.xml
toolkit/modules/DateTimePickerHelper.jsm
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -567,17 +567,17 @@ toolbar:not(#TabsToolbar) > #personal-bo
 #PopupAutoCompleteRichResult > richlistbox {
   transition: height 100ms;
 }
 
 #PopupAutoCompleteRichResult.showSearchSuggestionsNotification > richlistbox {
   transition: none;
 }
 
-#DateTimePickerPanel {
+#DateTimePickerPanel[active="true"] {
   -moz-binding: url("chrome://global/content/bindings/datetimepopup.xml#datetime-popup");
 }
 
 #urlbar[pageproxystate="invalid"] > #urlbar-icons > .urlbar-icon,
 #urlbar[pageproxystate="invalid"][focused="true"] > #urlbar-go-button ~ toolbarbutton,
 #urlbar[pageproxystate="valid"] > #urlbar-go-button,
 #urlbar:not([focused="true"]) > #urlbar-go-button {
   visibility: collapse;
--- a/toolkit/content/widgets/datetimepopup.xml
+++ b/toolkit/content/widgets/datetimepopup.xml
@@ -20,16 +20,18 @@
       </field>
       <field name="TIME_PICKER_WIDTH" readonly="true">"12em"</field>
       <field name="TIME_PICKER_HEIGHT" readonly="true">"21em"</field>
       <field name="DATE_PICKER_WIDTH" readonly="true">"23.1em"</field>
       <field name="DATE_PICKER_HEIGHT" readonly="true">"20.7em"</field>
       <constructor><![CDATA[
         this.mozIntl = Components.classes["@mozilla.org/mozintl;1"]
                                  .getService(Components.interfaces.mozIMozIntl);
+        // Notify DateTimePickerHelper.jsm that binding is ready.
+        this.dispatchEvent(new CustomEvent("DateTimePickerBindingReady"));
       ]]></constructor>
       <method name="loadPicker">
         <parameter name="type"/>
         <parameter name="detail"/>
         <body><![CDATA[
           this.hidden = false;
           this.type = type;
           this.pickerState = {};
--- a/toolkit/modules/DateTimePickerHelper.jsm
+++ b/toolkit/modules/DateTimePickerHelper.jsm
@@ -16,16 +16,17 @@ function debug(aStr) {
 }
 
 this.EXPORTED_SYMBOLS = [
   "DateTimePickerHelper"
 ];
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
 
 /*
  * DateTimePickerHelper receives message from content side (input box) and
  * is reposible for opening, closing and updating the picker. Similary,
  * DateTimePickerHelper listens for picker's events and notifies the content
  * side (input box) about them.
  */
 this.DateTimePickerHelper = {
@@ -100,17 +101,17 @@ this.DateTimePickerHelper = {
     let browser = this.weakBrowser ? this.weakBrowser.get() : null;
     if (browser) {
       browser.messageManager.sendAsyncMessage(
         "FormDateTime:PickerValueChanged", aEvent.detail);
     }
   },
 
   // Get picker from browser and show it anchored to the input box.
-  showPicker(aBrowser, aData) {
+  showPicker: Task.async(function* (aBrowser, aData) {
     let rect = aData.rect;
     let type = aData.type;
     let detail = aData.detail;
 
     this._anchor = aBrowser.ownerGlobal.gBrowser.popupAnchor;
     this._anchor.left = rect.left;
     this._anchor.top = rect.top;
     this._anchor.width = rect.width;
@@ -129,23 +130,34 @@ this.DateTimePickerHelper = {
     }
 
     this.weakBrowser = Cu.getWeakReference(aBrowser);
     this.picker = aBrowser.dateTimePicker;
     if (!this.picker) {
       debug("aBrowser.dateTimePicker not found, exiting now.");
       return;
     }
+    // The datetimepopup binding is only attached when it is needed.
+    // Check if loadPicker method is present to determine if binding has
+    // been attached. If not, attach the binding first before calling it.
+    if (!this.picker.loadPicker) {
+      let bindingPromise = new Promise(resolve => {
+        this.picker.addEventListener("DateTimePickerBindingReady",
+                                     resolve, {once: true});
+      });
+      this.picker.setAttribute("active", true);
+      yield bindingPromise;
+    }
     this.picker.loadPicker(type, detail);
     // The arrow panel needs an anchor to work. The popupAnchor (this._anchor)
     // is a transparent div that the arrow can point to.
     this.picker.openPopup(this._anchor, "after_start", 0, 0);
 
     this.addPickerListeners();
-  },
+  }),
 
   // Picker is closed, do some cleanup.
   close() {
     this.removePickerListeners();
     this.picker = null;
     this.weakBrowser = null;
     this._anchor.hidden = true;
   },