Bug 1178462 - Cancel inplace editor autocomplete on window blur;r=gl draft
authorJulian Descottes <jdescottes@mozilla.com>
Wed, 27 Apr 2016 09:55:18 +0200
changeset 356816 66336aebbfc117ba438493d804c3656dd50f5ed0
parent 356074 0f07f975526f3abda2f997bbb2feb0a25f771227
child 519491 24a61424a585eab269b8372537b7054ec7e7dd74
push id16609
push userjdescottes@mozilla.com
push dateWed, 27 Apr 2016 07:57:45 +0000
reviewersgl
bugs1178462
milestone48.0a1
Bug 1178462 - Cancel inplace editor autocomplete on window blur;r=gl MozReview-Commit-ID: BI9LHtUKta
devtools/client/shared/inplace-editor.js
--- a/devtools/client/shared/inplace-editor.js
+++ b/devtools/client/shared/inplace-editor.js
@@ -232,16 +232,17 @@ function InplaceEditor(options, event) {
   this.contentType = options.contentType || CONTENT_TYPES.PLAIN_TEXT;
   this.property = options.property;
   this.popup = options.popup;
   this.preserveTextStyles = options.preserveTextStyles === undefined
                           ? false
                           : !!options.preserveTextStyles;
 
   this._onBlur = this._onBlur.bind(this);
+  this._onWindowBlur = this._onWindowBlur.bind(this);
   this._onKeyPress = this._onKeyPress.bind(this);
   this._onInput = this._onInput.bind(this);
   this._onKeyup = this._onKeyup.bind(this);
 
   this._createInput();
 
   // Hide the provided element and add our editor.
   this.originalDisplay = this.elt.style.display;
@@ -276,16 +277,17 @@ function InplaceEditor(options, event) {
   }
 
   this.input.addEventListener("blur", this._onBlur, false);
   this.input.addEventListener("keypress", this._onKeyPress, false);
   this.input.addEventListener("input", this._onInput, false);
   this.input.addEventListener("dblclick", this._stopEventPropagation, false);
   this.input.addEventListener("click", this._stopEventPropagation, false);
   this.input.addEventListener("mousedown", this._stopEventPropagation, false);
+  this.doc.defaultView.addEventListener("blur", this._onWindowBlur, false);
 
   this.validate = options.validate;
 
   if (this.validate) {
     this.input.addEventListener("keyup", this._onKeyup, false);
   }
 
   this._updateSize();
@@ -339,16 +341,17 @@ InplaceEditor.prototype = {
     this.input.removeEventListener("keypress", this._onKeyPress, false);
     this.input.removeEventListener("keyup", this._onKeyup, false);
     this.input.removeEventListener("input", this._onInput, false);
     this.input.removeEventListener("dblclick", this._stopEventPropagation,
       false);
     this.input.removeEventListener("click", this._stopEventPropagation, false);
     this.input.removeEventListener("mousedown", this._stopEventPropagation,
       false);
+    this.doc.defaultView.removeEventListener("blur", this._onWindowBlur, false);
 
     this._stopAutosize();
 
     this.elt.style.display = this.originalDisplay;
 
     if (this.doc.activeElement == this.input) {
       this.elt.focus();
     }
@@ -917,16 +920,29 @@ InplaceEditor.prototype = {
       let val = this.cancelled ? this.initial : this.currentInputValue;
       return this.done(val, !this.cancelled, direction);
     }
 
     return null;
   },
 
   /**
+   * Hide the popup and cancel any pending popup opening.
+   */
+  _onWindowBlur: function() {
+    if (this.popup && this.popup.isOpen) {
+      this.popup.hidePopup();
+    }
+
+    if (this._openPopupTimeout) {
+      this.doc.defaultView.clearTimeout(this._openPopupTimeout);
+    }
+  },
+
+  /**
    * Handle loss of focus by calling done if it hasn't been called yet.
    */
   _onBlur: function(event) {
     if (event && this.popup && this.popup.isOpen &&
         this.popup.selectedIndex >= 0) {
       let label, preLabel;
 
       if (this._selectedIndex === undefined) {
@@ -1192,17 +1208,17 @@ InplaceEditor.prototype = {
     if (!this.input) {
       return;
     }
     let preTimeoutQuery = this.input.value;
 
     // Since we are calling this method from a keypress event handler, the
     // |input.value| does not include currently typed character. Thus we perform
     // this method async.
-    this.doc.defaultView.setTimeout(() => {
+    this._openPopupTimeout = this.doc.defaultView.setTimeout(() => {
       if (this._preventSuggestions) {
         this._preventSuggestions = false;
         return;
       }
       if (this.contentType == CONTENT_TYPES.PLAIN_TEXT) {
         return;
       }
       if (!this.input) {