@@ -317,7 +323,7 @@
+ target="_blank">
diff --git a/manage/config-dialog.css b/manage/config-dialog.css
index bd6f037e..46f5d4c3 100644
--- a/manage/config-dialog.css
+++ b/manage/config-dialog.css
@@ -97,11 +97,8 @@
visibility: hidden;
}
-.svg-icon.config-reset-icon {
- /*position: absolute;*/
- pointer-events: all !important;
+.config-reset-icon .svg-icon {
cursor: pointer;
- /*right: -7px;*/
fill: #aaa;
width: 16px;
height: 16px;
@@ -110,7 +107,7 @@
flex-shrink: 0;
}
-.svg-icon.config-reset-icon:hover {
+.config-reset-icon:hover .svg-icon {
fill: #666;
}
@@ -155,9 +152,11 @@
.color-swatch {
position: absolute;
+ top: 0;
+ left: 0;
border: 1px solid gray;
- margin-top: -22px;
cursor: pointer;
+ opacity: 1;
}
.colorpicker-popup {
diff --git a/manage/config-dialog.js b/manage/config-dialog.js
index 0661c333..503c5b39 100644
--- a/manage/config-dialog.js
+++ b/manage/config-dialog.js
@@ -195,21 +195,25 @@ function configDialog(style) {
}
function buildConfigForm() {
- let resetter = $create('SVG:svg.svg-icon.config-reset-icon', {viewBox: '0 0 20 20'}, [
- $create('SVG:title', t('genericResetLabel')),
- $create('SVG:polygon', {
- points: '16.2,5.5 14.5,3.8 10,8.3 5.5,3.8 3.8,5.5 8.3,10 3.8,14.5 ' +
- '5.5,16.2 10,11.7 14.5,16.2 16.2,14.5 11.7,10',
- }),
- ]);
+ let resetter =
+ $create('a.config-reset-icon', {href: '#'}, [
+ $create('SVG:svg.svg-icon', {viewBox: '0 0 20 20'}, [
+ $create('SVG:title', t('genericResetLabel')),
+ $create('SVG:polygon', {
+ points: '16.2,5.5 14.5,3.8 10,8.3 5.5,3.8 3.8,5.5 8.3,10 3.8,14.5 ' +
+ '5.5,16.2 10,11.7 14.5,16.2 16.2,14.5 11.7,10',
+ })
+ ])
+ ]);
for (const va of vars) {
let children;
switch (va.type) {
case 'color':
children = [
$create('.cm-colorview.config-value', [
- va.input = $create('.color-swatch', {
+ va.input = $create('a.color-swatch', {
va,
+ href: '#',
onclick: showColorpicker
}),
]),
@@ -269,6 +273,8 @@ function configDialog(style) {
...children,
resetter,
]));
+
+ va.savedValue = va.value;
}
}
@@ -307,6 +313,7 @@ function configDialog(style) {
const el = va.input.closest('label');
el.classList.toggle('dirty', Boolean(va.dirty));
el.classList.toggle('nondefault', !isDefault(va));
+ $('.config-reset-icon', el).disabled = isDefault(va);
}
function resetOnClick(event) {
@@ -316,7 +323,8 @@ function configDialog(style) {
onchange({target: this.va.input});
}
- function showColorpicker() {
+ function showColorpicker(event) {
+ event.preventDefault();
window.removeEventListener('keydown', messageBox.listeners.key, true);
const box = $('#message-box-contents');
colorpicker.show({
diff --git a/manage/filters.js b/manage/filters.js
index 9fb24c4b..fb12d179 100644
--- a/manage/filters.js
+++ b/manage/filters.js
@@ -31,7 +31,8 @@ onDOMready().then(onBackgroundReady).then(() => {
if (urlFilterParam) {
$('#search').value = 'url:' + urlFilterParam;
}
- $('#search-help').onclick = () => {
+ $('#search-help').onclick = event => {
+ event.preventDefault();
messageBox({
className: 'help-text',
title: t('searchStyles'),
@@ -352,7 +353,9 @@ function showFiltersStats() {
debounce(showFiltersStats, 100);
return;
}
- $('#filters summary').classList.toggle('active', filtersSelector.hide !== '');
+ const active = filtersSelector.hide !== '';
+ $('#filters summary').classList.toggle('active', active);
+ $('#reset-filters').disabled = !active;
const numTotal = BG.cachedStyles.list.length;
const numHidden = installed.getElementsByClassName('entry hidden').length;
const numShown = Math.min(numTotal - numHidden, installed.children.length);
diff --git a/manage/incremental-search.js b/manage/incremental-search.js
index 1d6f75a0..9976e187 100644
--- a/manage/incremental-search.js
+++ b/manage/incremental-search.js
@@ -7,6 +7,7 @@ onDOMready().then(() => {
let focusedName = '';
const input = $create('textarea', {
spellcheck: false,
+ attributes: {tabindex: -1},
oninput: incrementalSearch,
});
replaceInlineStyle({
diff --git a/manage/manage.css b/manage/manage.css
index 984dc3ee..3755a101 100644
--- a/manage/manage.css
+++ b/manage/manage.css
@@ -145,12 +145,11 @@ select {
}
.svg-icon.config {
- width: 16px;
- height: 16px;
+ transform: scale(.8);
}
.homepage {
- margin-left: 0.1em;
+ margin-left: 0.25em;
margin-right: 0.1em;
}
@@ -159,8 +158,7 @@ select {
}
.homepage .svg-icon {
- margin-top: -4px;
- margin-left: .5ex;
+ margin-top: 0;
}
.style-name {
@@ -190,6 +188,7 @@ select {
.actions > * {
margin-bottom: .25rem;
+ display: inline-block;
}
.actions > *:not(:last-child) {
@@ -212,7 +211,6 @@ select {
.applies-to-extra-expander {
font-weight: bold;
cursor: pointer;
- outline: none;
}
.applies-to-extra-expander {
@@ -284,7 +282,6 @@ select {
align-items: center;
margin-left: -13px;
cursor: pointer;
- outline: none;
}
#header summary h2 {
@@ -363,7 +360,6 @@ select {
.filter-selection select {
height: 18px;
- outline: none;
border: none;
max-width: 100%;
padding-left: 4px;
@@ -449,9 +445,8 @@ select {
color: hsla(180, 100%, 15%, 1);
}
-.newUI .homepage .svg-icon {
+.newUI .homepage:not([href=""]) {
position: absolute;
- margin-top: 0;
margin-left: -28px;
}
@@ -462,11 +457,9 @@ select {
}
.newUI .actions > * {
- margin: 0;
-}
-
-.newUI .actions .svg-icon {
- margin-right: 8px;
+ margin: 0 6px 0 0;
+ width: 20px;
+ height: 20px;
}
.newUI .updater-icons > * {
@@ -488,7 +481,7 @@ select {
.newUI .checking-update .check-update {
opacity: 0;
- display: inline;
+ display: inline-block;
pointer-events: none;
}
@@ -496,7 +489,7 @@ select {
.newUI .no-update:not(.update-problem):not(.update-done) .up-to-date,
.newUI .no-update.update-problem .check-update,
.newUI .update-done .updated {
- display: inline;
+ display: inline-block;
}
.newUI .up-to-date svg,
@@ -595,6 +588,7 @@ select {
line-height: .5ex;
vertical-align: super;
letter-spacing: .1ex;
+ text-decoration: none;
}
.newUI .applies-to:not(.has-more) .expander {
@@ -602,7 +596,7 @@ select {
}
.newUI .has-favicons .applies-to .expander {
- padding-left: 20px;
+ margin-left: 20px;
}
.newUI .target:hover {
@@ -661,15 +655,21 @@ 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="#faviconsHelp"] {
+ width: 14px;
+ height: 14px;
+ display: inline-block;
+ vertical-align: middle;
+ position: relative;
+ top: -1px;
}
-#newUIoptions [data-toggle-on-click][open] {
+#newUIoptions [data-toggle-on-click] svg {
+ transform: rotate(-90deg);
+ position: static;
+}
+
+#newUIoptions [data-toggle-on-click][open] svg {
transform: none;
}
@@ -690,14 +690,14 @@ input[id^="manage.newUI"] {
}
/* Default, no update buttons */
-.update,
-.check-update {
+.updater-icons .update,
+.updater-icons .check-update {
display: none;
}
-/* Check update button for things that can*/
+/* Check update button for things that can */
.updatable .check-update {
- display: inline;
+ display: inline-block;
}
/* Update check in progress */
@@ -707,7 +707,7 @@ input[id^="manage.newUI"] {
/* Updates available */
.can-update .update {
- display: inline;
+ display: inline-block;
}
.can-update[data-details$="locally edited"] button.update:after {
@@ -804,6 +804,10 @@ input[id^="manage.newUI"] {
#reset-filters {
position: absolute;
margin-top: 2px;
+ display: inline-block;
+}
+
+#reset-filters svg {
fill: hsla(180, 50%, 27%, .5);
width: 24px; /* widen the click area a bit */
height: 20px;
@@ -811,7 +815,7 @@ input[id^="manage.newUI"] {
box-sizing: border-box;
}
-#reset-filters:hover {
+#reset-filters:hover svg {
fill: hsla(180, 50%, 27%, 1);
}
@@ -839,8 +843,8 @@ input[id^="manage.newUI"] {
border-radius: 0.25rem;
}
-#search-wrapper .info {
- margin: 4px -5px 0 8px;
+#search-help {
+ margin: 4px -5px 0 2px;
}
#message-box.help-text > div {
diff --git a/manage/manage.js b/manage/manage.js
index eea012b2..71c31798 100644
--- a/manage/manage.js
+++ b/manage/manage.js
@@ -334,10 +334,12 @@ Object.assign(handleEvent, {
},
check(event, entry) {
+ event.preventDefault();
checkUpdate(entry);
},
update(event, entry) {
+ event.preventDefault();
const request = Object.assign(entry.updatedCode, {
id: entry.styleId,
reason: 'update',
@@ -353,6 +355,7 @@ Object.assign(handleEvent, {
},
delete(event, entry) {
+ event.preventDefault();
const id = entry.styleId;
const {name} = BG.cachedStyles.byId.get(id) || {};
animateElement(entry);
@@ -362,8 +365,8 @@ Object.assign(handleEvent, {
className: 'danger center',
buttons: [t('confirmDelete'), t('confirmCancel')],
})
- .then(({button, enter}) => {
- if (button === 0 || enter) {
+ .then(({button}) => {
+ if (button === 0) {
deleteStyleSafe({id});
}
});
@@ -374,7 +377,8 @@ Object.assign(handleEvent, {
event.preventDefault();
},
- expandTargets() {
+ expandTargets(event) {
+ event.preventDefault();
this.closest('.applies-to').classList.toggle('expanded');
},
@@ -388,6 +392,7 @@ Object.assign(handleEvent, {
},
config(event, {styleMeta}) {
+ event.preventDefault()
configDialog(styleMeta);
},
});
diff --git a/manage/updater-ui.js b/manage/updater-ui.js
index e936bc26..8e58e627 100644
--- a/manage/updater-ui.js
+++ b/manage/updater-ui.js
@@ -170,7 +170,8 @@ function renderUpdatesOnlyFilter({show, check} = {}) {
}
-function showUpdateHistory() {
+function showUpdateHistory(event) {
+ event.preventDefault();
const log = $create('.update-history-log');
let logText, scroller, toggler;
let deleted = false;
@@ -179,13 +180,17 @@ function showUpdateHistory() {
messageBox({
title: t('updateCheckHistory'),
contents: log,
+ blockScroll: true,
buttons: [
t('confirmOK'),
logText && {textContent: t('confirmDelete'), onclick: deleteHistory},
],
onshow: logText && (() => {
scroller = $('#message-box-contents');
+ scroller.tabIndex = 0;
+ setTimeout(() => scroller.focus());
scrollToBottom();
+
$('#message-box-buttons button').insertAdjacentElement('afterend',
// TODO: add a global class for our labels
// TODO: add a
or a common function to create such controls
@@ -196,6 +201,7 @@ function showUpdateHistory() {
$create('SVG:use', {'xlink:href': '#svg-icon-checked'})),
t('manageOnlyUpdates'),
]));
+
toggler.onchange();
}),
});
diff --git a/msgbox/msgbox.js b/msgbox/msgbox.js
index c02b1eef..3862e039 100644
--- a/msgbox/msgbox.js
+++ b/msgbox/msgbox.js
@@ -1,3 +1,4 @@
+/* global focusAccessibility */
'use strict';
function messageBox({
@@ -12,10 +13,14 @@ function messageBox({
bindGlobalListeners();
createElement();
document.body.appendChild(messageBox.element);
- if (onshow) {
+
+ messageBox.originalFocus = document.activeElement;
+ moveFocus(1);
+
+ if (typeof onshow === 'function') {
onshow(messageBox.element);
}
- messageBox.element.focus();
+
return new Promise(_resolve => {
messageBox.resolve = _resolve;
});
@@ -29,13 +34,30 @@ function messageBox({
resolveWith({button: this.buttonIndex});
},
key(event) {
- const keyCode = event.keyCode || event.which;
- if (!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey
- && (keyCode === 13 || keyCode === 27)) {
- event.preventDefault();
- event.stopPropagation();
- resolveWith(keyCode === 13 ? {enter: true} : {esc: true});
+ const {which, shiftKey, ctrlKey, altKey, metaKey, target} = event;
+ if (shiftKey && which !== 9 || ctrlKey || altKey || metaKey) {
+ return;
}
+ switch (which) {
+ case 13:
+ for (let el = target; el; el = el.parentElement) {
+ if (focusAccessibility.ELEMENTS.includes(el.localName)) {
+ return;
+ }
+ }
+ break;
+ case 27:
+ event.preventDefault();
+ event.stopPropagation();
+ break;
+ case 9:
+ moveFocus(shiftKey ? -1 : 1);
+ event.preventDefault();
+ return;
+ default:
+ return;
+ }
+ resolveWith(which === 13 ? {enter: true} : {esc: true});
},
scroll() {
scrollTo(blockScroll.x, blockScroll.y);
@@ -50,6 +72,9 @@ function messageBox({
className: 'fadeout',
onComplete: removeSelf,
});
+ if (messageBox.element.contains(document.activeElement)) {
+ messageBox.originalFocus.focus();
+ }
}
function createElement() {
@@ -97,6 +122,21 @@ function messageBox({
messageBox.element = null;
messageBox.resolve = null;
}
+
+ function moveFocus(dir) {
+ const elements = [...messageBox.element.getElementsByTagName('*')];
+ const activeIndex = elements.indexOf(document.activeElement);
+ const num = elements.length;
+ for (let i = 1; i < num; i++) {
+ const elementIndex = (activeIndex + i * dir + num) % num;
+ // we don't use positive tabindex so we stop at any valid value
+ const el = elements[elementIndex];
+ if (!el.disabled && el.tabIndex >= 0) {
+ el.focus();
+ return;
+ }
+ }
+ }
}
messageBox.alert = text =>
diff --git a/options.html b/options.html
index 8b00b659..5d5b6895 100644
--- a/options.html
+++ b/options.html
@@ -116,12 +116,12 @@