more things made focusable

* mozilla-format (i) icon
* showHelp() restores original focus
* showHelp's nested confirmation is debounced to enable focusing Yes/No
* RegExp tester tab URLs are focusable now
This commit is contained in:
tophf 2017-12-13 07:33:16 +03:00
parent fd4300f841
commit 6ee952f3d3
4 changed files with 54 additions and 32 deletions

View File

@ -207,8 +207,8 @@
</div> </div>
<div id="mozilla-format-container"> <div id="mozilla-format-container">
<h2 id="mozilla-format-heading" i18n-text="styleMozillaFormatHeading"> <h2 id="mozilla-format-heading" i18n-text="styleMozillaFormatHeading">
<a class="svg-inline-wrapper" href="#"> <a id="to-mozilla-help" class="svg-inline-wrapper" href="#">
<svg id="to-mozilla-help" class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg> <svg class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg>
</a> </a>
</h2> </h2>
<button id="from-mozilla" i18n-text="importLabel"></button> <button id="from-mozilla" i18n-text="importLabel"></button>

View File

@ -377,7 +377,7 @@ html:not(.usercss) .applies-to li:last-child .add-applies-to {
.has-regexp .test-regexp { .has-regexp .test-regexp {
display: inline-block; display: inline-block;
} }
.regexp-report summary, .regexp-report div { .regexp-report summary {
cursor: pointer; cursor: pointer;
} }
.regexp-report mark { .regexp-report mark {
@ -414,11 +414,17 @@ html:not(.usercss) .applies-to li:last-child .add-applies-to {
position: absolute; position: absolute;
margin-top: -1px; margin-top: -1px;
} }
.regexp-report details div:hover { .regexp-report details a {
color: inherit;
text-decoration: none;
display: block;
cursor: pointer;
}
.regexp-report details a:hover {
text-decoration: underline; text-decoration: underline;
text-decoration-skip: ink; text-decoration-skip: ink;
} }
.regexp-report details div img { .regexp-report details a img {
width: 16px; width: 16px;
max-height: 16px; max-height: 16px;
position: absolute; position: absolute;

View File

@ -516,23 +516,16 @@ function showToggleStyleHelp(event) {
function showHelp(title = '', body) { function showHelp(title = '', body) {
const div = $('#help-popup'); const div = $('#help-popup');
div.className = ''; div.className = '';
const contents = $('.contents', div); const contents = $('.contents', div);
contents.textContent = ''; contents.textContent = '';
if (body) { if (body) {
contents.appendChild(typeof body === 'string' ? tHTML(body) : body); contents.appendChild(typeof body === 'string' ? tHTML(body) : body);
} }
$('.title', div).textContent = title; $('.title', div).textContent = title;
if (getComputedStyle(div).display === 'none') { showHelp.close = showHelp.close || (event => {
window.addEventListener('keydown', closeHelp, true);
// avoid chaining on multiple showHelp() calls
$('.dismiss', div).onclick = closeHelp;
}
// reset any inline styles
div.style = 'display: block';
return div;
function closeHelp(event) {
const canClose = const canClose =
!event || !event ||
event.type === 'click' || event.type === 'click' ||
@ -549,16 +542,32 @@ function showHelp(title = '', body) {
return; return;
} }
if (event && div.codebox && !div.codebox.options.readOnly && !div.codebox.isClean()) { if (event && div.codebox && !div.codebox.options.readOnly && !div.codebox.isClean()) {
messageBox.confirm(t('confirmDiscardChanges')).then(ok => ok && closeHelp()); setTimeout(() => {
messageBox.confirm(t('confirmDiscardChanges'))
.then(ok => ok && showHelp.close());
});
return; return;
} }
if (div.contains(document.activeElement) && showHelp.originalFocus) {
showHelp.originalFocus.focus();
}
div.style.display = ''; div.style.display = '';
contents.textContent = ''; contents.textContent = '';
clearTimeout(contents.timer); clearTimeout(contents.timer);
window.removeEventListener('keydown', closeHelp, true); window.removeEventListener('keydown', showHelp.close, true);
window.dispatchEvent(new Event('closeHelp')); window.dispatchEvent(new Event('closeHelp'));
(editors.lastActive || editors[0]).focus(); });
if (getComputedStyle(div).display === 'none') {
window.addEventListener('keydown', showHelp.close, true);
$('.dismiss', div).onclick = showHelp.close;
} }
// reset any inline styles
div.style = 'display: block';
showHelp.originalFocus = document.activeElement;
return div;
} }
function showCodeMirrorPopup(title, html, options) { function showCodeMirrorPopup(title, html, options) {

View File

@ -110,12 +110,12 @@ var regExpTester = (() => {
: GET_FAVICON_URL + new URL(url).hostname; : GET_FAVICON_URL + new URL(url).hostname;
const icon = $create('img', {src: faviconUrl}); const icon = $create('img', {src: faviconUrl});
if (match.text.length === url.length) { if (match.text.length === url.length) {
full.push($create('div', [ full.push($create('a', {href: '#'}, [
icon, icon,
url, url,
])); ]));
} else { } else {
partial.push($create('div', [ partial.push($create('a', {href: '#'}, [
icon, icon,
url.substr(0, match.pos), url.substr(0, match.pos),
$create('mark', match.text), $create('mark', match.text),
@ -161,25 +161,32 @@ var regExpTester = (() => {
} }
} }
showHelp(t('styleRegexpTestTitle'), report); showHelp(t('styleRegexpTestTitle'), report);
report.onclick = onClick;
const note = $create('p.regexp-report-note', const note = $create('p.regexp-report-note',
t('styleRegexpTestNote') t('styleRegexpTestNote')
.split(/(\\+)/) .split(/(\\+)/)
.map(s => (s.startsWith('\\') ? $create('code', s) : s))); .map(s => (s.startsWith('\\') ? $create('code', s) : s)));
report.appendChild(note); report.appendChild(note);
report.style.paddingBottom = note.offsetHeight + 'px'; adjustNote(report, note);
});
report.onclick = event => { function onClick(event) {
const target = event.target.closest('a, .regexp-report div'); const a = event.target.closest('a');
if (target) { if (a) {
event.preventDefault();
openURL({ openURL({
url: target.href || target.textContent, url: a.href && a.getAttribute('href') !== '#' && a.href || a.textContent,
currentWindow: null, currentWindow: null,
}); });
event.preventDefault(); } else if (event.target.closest('details')) {
setTimeout(adjustNote);
}
}
function adjustNote(report, note) {
report.style.paddingBottom = note.offsetHeight + 'px';
} }
};
});
} }
return {toggle, update}; return {toggle, update};