Bug 1517507 - Part 4 - Move the editing code to the PrefRow class. r=bgrins
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Tue, 08 Jan 2019 11:48:41 +0000
changeset 510010 14e4487e1c6b6fbee0e3c617219d1dae18a15bdb
parent 510009 13e4170bccb10d6d69fb9d69bbe75eda75017557
child 510011 3d09512072a5b37eb90f38a9490f89264be90356
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1517507
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1517507 - Part 4 - Move the editing code to the PrefRow class. r=bgrins Differential Revision: https://phabricator.services.mozilla.com/D15665
browser/components/aboutconfig/content/aboutconfig.js
--- a/browser/components/aboutconfig/content/aboutconfig.js
+++ b/browser/components/aboutconfig/content/aboutconfig.js
@@ -2,26 +2,27 @@
  * 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/. */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/Preferences.jsm");
 
 let gDefaultBranch = Services.prefs.getDefaultBranch("");
 let gPrefArray;
-let gPrefInEdit;
+let gPrefInEdit = null;
 
 class PrefRow {
   constructor(name) {
     this.name = name;
     this.refreshValue();
 
+    this.editing = false;
     this.element = document.createElement("tr");
     this.element.setAttribute("aria-label", this.name);
-    this.rebuildElement();
+    this._setupElement();
   }
 
   refreshValue() {
     this.hasUserValue = Services.prefs.prefHasUserValue(this.name);
     this.hasDefaultValue = this.hasUserValue ? prefHasDefaultValue(this.name)
                                              : true;
     this.isLocked = Services.prefs.prefIsLocked(this.name);
 
@@ -36,17 +37,17 @@ class PrefRow {
         this.value = Services.prefs.getComplexValue(this.name,
           Ci.nsIPrefLocalizedString).data;
       }
     } catch (ex) {
       this.value = "";
     }
   }
 
