Bug 1497725 - Add a search field to the new "about:config" page. r=paolo
authorLuke Schwalfenberg <lschwalfenberg@gmail.com>
Mon, 19 Nov 2018 13:52:08 +0000
changeset 446991 4ef55dde9b9310f0f1060943700a76955b94d688
parent 446990 58d0df7129383a0984e87ea333d6b6ea198a8b55
child 446992 62c4741625fed62804f105d8d979f4b5b3d0f191
child 447079 640b09ec036ea40e164b2193172bf247475d9930
push id35064
push userdvarga@mozilla.com
push dateMon, 19 Nov 2018 17:02:31 +0000
treeherdermozilla-central@62c4741625fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspaolo
bugs1497725
milestone65.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 1497725 - Add a search field to the new "about:config" page. r=paolo Differential Revision: https://phabricator.services.mozilla.com/D11843
browser/components/aboutconfig/content/aboutconfig.css
browser/components/aboutconfig/content/aboutconfig.html
browser/components/aboutconfig/content/aboutconfig.js
browser/components/aboutconfig/content/aboutconfig.notftl
browser/components/aboutconfig/test/browser/browser.ini
browser/components/aboutconfig/test/browser/browser_search.js
--- a/browser/components/aboutconfig/content/aboutconfig.css
+++ b/browser/components/aboutconfig/content/aboutconfig.css
@@ -1,12 +1,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
+#search {
+  position: sticky;
+  top: 0;
+  margin: 10px;
+  box-sizing: border-box;
+  width: calc(100% - 20px);
+  min-width: 644px;
+  background-image: url("chrome://global/skin/icons/search-textbox.svg");
+  background-repeat: no-repeat;
+  background-position: 9px center;
+  background-size: 12px 12px;
+  padding-left: 30px;
+}
+
 #prefs {
   background-color: var(--in-content-box-background);
   color: var(--in-content-text-color);
   margin: 10px;
   min-width: 644px;
   /* To stay consistent with about:preferences (664px - 20px margin). */
   border: 1px solid var(--in-content-box-border-color);
   border-radius: 2px;
--- a/browser/components/aboutconfig/content/aboutconfig.html
+++ b/browser/components/aboutconfig/content/aboutconfig.html
@@ -11,11 +11,12 @@
     <link rel="stylesheet" type="text/css"
           href="chrome://browser/content/aboutconfig/aboutconfig.css">
     <link rel="localization" href="browser/aboutConfig.ftl">
     <script type="application/javascript"
             src="chrome://browser/content/aboutconfig/aboutconfig.js"></script>
     <title data-l10n-id="about-config-title"></title>
   </head>
   <body onload="onLoad();">
+    <input type="text" id="search" data-l10n-id="about-config-search">
     <table id="prefs"></table>
   </body>
 </html>
--- a/browser/components/aboutconfig/content/aboutconfig.js
+++ b/browser/components/aboutconfig/content/aboutconfig.js
@@ -24,18 +24,35 @@ function onLoad() {
     } catch (ex) {
       pref.value = "";
     }
     return pref;
   });
 
   gPrefArray.sort((a, b) => a.name > b.name);
 
+  document.getElementById("search").addEventListener("keypress", function(e) {
+    if (e.code == "Enter") {
+      filterPrefs();
+    }
+  });
+
+  document.getElementById("prefs").appendChild(createPrefsFragment(gPrefArray));
+}
+
+function filterPrefs() {
+  let substring = document.getElementById("search").value.trim();
+  let fragment = createPrefsFragment(gPrefArray.filter(pref => pref.name.includes(substring)));
+  document.getElementById("prefs").textContent = "";
+  document.getElementById("prefs").appendChild(fragment);
+}
+
+function createPrefsFragment(prefArray) {
   let fragment = document.createDocumentFragment();
-  for (let pref of gPrefArray) {
+  for (let pref of prefArray) {
     let row = document.createElement("tr");
     if (pref.hasUserValue) {
       row.classList.add("has-user-value");
     }
     row.setAttribute("aria-label", pref.name);
 
     let nameCell = document.createElement("td");
     // Add <wbr> behind dots to prevent line breaking in random mid-word places.
@@ -48,10 +65,10 @@ function onLoad() {
 
     let valueCell = document.createElement("td");
     valueCell.classList.add("cell-value");
     valueCell.textContent = pref.value;
     row.appendChild(valueCell);
 
     fragment.appendChild(row);
   }
-  document.getElementById("prefs").appendChild(fragment);
+  return fragment;
 }
--- a/browser/components/aboutconfig/content/aboutconfig.notftl
+++ b/browser/components/aboutconfig/content/aboutconfig.notftl
@@ -1,5 +1,8 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # 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/.
 
 about-config-title = about:config
+
+about-config-search =
+    .placeholder = Search
--- a/browser/components/aboutconfig/test/browser/browser.ini
+++ b/browser/components/aboutconfig/test/browser/browser.ini
@@ -1,3 +1,5 @@
 [DEFAULT]
 
 [browser_basic.js]
+[browser_search.js]
+skip-if = debug # Bug 1507747
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutconfig/test/browser/browser_search.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+ChromeUtils.import("resource://gre/modules/Preferences.jsm", this);
+
+const PAGE_URL = "chrome://browser/content/aboutconfig/aboutconfig.html";
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      ["test.aboutconfig.a", "test value 1"],
+      ["test.aboutconfig.ab", "test value 2"],
+      ["test.aboutconfig.b", "test value 3"],
+    ],
+  });
+});
+
+add_task(async function test_search() {
+  await BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: PAGE_URL,
+  }, async browser => {
+    let prefArray = Services.prefs.getChildList("");
+
+    // Test page loaded with correct number of prefs.
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   aPrefArray.length);
+
+      // Test page search of "button" returns correct number of preferences.
+      let search = content.document.getElementById("search");
+      search.value = "button   ";
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      let filteredPrefArray =
+          aPrefArray.filter(pref => pref.includes("button"));
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   filteredPrefArray.length);
+
+      // Test empty search returns all preferences.
+      let search = content.document.getElementById("search");
+      search.value = "";
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   aPrefArray.length);
+
+      // Test invalid search returns no preferences.
+      let search = content.document.getElementById("search");
+      search.value = "aJunkValueasdf";
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   0);
+
+      // Test added preferences search returns 2 preferences.
+      let search = content.document.getElementById("search");
+      search.value = "test.aboutconfig.a";
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   2);
+    });
+  });
+});