Bug 1261317 - part1: inplace-editor: small refactor of keypress event handler;r=pbro
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 01 Apr 2016 17:44:39 +0200
changeset 291867 33d4c04cf572fecce5536c27f164753ba2a7e30f
parent 291866 c9e9878330240c437f0a3a2bca4cce608b5ef33f
child 291868 d37f13e88aae4ba2c69951189f3d88c723bfc9a7
push idunknown
push userunknown
push dateunknown
reviewerspbro
bugs1261317
milestone48.0a1
Bug 1261317 - part1: inplace-editor: small refactor of keypress event handler;r=pbro Refactor the keypress event handler to make it easier to read. MozReview-Commit-ID: 4yvlg7GIYMK
devtools/client/shared/inplace-editor.js
--- a/devtools/client/shared/inplace-editor.js
+++ b/devtools/client/shared/inplace-editor.js
@@ -38,16 +38,32 @@ const MAX_POPUP_ENTRIES = 10;
 const FOCUS_FORWARD = Ci.nsIFocusManager.MOVEFOCUS_FORWARD;
 const FOCUS_BACKWARD = Ci.nsIFocusManager.MOVEFOCUS_BACKWARD;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://devtools/shared/event-emitter.js");
 const { findMostRelevantCssPropertyIndex } = require("./suggestion-picker");
 
 /**
+ * Helper to check if the provided key matches one of the expected keys.
+ * Keys will be prefixed with DOM_VK_ and should match a key in nsIDOMKeyEvent.
+ *
+ * @param {String} key
+ *        the key to check (can be a keyCode).
+ * @param {...String} keys
+ *        list of possible keys allowed.
+ * @return {Boolean} true if the key matches one of the keys.
+ */
+function isKeyIn(key, ...keys) {
+  return keys.some(expectedKey => {
+    return key === Ci.nsIDOMKeyEvent["DOM_VK_" + expectedKey];
+  });
+}
+
+/**
  * Mark a span editable.  |editableField| will listen for the span to
  * be focused and create an InlineEditor to handle text input.
  * Changes will be committed when the InlineEditor's input is blurred
  * or dropped when the user presses escape.
  *
  * @param {Object} options
  *    Options for the editable field, including:
  *    {Element} element:
@@ -137,18 +153,17 @@ function editableItem(options, callback)
       }
       evt.stopPropagation();
     }
   }, false);
 
   // If focused by means other than a click, start editing by
   // pressing enter or space.
   element.addEventListener("keypress", function(evt) {
-    if (evt.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN ||
-        evt.charCode === Ci.nsIDOMKeyEvent.DOM_VK_SPACE) {
+    if (isKeyIn(evt.keyCode, "RETURN") || isKeyIn(evt.charCode, "SPACE")) {
       callback(element);
     }
   }, true);
 
   // Ugly workaround - the element is focused on mousedown but
   // the editor is activated on click/mouseup.  This leads
   // to an ugly flash of the focus ring before showing the editor.
   // So hide the focus ring while the mouse is down.
@@ -963,89 +978,78 @@ InplaceEditor.prototype = {
   },
 
   /**
    * Handle the input field's keypress event.
    */
   _onKeyPress: function(event) {
     let prevent = false;
 
+    let key = event.keyCode;
+    let input = this.input;
+
     let isPlainText = this.contentType == CONTENT_TYPES.PLAIN_TEXT;
-    let increment = isPlainText ? 0 : this._getIncrement(event);
 
-    // Use default cursor movement rather than providing auto-suggestions.
-    if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_HOME ||
-        event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_END ||
-        event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP ||
-        event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
+    let increment = 0;
+    if (!isPlainText) {
+      increment = this._getIncrement(event);
+    }
+
+    if (isKeyIn(key, "HOME", "END", "PAGE_UP", "PAGE_DOWN")) {
       this._preventSuggestions = true;
     }
 
     let cycling = false;
     if (increment && this._incrementValue(increment)) {
       this._updateSize();
       prevent = true;
       cycling = true;
     } else if (increment && this.popup && this.popup.isOpen) {
+      prevent = true;
       cycling = true;
-      prevent = true;
       this._cycleCSSSuggestion(increment > 0);
       this._doValidation();
     }
 
-    if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_BACK_SPACE ||
-        event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_DELETE ||
-        event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_LEFT ||
-        event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RIGHT) {
+    if (isKeyIn(key, "BACK_SPACE", "DELETE", "LEFT", "RIGHT")) {
       if (this.popup && this.popup.isOpen) {
         this.popup.hidePopup();
       }
     } else if (!cycling && !event.metaKey && !event.altKey && !event.ctrlKey) {
       this._maybeSuggestCompletion(true);
     }
 
-    if (this.multiline &&
-        event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN &&
-        event.shiftKey) {
+    if (this.multiline && event.shiftKey && isKeyIn(key, "RETURN")) {
       prevent = false;
-    } else if (this._advanceChars(event.charCode, this.input.value,
-                                  this.input.selectionStart) ||
-               event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN ||
-               event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB) {
+    } else if (
+      this._advanceChars(event.charCode, input.value, input.selectionStart) ||
+      isKeyIn(key, "RETURN", "TAB")) {
       prevent = true;
 
-      let direction = FOCUS_FORWARD;
-      if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
-          event.shiftKey) {
-        if (this.stopOnShiftTab) {
-          direction = null;
-        } else {
-          direction = FOCUS_BACKWARD;
-        }
-      }
-      if ((this.stopOnReturn &&
-           event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_RETURN) ||
-          (this.stopOnTab && event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
-           !event.shiftKey)) {
+      let direction;
+      if ((this.stopOnReturn && isKeyIn(key, "RETURN")) ||
+          (this.stopOnTab && !event.shiftKey && isKeyIn(key, "TAB")) ||
+          (this.stopOnShiftTab && event.shiftKey && isKeyIn(key, "TAB"))) {
         direction = null;
+      } else if (event.shiftKey && isKeyIn(key, "TAB")) {
+        direction = FOCUS_BACKWARD;
+      } else {
+        direction = FOCUS_FORWARD;
       }
 
       // Now we don't want to suggest anything as we are moving out.
       this._preventSuggestions = true;
       // But we still want to show suggestions for css values. i.e. moving out
       // of css property input box in forward direction
       if (this.contentType == CONTENT_TYPES.CSS_PROPERTY &&
           direction == FOCUS_FORWARD) {
         this._preventSuggestions = false;
       }
 
-      let input = this.input;
-
-      if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_TAB &&
-          this.contentType == CONTENT_TYPES.CSS_MIXED) {
+      if (isKeyIn(key, "TAB") && this.contentType == CONTENT_TYPES.CSS_MIXED) {
         if (this.popup && input.selectionStart < input.selectionEnd) {
           event.preventDefault();
           input.setSelectionRange(input.selectionEnd, input.selectionEnd);
           this.emit("after-suggest");
           return;
         } else if (this.popup && this.popup.isOpen) {
           event.preventDefault();
           this._cycleCSSSuggestion(event.shiftKey, true);
@@ -1070,62 +1074,60 @@ InplaceEditor.prototype = {
         if (next && next.ownerDocument === this.doc && next._editable) {
           let e = this.doc.createEvent("Event");
           e.initEvent(next._trigger, true, true);
           next.dispatchEvent(e);
         }
       }
 
       this._clear();
-    } else if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE) {
+    } else if (isKeyIn(key, "ESCAPE")) {
       // Cancel and blur ourselves.
       // Now we don't want to suggest anything as we are moving out.
       this._preventSuggestions = true;
       // Close the popup if open
       if (this.popup && this.popup.isOpen) {
         this.popup.hidePopup();
       }
       prevent = true;
       this.cancelled = true;
       this._apply();
       this._clear();
       event.stopPropagation();
-    } else if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_SPACE) {
+    } else if (isKeyIn(key, "SPACE")) {
       // No need for leading spaces here.  This is particularly
       // noticable when adding a property: it's very natural to type
       // <name>: (which advances to the next property) then spacebar.
-      prevent = !this.input.value;
+      prevent = !input.value;
     }
 
     if (prevent) {
       event.preventDefault();
     }
   },
 
   /**
    * Get the increment/decrement step to use for the provided key event.
    */
   _getIncrement: function(event) {
     const largeIncrement = 100;
     const mediumIncrement = 10;
     const smallIncrement = 0.1;
 
     let increment = 0;
+    let key = event.keyCode;
 
-    if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_UP ||
-        event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP) {
+    if (isKeyIn(key, "UP", "PAGE_UP")) {
       increment = 1;
-    } else if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_DOWN ||
-               event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
+    } else if (isKeyIn(key, "DOWN", "PAGE_DOWN")) {
       increment = -1;
     }
 
     if (event.shiftKey && !event.altKey) {
-      if (event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP ||
-          event.keyCode === Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN) {
+      if (isKeyIn(key, "PAGE_UP", "PAGE_DOWN")) {
         increment *= largeIncrement;
       } else {
         increment *= mediumIncrement;
       }
     } else if (event.altKey && !event.shiftKey) {
       increment *= smallIncrement;
     }