-  rebuildElement() {
+  _setupElement() {
     this.element.textContent = "";
     let nameCell = document.createElement("td");
     this.element.append(
       nameCell,
       this.valueCell = document.createElement("td"),
       this.editCell = document.createElement("td"),
       this.resetCell = document.createElement("td")
     );
@@ -67,23 +68,49 @@ class PrefRow {
     nameCell.append(parts[parts.length - 1]);
 
     this.refreshElement();
   }
 
   refreshElement() {
     this.element.classList.toggle("has-user-value", !!this.hasUserValue);
     this.element.classList.toggle("locked", !!this.isLocked);
-    this.valueCell.textContent = this.value;
-    if (this.value.constructor.name == "Boolean") {
-      document.l10n.setAttributes(this.editButton, "about-config-pref-toggle");
-      this.editButton.className = "button-toggle";
+    if (!this.editing) {
+      this.valueCell.textContent = this.value;
+      if (this.value.constructor.name == "Boolean") {
+        document.l10n.setAttributes(this.editButton, "about-config-pref-toggle");
+        this.editButton.className = "button-toggle";
+      } else {
+        document.l10n.setAttributes(this.editButton, "about-config-pref-edit");
+        this.editButton.className = "button-edit";
+      }
+      this.editButton.removeAttribute("form");
+      delete this.inputField;
     } else {
-      document.l10n.setAttributes(this.editButton, "about-config-pref-edit");
-      this.editButton.className = "button-edit";
+      this.valueCell.textContent = "";
+      // The form is needed for the validation report to appear, but we need to
+      // prevent the associated button from reloading the page.
+      let form = document.createElement("form");
+      form.addEventListener("submit", event => event.preventDefault());
+      form.id = "form-edit";
+      this.inputField = document.createElement("input");
+      this.inputField.value = this.value;
+      if (this.value.constructor.name == "Number") {
+        this.inputField.type = "number";
+        this.inputField.required = true;
+        this.inputField.min = -2147483648;
+        this.inputField.max = 2147483647;
+      } else {
+        this.inputField.type = "text";
+      }
+      form.appendChild(this.inputField);
+      this.valueCell.appendChild(form);
+      document.l10n.setAttributes(this.editButton, "about-config-pref-save");
+      this.editButton.className = "primary button-save";
+      this.editButton.setAttribute("form", "form-edit");
     }
     this.editButton.disabled = this.isLocked;
     if (!this.isLocked && this.hasUserValue) {
       if (!this.resetButton) {
         this.resetButton = document.createElement("button");
         this.resetCell.appendChild(this.resetButton);
       }
       if (!this.hasDefaultValue) {
@@ -95,16 +122,46 @@ class PrefRow {
                                     "about-config-pref-reset");
         this.resetButton.className = "button-reset";
       }
     } else if (this.resetButton) {
       this.resetButton.remove();
       delete this.resetButton;
     }
   }
+
+  edit() {
+    if (gPrefInEdit) {
+      gPrefInEdit.endEdit();
+    }
+    gPrefInEdit = this;
+    this.editing = true;
+    this.refreshElement();
+    this.inputField.focus();
+  }
+
+  save() {
+    if (this.value.constructor.name == "Number") {
+      if (!this.inputField.reportValidity()) {
+        return;
+      }
+      Services.prefs.setIntPref(this.name, parseInt(this.inputField.value));
+    } else {
+      Services.prefs.setStringPref(this.name, this.inputField.value);
+    }
+    this.refreshValue();
+    this.endEdit();
+    this.editButton.focus();
+  }
+
+  endEdit() {
+    this.editing = false;
+    this.refreshElement();
+    gPrefInEdit = null;
+  }
 }
 
 function getPrefName(prefRow) {
   return prefRow.getAttribute("aria-label");
 }
 
 document.addEventListener("DOMContentLoaded", () => {
   if (!Preferences.get("browser.aboutConfig.showWarning")) {
@@ -147,52 +204,50 @@ function loadPrefs() {
     let prefRow = event.target.closest("tr");
     let prefName = getPrefName(prefRow);
     let pref = gPrefArray.find(p => p.name == prefName);
     let button = event.target.closest("button");
     if (button.classList.contains("button-reset")) {
       // Reset pref and update gPrefArray.
       Services.prefs.clearUserPref(prefName);
       pref.refreshValue();
-      pref.rebuildElement();
+      pref.refreshElement();
       pref.editButton.focus();
     } else if (button.classList.contains("add-true")) {
       addNewPref(prefRow.firstChild.innerHTML, true);
     } else if (button.classList.contains("add-false")) {
       addNewPref(prefRow.firstChild.innerHTML, false);
     } else if (button.classList.contains("add-Number") ||
       button.classList.contains("add-String")) {
       addNewPref(prefRow.firstChild.innerHTML,
-        button.classList.contains("add-Number") ? 0 : "");
-      prefRow = [...prefs.getElementsByTagName("tr")]
-        .find(row => row.querySelector("td").textContent == prefName);
-      startEditingPref(prefRow, gPrefArray.find(p => p.name == prefName));
-      prefRow.querySelector("td.cell-value").firstChild.firstChild.focus();
+        button.classList.contains("add-Number") ? 0 : "").edit();
     } else if (button.classList.contains("button-toggle")) {
       // Toggle the pref and update gPrefArray.
       Services.prefs.setBoolPref(prefName, !pref.value);
       pref.refreshValue();
       pref.refreshElement();
     } else if (button.classList.contains("button-edit")) {
-      startEditingPref(prefRow, pref);
-      prefRow.querySelector("td.cell-value").firstChild.firstChild.focus();
+      pref.edit();
     } else if (button.classList.contains("button-save")) {
-      endEditingPref(prefRow);
-      prefRow.querySelector("td.cell-edit").firstChild.focus();
+      pref.save();
     } else {
       Services.prefs.clearUserPref(prefName);
       gPrefArray.splice(gPrefArray.findIndex(p => p.name == prefName), 1);
       prefRow.remove();
     }
   });
 
   filterPrefs();
 }
 
 function filterPrefs() {
+  if (gPrefInEdit) {
+    gPrefInEdit.endEdit();
+  }
+
   let substring = document.getElementById("search").value.trim();
   document.getElementById("prefs").textContent = "";
   if (substring && !gPrefArray.some(pref => pref.name == substring)) {
     document.getElementById("prefs").appendChild(createNewPrefFragment(substring));
   }
   let fragment = createPrefsFragment(gPrefArray.filter(pref => pref.name.includes(substring)));
   document.getElementById("prefs").appendChild(fragment);
 }
@@ -233,70 +288,16 @@ function createNewPrefFragment(name) {
 
   let buttonCell = document.createElement("td");
   row.appendChild(buttonCell);
 
   fragment.appendChild(row);
   return fragment;
 }
 
-function startEditingPref(row, arrayEntry) {
-  if (gPrefInEdit) {
-    // Abort editing-process first.
-    gPrefInEdit.rebuildElement();
-  }
-
-  let name = getPrefName(row);
-  gPrefInEdit = arrayEntry;
-
-  let valueCell = row.querySelector("td.cell-value");
-  valueCell.textContent = "";
-  // The form is needed for the invalid-tooltip to appear.
-  let form = document.createElement("form");
-  form.id = "form-edit";
-  let inputField = document.createElement("input");
-  inputField.value = arrayEntry.value;
-  if (arrayEntry.value.constructor.name == "Number") {
-    inputField.type = "number";
-    inputField.required = true;
-    inputField.min = -2147483648;
-    inputField.max = 2147483647;
-  } else {
-    inputField.type = "text";
-  }
-  form.appendChild(inputField);
-  valueCell.appendChild(form);
-
-  let buttonCell = row.querySelector("td.cell-edit");
-  buttonCell.childNodes[0].remove();
-  let button = document.createElement("button");
-  button.classList.add("primary", "button-save");
-  document.l10n.setAttributes(button, "about-config-pref-save");
-  button.setAttribute("form", "form-edit");
-  buttonCell.appendChild(button);
-}
-
-function endEditingPref(row) {
-  let name = gPrefInEdit.name;
-  let input = row.querySelector("td.cell-value").firstChild.firstChild;
-  let newValue = input.value;
-  if (Services.prefs.getPrefType(name) == Services.prefs.PREF_INT) {
-    if (!input.reportValidity()) {
-      return;
-    }
-    Services.prefs.setIntPref(name, parseInt(newValue));
-  } else {
-    Services.prefs.setStringPref(name, newValue);
-  }
-
-  // Update gPrefArray.
-  gPrefInEdit.refreshValue();
-  gPrefInEdit.rebuildElement();
-}
-
 function prefHasDefaultValue(name) {
   try {
     switch (Services.prefs.getPrefType(name)) {
       case Ci.nsIPrefBranch.PREF_STRING:
         gDefaultBranch.getStringPref(name);
         return true;
       case Ci.nsIPrefBranch.PREF_INT:
         gDefaultBranch.getIntPref(name);
@@ -306,12 +307,14 @@ function prefHasDefaultValue(name) {
         return true;
     }
   } catch (ex) {}
   return false;
 }
 
 function addNewPref(name, value) {
   Preferences.set(name, value);
-  gPrefArray.push(new PrefRow(name));
+  let pref = new PrefRow(name);
+  gPrefArray.push(pref);
   gPrefArray.sort((a, b) => a.name > b.name);
   filterPrefs();
+  return pref;
 }