From e3861e67b45c40131a661fda52f7c099a8ee10bf Mon Sep 17 00:00:00 2001 From: kkapsner Date: Tue, 18 Sep 2018 13:14:39 +0200 Subject: [PATCH] Create search in options page Fixes #242 --- _locales/de/messages.json | 4 +++ _locales/en/messages.json | 4 +++ lib/search.js | 51 +++++++++++++++++++++++++++++++++++++ lib/settingStrings.js | 53 +++++++++++++++++++++++++++++++++++++++ options/options.css | 16 +++++++++++- options/options.html | 2 ++ options/options.js | 34 ++++++++++++++++++++++++- options/optionsGui.js | 5 +++- 8 files changed, 166 insertions(+), 3 deletions(-) create mode 100644 lib/search.js create mode 100644 lib/settingStrings.js diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 4519ff2..efa5246 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -37,6 +37,10 @@ "message": "Bitte warten...", "description": "" }, + "search": { + "message": "Suchen", + "description": "" + }, "input": { "message": "Eingabe", diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 450477c..72b91f9 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -37,6 +37,10 @@ "message": "Please wait...", "description": "" }, + "search": { + "message": "Search", + "description": "" + }, "input": { "message": "input", diff --git a/lib/search.js b/lib/search.js new file mode 100644 index 0000000..6971e94 --- /dev/null +++ b/lib/search.js @@ -0,0 +1,51 @@ +/* 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/. */ +(function(){ + "use strict"; + + var scope; + if ((typeof exports) !== "undefined"){ + scope = exports; + } + else { + window.scope.search = {}; + scope = window.scope.search; + } + + const texts = []; + + scope.register = function(text, content){ + texts.push({text: text.toLowerCase(), content}); + }; + scope.search = function(search){ + search = search.toLowerCase(); + const result = []; + texts.forEach(function(text){ + if (text.text.indexOf(search) !== -1){ + result.push(text.content); + } + }); + return result; + }; + const searchListeners = []; + scope.init = function(){ + const node = document.createElement("input"); + node.id = "search"; + node.placeholder = browser.i18n.getMessage("search"); + window.setTimeout(() => node.focus(), 1); + let lastResults = []; + node.addEventListener("input", function(){ + const search = this.value; + const results = search? scope.search(search): []; + searchListeners.forEach(function(callback){ + callback({search, results, lastResults}); + }); + lastResults = results; + }); + return node; + }; + scope.on = function(callback){ + searchListeners.push(callback); + }; +}()); \ No newline at end of file diff --git a/lib/settingStrings.js b/lib/settingStrings.js new file mode 100644 index 0000000..a534d17 --- /dev/null +++ b/lib/settingStrings.js @@ -0,0 +1,53 @@ +/* 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/. */ +(function(){ + "use strict"; + + var scope; + if ((typeof exports) !== "undefined"){ + scope = exports; + } + else { + scope = {}; + window.scope.settingStrings = scope; + } + + scope.getMessages = function(settingDefinition){ + const messages = [ + settingDefinition.name + "_title", + settingDefinition.name + "_description", + ]; + if (settingDefinition.urlSpecific){ + messages.push(settingDefinition.name + "_urlSpecific"); + } + if (settingDefinition.options){ + settingDefinition.options.forEach(function(option){ + messages.push(settingDefinition.name + "_option." + option); + }); + } + return messages; + }; + + scope.getStrings = function(settingDefinition){ + const strings = []; + function addString(string){ + if ((typeof string) === "string" && string.trim()){ + strings.push(string); + } + } + + addString(settingDefinition.name); + if (settingDefinition.options){ + settingDefinition.options.forEach(function(option){ + addString(option); + }); + } + + scope.getMessages(settingDefinition).forEach(function(message){ + addString(browser.i18n.getMessage(message)); + }); + + return strings; + }; +}()); \ No newline at end of file diff --git a/options/options.css b/options/options.css index 749079c..b1fb3f4 100644 --- a/options/options.css +++ b/options/options.css @@ -28,7 +28,7 @@ header .bookmarkNotice .dontShowOptionsOnUpdate input { border-spacing: 0; border-collapse: collapse; } -.settings.displayDescriptions { +.settings { table-layout: fixed; } .settings * { @@ -214,4 +214,18 @@ td.hideColumn { text-align: right; color: gray; font-size: 0.8em; +} + +#search { + box-sizing: border-box; + width: 100%; + border: none; + background-color: transparent; +} +.searching .settingRow { + display: none; +} + +.searching .settingRow.found { + display: table-row; } \ No newline at end of file diff --git a/options/options.html b/options/options.html index c0ee525..77ce1fa 100644 --- a/options/options.html +++ b/options/options.html @@ -10,7 +10,9 @@ + + diff --git a/options/options.js b/options/options.js index 6ff28fa..c674aad 100644 --- a/options/options.js +++ b/options/options.js @@ -10,6 +10,8 @@ const optionsGui = require("./optionsGui"); const settings = require("./settings"); const settingsDisplay = require("./settingsDisplay"); + const search = require("./search"); + const settingStrings = require("./settingStrings"); var callbacks = { showReleaseNotes: function(){ @@ -168,7 +170,26 @@ document.body.appendChild(table); const displayHidden = settings.getDefinition(settingsDisplay.displayHidden); - table.appendChild(optionsGui.createThead(displayHidden)); + table.appendChild( + optionsGui.createThead( + displayHidden, + search.init() + ) + ); + search.on(function({search, results, lastResults}){ + lastResults.forEach(function(node){ + node.classList.remove("found"); + }); + if (search){ + document.body.classList.add("searching"); + results.forEach(function(node){ + node.classList.add("found"); + }); + } + else { + document.body.classList.remove("searching"); + } + }); let lastSection = null; let addSection = function addSection(name){ @@ -192,10 +213,16 @@ body.appendChild(row); }, updateDisplay: function(){ + const searchMode = document.body.classList.contains("searching"); var anyVisible = false; rows.forEach(function(row){ var isHidden = row.classList.contains("hidden"); if (!isHidden){ + if (searchMode){ + if (!row.classList.contains("found")){ + return; + } + } if (anyVisible){ row.classList.remove("firstVisible"); } @@ -208,6 +235,8 @@ body.classList[anyVisible? "remove": "add"]("hidden"); } }; + + search.on(function(){section.updateDisplay();}); lastSection = section; }; addSection(); @@ -306,6 +335,9 @@ } var row = optionsGui.createSettingRow(setting); + settingStrings.getStrings(setting).forEach(function(string){ + search.register(string, row); + }); let section = lastSection; section.addRow(row); if (!display.displayDependencies){ diff --git a/options/optionsGui.js b/options/optionsGui.js index 9972ab8..97fdbd0 100644 --- a/options/optionsGui.js +++ b/options/optionsGui.js @@ -375,7 +375,7 @@ scope.createSettingRow = createSettingRow; - function createThead(displayHidden){ + function createThead(displayHidden, restContent){ const tHead = document.createElement("thead"); const headRow = document.createElement("tr"); const hideHeadCell = document.createElement("td"); @@ -393,6 +393,9 @@ const restHeadCell = document.createElement("td"); restHeadCell.colSpan = 2; + if (restContent){ + restHeadCell.appendChild(restContent); + } headRow.appendChild(restHeadCell); tHead.appendChild(headRow); return tHead;