manage: search regexps, add search help, fix favicons toggle icon
* the toggle icon is now a triangle, rotated when open
This commit is contained in:
parent
69ee57f88f
commit
03b6f6c263
|
@ -691,9 +691,9 @@
|
|||
"message": "Search contents",
|
||||
"description": "Label for the search filter textbox on the Manage styles page"
|
||||
},
|
||||
"searchStylesTooltip": {
|
||||
"message": "To show styles for a URL, prefix it with 'url:'\nFor example, url:https://github.com/openstyles/stylus",
|
||||
"description": "Label for the search filter textbox on the Manage styles page"
|
||||
"searchStylesHelp": {
|
||||
"message": "</> key focuses the search field.\nPlain text: search within the name, code, homepage URL and sites it is applied to. Words with less than 3 letters are ignored.\nMatching URL: prefix the search with <url:>, e.g. <url:https://github.com/openstyles/stylus>\nRegular expressions: include slashes and flags, e.g. </foo.*?/simguy>\nExact words: wrap the query in double quotes, e.g. <\"Like this!\">",
|
||||
"description": "Text in the minihelp displayed when clicking (i) icon to the right of the search input field on the Manage styles page"
|
||||
},
|
||||
"sectionAdd": {
|
||||
"message": "Add another section",
|
||||
|
|
|
@ -286,9 +286,9 @@ function tryCatch(func, ...args) {
|
|||
}
|
||||
|
||||
|
||||
function tryRegExp(regexp) {
|
||||
function tryRegExp(regexp, flags) {
|
||||
try {
|
||||
return new RegExp(regexp);
|
||||
return new RegExp(regexp, flags);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
|
|
22
manage.html
22
manage.html
|
@ -237,10 +237,12 @@
|
|||
<span i18n-text="manageOnlyUpdates"></span>
|
||||
</label>
|
||||
|
||||
<input id="search" type="search" i18n-placeholder="searchStyles" spellcheck="false"
|
||||
i18n-title="searchStylesTooltip"
|
||||
data-filter=":not(.not-matching)"
|
||||
data-filter-hide=".not-matching">
|
||||
<div id="search-wrapper">
|
||||
<input id="search" type="search" i18n-placeholder="searchStyles" spellcheck="false"
|
||||
data-filter=":not(.not-matching)"
|
||||
data-filter-hide=".not-matching">
|
||||
<svg id="search-help" class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg>
|
||||
</div>
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -292,10 +294,11 @@
|
|||
<label for="manage.newUI.favicons" i18n-text="manageFavicons">
|
||||
<input id="manage.newUI.favicons" type="checkbox">
|
||||
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||
<svg class="svg-icon select-arrow" data-toggle-on-click="#faviconsHelp">
|
||||
<title i18n-text="optionsSubheading"></title>
|
||||
<use xlink:href="#svg-icon-select-arrow"/>
|
||||
</svg>
|
||||
</label>
|
||||
<svg class="svg-icon info" viewBox="0 0 14 16" i18n-alt="helpAlt" data-toggle-on-click="#faviconsHelp">
|
||||
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
|
||||
</svg>
|
||||
<div id="faviconsHelp" class="hidden" i18n-text="manageFaviconsHelp">
|
||||
<div>
|
||||
<label for="manage.newUI.faviconsGray" i18n-text="manageFaviconsGray">
|
||||
|
@ -348,6 +351,11 @@
|
|||
<symbol id="svg-icon-select-arrow" viewBox="0 0 1792 1792">
|
||||
<path fill-rule="evenodd" d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>
|
||||
</symbol>
|
||||
|
||||
<symbol id="svg-icon-help" viewBox="0 0 14 16">
|
||||
<title i18n-text="helpAlt"></title>
|
||||
<path fill-rule="evenodd" d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"></path>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global installed */
|
||||
/* global installed messageBox */
|
||||
'use strict';
|
||||
|
||||
const filtersSelector = {
|
||||
|
@ -31,6 +31,25 @@ onDOMready().then(onBackgroundReady).then(() => {
|
|||
if (urlFilterParam) {
|
||||
$('#search').value = 'url:' + urlFilterParam;
|
||||
}
|
||||
$('#search-help').onclick = () => {
|
||||
messageBox({
|
||||
className: 'help-text',
|
||||
title: t('searchStyles'),
|
||||
contents:
|
||||
$create('ul',
|
||||
t('searchStylesHelp').split('\n').map(line =>
|
||||
$create('li', line.split(/(<.*?>)/).map((s, i, words) => {
|
||||
if (s.startsWith('<')) {
|
||||
const num = words.length;
|
||||
const className = i === num - 2 && !words[num - 1] ? '.last' : '';
|
||||
return $create('mark' + className, s.slice(1, -1));
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
})))),
|
||||
buttons: [t('confirmOK')],
|
||||
});
|
||||
};
|
||||
|
||||
$$('select[id$=".invert"]').forEach(el => {
|
||||
const slave = $('#' + el.id.replace('.invert', ''));
|
||||
|
@ -350,10 +369,11 @@ function showFiltersStats() {
|
|||
|
||||
function searchStyles({immediately, container}) {
|
||||
const searchElement = $('#search');
|
||||
const urlMode = /^\s*url:/i.test(searchElement.value);
|
||||
const value = searchElement.value;
|
||||
const urlMode = /^\s*url:/i.test(value);
|
||||
const query = urlMode
|
||||
? searchElement.value.replace(/^\s*url:/i, '').trim()
|
||||
: searchElement.value.toLocaleLowerCase();
|
||||
? value.replace(/^\s*url:/i, '').trim()
|
||||
: value.toLocaleLowerCase();
|
||||
const queryPrev = searchElement.lastValue || '';
|
||||
if (query === queryPrev && !immediately && !container) {
|
||||
return;
|
||||
|
@ -364,6 +384,12 @@ function searchStyles({immediately, container}) {
|
|||
}
|
||||
searchElement.lastValue = query;
|
||||
|
||||
const trimmed = query.trim();
|
||||
const rx = trimmed.startsWith('/') && trimmed.indexOf('/', 1) > 0 &&
|
||||
tryRegExp(...(value.match(/^\s*\/(.*?)\/([gimsuy]*)\s*$/) || []).slice(1));
|
||||
const words = rx ? null :
|
||||
trimmed.startsWith('"') && trimmed.endsWith('"') ? [value.trim().slice(1, -1)] :
|
||||
query.split(/\s+/).filter(s => s.length > 2);
|
||||
const searchInVisible = !urlMode && queryPrev && query.includes(queryPrev);
|
||||
const entries = container && container.children || container ||
|
||||
(searchInVisible ? $$('.entry:not(.hidden)') : installed.children);
|
||||
|
@ -415,6 +441,17 @@ function searchStyles({immediately, container}) {
|
|||
}
|
||||
|
||||
function isMatchingText(text) {
|
||||
return text.toLocaleLowerCase().indexOf(query) >= 0;
|
||||
if (rx) {
|
||||
return rx.test(text);
|
||||
}
|
||||
for (let pass = 1; pass <= 2; pass++) {
|
||||
for (const word of words) {
|
||||
if (text.includes(word)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
text = text.toLocaleLowerCase();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -658,6 +658,7 @@ select {
|
|||
align-items: center;
|
||||
margin-bottom: auto;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#newUIoptions input[type="number"] {
|
||||
|
@ -665,6 +666,18 @@ select {
|
|||
margin-right: .5em;
|
||||
}
|
||||
|
||||
#newUIoptions [data-toggle-on-click] {
|
||||
transform: rotate(-90deg);
|
||||
cursor: pointer;
|
||||
right: -16px;
|
||||
top: 0;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
#newUIoptions [data-toggle-on-click][open] {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
input[id^="manage.newUI"] {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
@ -763,7 +776,6 @@ input[id^="manage.newUI"] {
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
#filters input,
|
||||
#filters label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -816,14 +828,48 @@ input[id^="manage.newUI"] {
|
|||
display: none;
|
||||
}
|
||||
|
||||
#search-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#search {
|
||||
width: calc(100% - 4px);
|
||||
flex-grow: 1;
|
||||
margin: 0.25rem 0 0;
|
||||
border-radius: 0.25rem;
|
||||
padding-left: 0.25rem;
|
||||
border-width: 1px;
|
||||
}
|
||||
|
||||
#search-wrapper .info {
|
||||
margin: 4px -5px 0 8px;
|
||||
}
|
||||
|
||||
#message-box.help-text > div {
|
||||
max-width: 26rem;
|
||||
}
|
||||
.help-text li:not(:last-child) {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.help-text mark {
|
||||
background-color: rgba(128, 128, 128, .15);
|
||||
color: currentColor;
|
||||
padding: 2px 6px;
|
||||
font-weight: bold;
|
||||
font-family: monospace;
|
||||
border: 1px solid rgba(128, 128, 128, .25);
|
||||
display: inline-block;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
.help-text mark.last {
|
||||
display: block;
|
||||
width: -moz-min-content;
|
||||
width: min-content;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#import ul {
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
|
|
|
@ -66,7 +66,15 @@ function initGlobalEvents() {
|
|||
$$('[data-toggle-on-click]').forEach(el => {
|
||||
// dataset on SVG doesn't work in Chrome 49-??, works in 57+
|
||||
const target = $(el.getAttribute('data-toggle-on-click'));
|
||||
el.onclick = () => target.classList.toggle('hidden');
|
||||
el.onclick = event => {
|
||||
event.preventDefault();
|
||||
target.classList.toggle('hidden');
|
||||
if (target.classList.contains('hidden')) {
|
||||
el.removeAttribute('open');
|
||||
} else {
|
||||
el.setAttribute('open', '');
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
// triggered automatically by setupLivePrefs() below
|
||||
|
|
Loading…
Reference in New Issue
Block a user