tweak editor (#1063)
* also apply live-preview if an unsaved style was disabled * use box-shadow instead of outline for focus everywhere * allow focus outline on click in text/search input or textarea * search inputs should use the same style as text inputs * also use box-shadow focus on delete buttons * remove URLSearchParams workaround, not needed since Chrome 55 * use `once` in addEventListener, available since Chrome 55 * update USO bug workarounds, remove obsolete ones * ping/pong to fix openURL with `message` in FF * use unprefixed CSS filter, available since Chrome 53 * use unprefixed CSS user-select, available since Chrome 54 * focus tweaks * also use text query in inline search for Stylus category * use event.key, available since Chrome 51 Co-authored-by: narcolepticinsomniac
This commit is contained in:
parent
60fc6f2456
commit
9e487b03e5
|
@ -66,11 +66,13 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
|
||||||
/* Same as openURL, the only extra prop in `opts` is `message` - it'll be sent when the tab is ready,
|
/* Same as openURL, the only extra prop in `opts` is `message` - it'll be sent when the tab is ready,
|
||||||
which is needed in the popup, otherwise another extension could force the tab to open in foreground
|
which is needed in the popup, otherwise another extension could force the tab to open in foreground
|
||||||
thus auto-closing the popup (in Chrome at least) and preventing the sendMessage code from running */
|
thus auto-closing the popup (in Chrome at least) and preventing the sendMessage code from running */
|
||||||
openURL(opts) {
|
async openURL(opts) {
|
||||||
const {message} = opts;
|
const tab = await openURL(opts);
|
||||||
return openURL(opts) // will pass the resolved value untouched when `message` is absent or falsy
|
if (opts.message) {
|
||||||
.then(message && (tab => tab.status === 'complete' ? tab : onTabReady(tab)))
|
await onTabReady(tab);
|
||||||
.then(message && (tab => msg.sendTab(tab.id, opts.message)));
|
await msg.sendTab(tab.id, opts.message);
|
||||||
|
}
|
||||||
|
return tab;
|
||||||
function onTabReady(tab) {
|
function onTabReady(tab) {
|
||||||
return new Promise((resolve, reject) =>
|
return new Promise((resolve, reject) =>
|
||||||
setTimeout(function ping(numTries = 10, delay = 100) {
|
setTimeout(function ping(numTries = 10, delay = 100) {
|
||||||
|
@ -297,13 +299,10 @@ function openEditor(params) {
|
||||||
'url-prefix'?: String
|
'url-prefix'?: String
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const searchParams = new URLSearchParams();
|
const u = new URL(chrome.runtime.getURL('edit.html'));
|
||||||
for (const key in params) {
|
u.search = new URLSearchParams(params);
|
||||||
searchParams.set(key, params[key]);
|
|
||||||
}
|
|
||||||
const search = searchParams.toString();
|
|
||||||
return openURL({
|
return openURL({
|
||||||
url: 'edit.html' + (search && `?${search}`),
|
url: `${u}`,
|
||||||
newWindow: prefs.get('openEditInWindow'),
|
newWindow: prefs.get('openEditInWindow'),
|
||||||
windowPosition: prefs.get('windowPosition'),
|
windowPosition: prefs.get('windowPosition'),
|
||||||
currentWindow: null
|
currentWindow: null
|
||||||
|
|
|
@ -37,7 +37,7 @@ const tokenManager = (() => {
|
||||||
scopes: ['https://www.googleapis.com/auth/drive.appdata'],
|
scopes: ['https://www.googleapis.com/auth/drive.appdata'],
|
||||||
revoke: token => {
|
revoke: token => {
|
||||||
const params = {token};
|
const params = {token};
|
||||||
return postQuery(`https://accounts.google.com/o/oauth2/revoke?${stringifyQuery(params)}`);
|
return postQuery(`https://accounts.google.com/o/oauth2/revoke?${new URLSearchParams(params)}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onedrive: {
|
onedrive: {
|
||||||
|
@ -137,14 +137,6 @@ const tokenManager = (() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringifyQuery(obj) {
|
|
||||||
const search = new URLSearchParams();
|
|
||||||
for (const key of Object.keys(obj)) {
|
|
||||||
search.set(key, obj[key]);
|
|
||||||
}
|
|
||||||
return search.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function authUser(name, k, interactive = false) {
|
function authUser(name, k, interactive = false) {
|
||||||
const provider = AUTH[name];
|
const provider = AUTH[name];
|
||||||
const state = Math.random().toFixed(8).slice(2);
|
const state = Math.random().toFixed(8).slice(2);
|
||||||
|
@ -160,7 +152,7 @@ const tokenManager = (() => {
|
||||||
if (provider.authQuery) {
|
if (provider.authQuery) {
|
||||||
Object.assign(query, provider.authQuery);
|
Object.assign(query, provider.authQuery);
|
||||||
}
|
}
|
||||||
const url = `${provider.authURL}?${stringifyQuery(query)}`;
|
const url = `${provider.authURL}?${new URLSearchParams(query)}`;
|
||||||
return webextLaunchWebAuthFlow({
|
return webextLaunchWebAuthFlow({
|
||||||
url,
|
url,
|
||||||
interactive,
|
interactive,
|
||||||
|
@ -211,11 +203,9 @@ const tokenManager = (() => {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
}
|
},
|
||||||
|
body: body ? new URLSearchParams(body) : null,
|
||||||
};
|
};
|
||||||
if (body) {
|
|
||||||
options.body = stringifyQuery(body);
|
|
||||||
}
|
|
||||||
return fetch(url, options)
|
return fetch(url, options)
|
||||||
.then(r => {
|
.then(r => {
|
||||||
if (r.ok) {
|
if (r.ok) {
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
/* global cloneInto msg API */
|
/* global cloneInto msg API */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
(() => {
|
// eslint-disable-next-line no-unused-expressions
|
||||||
|
/^\/styles\/(\d+)(\/([^/]*))?([?#].*)?$/.test(location.pathname) && (() => {
|
||||||
|
const styleId = RegExp.$1;
|
||||||
|
const pageEventId = `${performance.now()}${Math.random()}`;
|
||||||
|
|
||||||
window.dispatchEvent(new CustomEvent(chrome.runtime.id + '-install'));
|
window.dispatchEvent(new CustomEvent(chrome.runtime.id + '-install'));
|
||||||
window.addEventListener(chrome.runtime.id + '-install', orphanCheck, true);
|
window.addEventListener(chrome.runtime.id + '-install', orphanCheck, true);
|
||||||
|
|
||||||
|
@ -17,35 +21,18 @@
|
||||||
}, '*');
|
}, '*');
|
||||||
});
|
});
|
||||||
|
|
||||||
let gotBody = false;
|
|
||||||
let currentMd5;
|
let currentMd5;
|
||||||
new MutationObserver(observeDOM).observe(document.documentElement, {
|
const md5Url = getMeta('stylish-md5-url') || `https://update.userstyles.org/${styleId}.md5`;
|
||||||
childList: true,
|
Promise.all([
|
||||||
subtree: true,
|
API.findStyle({md5Url}),
|
||||||
});
|
getResource(md5Url),
|
||||||
observeDOM();
|
onDOMready(),
|
||||||
|
]).then(checkUpdatability);
|
||||||
|
|
||||||
function observeDOM() {
|
document.documentElement.appendChild(
|
||||||
if (!gotBody) {
|
Object.assign(document.createElement('script'), {
|
||||||
if (!document.body) return;
|
textContent: `(${inPageContext})('${pageEventId}')`,
|
||||||
gotBody = true;
|
}));
|
||||||
// TODO: remove the following statement when USO pagination title is fixed
|
|
||||||
document.title = document.title.replace(/^(\d+)&\w+=/, '#$1: ');
|
|
||||||
const md5Url = getMeta('stylish-md5-url') || location.href;
|
|
||||||
Promise.all([
|
|
||||||
API.findStyle({md5Url}),
|
|
||||||
getResource(md5Url)
|
|
||||||
])
|
|
||||||
.then(checkUpdatability);
|
|
||||||
}
|
|
||||||
if (document.getElementById('install_button')) {
|
|
||||||
onDOMready().then(() => {
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
sendEvent(sendEvent.lastEvent);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMessage(msg) {
|
function onMessage(msg) {
|
||||||
switch (msg.method) {
|
switch (msg.method) {
|
||||||
|
@ -72,7 +59,7 @@
|
||||||
|
|
||||||
function checkUpdatability([installedStyle, md5]) {
|
function checkUpdatability([installedStyle, md5]) {
|
||||||
// TODO: remove the following statement when USO is fixed
|
// TODO: remove the following statement when USO is fixed
|
||||||
document.dispatchEvent(new CustomEvent('stylusFixBuggyUSOsettings', {
|
document.dispatchEvent(new CustomEvent(pageEventId, {
|
||||||
detail: installedStyle && installedStyle.updateUrl,
|
detail: installedStyle && installedStyle.updateUrl,
|
||||||
}));
|
}));
|
||||||
currentMd5 = md5;
|
currentMd5 = md5;
|
||||||
|
@ -141,7 +128,6 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function onClick(event) {
|
function onClick(event) {
|
||||||
if (onClick.processing || !orphanCheck()) {
|
if (onClick.processing || !orphanCheck()) {
|
||||||
return;
|
return;
|
||||||
|
@ -227,13 +213,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getMeta(name) {
|
function getMeta(name) {
|
||||||
const e = document.querySelector(`link[rel="${name}"]`);
|
const e = document.querySelector(`link[rel="${name}"]`);
|
||||||
return e ? e.getAttribute('href') : null;
|
return e ? e.getAttribute('href') : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getResource(url, options) {
|
function getResource(url, options) {
|
||||||
if (url.startsWith('#')) {
|
if (url.startsWith('#')) {
|
||||||
return Promise.resolve(document.getElementById(url.slice(1)).textContent);
|
return Promise.resolve(document.getElementById(url.slice(1)).textContent);
|
||||||
|
@ -280,7 +264,6 @@
|
||||||
.catch(() => null);
|
.catch(() => null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function styleSectionsEqual({sections: a}, {sections: b}) {
|
function styleSectionsEqual({sections: a}, {sections: b}) {
|
||||||
if (!a || !b) {
|
if (!a || !b) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -318,20 +301,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function onDOMready() {
|
function onDOMready() {
|
||||||
if (document.readyState !== 'loading') {
|
return document.readyState !== 'loading'
|
||||||
return Promise.resolve();
|
? Promise.resolve()
|
||||||
}
|
: new Promise(resolve => document.addEventListener('DOMContentLoaded', resolve, {once: true}));
|
||||||
return new Promise(resolve => {
|
|
||||||
document.addEventListener('DOMContentLoaded', function _() {
|
|
||||||
document.removeEventListener('DOMContentLoaded', _);
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function openSettings(countdown = 10e3) {
|
function openSettings(countdown = 10e3) {
|
||||||
const button = document.querySelector('.customize_button');
|
const button = document.querySelector('.customize_button');
|
||||||
if (button) {
|
if (button) {
|
||||||
|
@ -349,12 +324,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function orphanCheck() {
|
function orphanCheck() {
|
||||||
// TODO: switch to install-hook-usercss.js impl, and remove explicit orphanCheck() calls
|
try {
|
||||||
if (chrome.i18n && chrome.i18n.getUILanguage()) {
|
if (chrome.i18n.getUILanguage()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} catch (e) {}
|
||||||
// In Chrome content script is orphaned on an extension update/reload
|
// In Chrome content script is orphaned on an extension update/reload
|
||||||
// so we need to detach event listeners
|
// so we need to detach event listeners
|
||||||
window.removeEventListener(chrome.runtime.id + '-install', orphanCheck, true);
|
window.removeEventListener(chrome.runtime.id + '-install', orphanCheck, true);
|
||||||
|
@ -366,132 +341,56 @@
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// run in page context
|
function inPageContext(eventId) {
|
||||||
document.documentElement.appendChild(document.createElement('script')).text = '(' + (
|
document.currentScript.remove();
|
||||||
() => {
|
const origMethods = {
|
||||||
document.currentScript.remove();
|
json: Response.prototype.json,
|
||||||
|
byId: document.getElementById,
|
||||||
// spoof Stylish extension presence in Chrome
|
};
|
||||||
if (window.chrome && chrome.app) {
|
let vars;
|
||||||
const realImage = window.Image;
|
// USO bug workaround: prevent errors in console after install and busy cursor
|
||||||
window.Image = function Image(...args) {
|
document.getElementById = id =>
|
||||||
return new Proxy(new realImage(...args), {
|
origMethods.byId.call(document, id) ||
|
||||||
get(obj, key) {
|
(/^(stylish-code|stylish-installed-style-installed-\w+|post-install-ad|style-install-unknown)$/.test(id)
|
||||||
return obj[key];
|
? Object.assign(document.createElement('p'), {className: 'afterdownload-ad'})
|
||||||
},
|
: null);
|
||||||
set(obj, key, value) {
|
// USO bug workaround: use the actual image data in customized settings
|
||||||
if (key === 'src' && /^chrome-extension:/i.test(value)) {
|
document.addEventListener(eventId, ({detail}) => {
|
||||||
setTimeout(() => typeof obj.onload === 'function' && obj.onload());
|
vars = /\?/.test(detail) && new URL(detail).searchParams;
|
||||||
} else {
|
if (!vars) Response.prototype.json = origMethods.json;
|
||||||
obj[key] = value;
|
}, {once: true});
|
||||||
}
|
Response.prototype.json = async function () {
|
||||||
return true;
|
const json = await origMethods.json.apply(this, arguments);
|
||||||
},
|
if (vars && json && Array.isArray(json.style_settings)) {
|
||||||
});
|
Response.prototype.json = origMethods.json;
|
||||||
};
|
const images = new Map();
|
||||||
}
|
for (const ss of json.style_settings) {
|
||||||
|
const value = vars.get('ik-' + ss.install_key);
|
||||||
// USO bug workaround: use the actual style settings in API response
|
if (value && ss.setting_type === 'image' && ss.style_setting_options) {
|
||||||
let settings;
|
let isListed;
|
||||||
const originalResponseJson = Response.prototype.json;
|
for (const opt of ss.style_setting_options) {
|
||||||
document.addEventListener('stylusFixBuggyUSOsettings', function _({detail}) {
|
isListed |= opt.default = (opt.value === value);
|
||||||
document.removeEventListener('stylusFixBuggyUSOsettings', _);
|
}
|
||||||
// TODO: remove .replace(/^\?/, '') when minimum_chrome_version >= 52 (https://crbug.com/601425)
|
images.set(ss.install_key, {url: value, isListed});
|
||||||
settings = /\?/.test(detail) && new URLSearchParams(new URL(detail).search.replace(/^\?/, ''));
|
}
|
||||||
if (!settings) {
|
|
||||||
Response.prototype.json = originalResponseJson;
|
|
||||||
}
|
}
|
||||||
});
|
if (images.size) {
|
||||||
Response.prototype.json = function (...args) {
|
new MutationObserver((_, observer) => {
|
||||||
return originalResponseJson.call(this, ...args).then(json => {
|
if (document.getElementById('style-settings')) {
|
||||||
if (!settings || typeof ((json || {}).style_settings || {}).every !== 'function') {
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
Response.prototype.json = originalResponseJson;
|
|
||||||
const images = new Map();
|
|
||||||
for (const jsonSetting of json.style_settings) {
|
|
||||||
let value = settings.get('ik-' + jsonSetting.install_key);
|
|
||||||
if (!value
|
|
||||||
|| !jsonSetting.style_setting_options
|
|
||||||
|| !jsonSetting.style_setting_options[0]) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (value.startsWith('ik-')) {
|
|
||||||
value = value.replace(/^ik-/, '');
|
|
||||||
const defaultItem = jsonSetting.style_setting_options.find(item => item.default);
|
|
||||||
if (!defaultItem || defaultItem.install_key !== value) {
|
|
||||||
if (defaultItem) {
|
|
||||||
defaultItem.default = false;
|
|
||||||
}
|
|
||||||
jsonSetting.style_setting_options.some(item => {
|
|
||||||
if (item.install_key === value) {
|
|
||||||
item.default = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (jsonSetting.setting_type === 'image') {
|
|
||||||
jsonSetting.style_setting_options.some(item => {
|
|
||||||
if (item.default) {
|
|
||||||
item.default = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
images.set(jsonSetting.install_key, value);
|
|
||||||
} else {
|
|
||||||
const item = jsonSetting.style_setting_options[0];
|
|
||||||
if (item.value !== value && item.install_key === 'placeholder') {
|
|
||||||
item.value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (images.size) {
|
|
||||||
new MutationObserver((_, observer) => {
|
|
||||||
if (!document.getElementById('style-settings')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
for (const [name, url] of images.entries()) {
|
for (const [name, {url, isListed}] of images) {
|
||||||
const elRadio = document.querySelector(`input[name="ik-${name}"][value="user-url"]`);
|
const elRadio = document.querySelector(`input[name="ik-${name}"][value="user-url"]`);
|
||||||
const elUrl = elRadio && document.getElementById(elRadio.id.replace('url-choice', 'user-url'));
|
const elUrl = elRadio &&
|
||||||
|
document.getElementById(elRadio.id.replace('url-choice', 'user-url'));
|
||||||
if (elUrl) {
|
if (elUrl) {
|
||||||
|
elRadio.checked = !isListed;
|
||||||
elUrl.value = url;
|
elUrl.value = url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).observe(document, {childList: true, subtree: true});
|
}
|
||||||
}
|
}).observe(document, {childList: true, subtree: true});
|
||||||
return json;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
) + `)('${chrome.runtime.getURL('').slice(0, -1)}')`;
|
|
||||||
|
|
||||||
// TODO: remove the following statement when USO pagination is fixed
|
|
||||||
if (location.search.includes('category=')) {
|
|
||||||
document.addEventListener('DOMContentLoaded', function _() {
|
|
||||||
document.removeEventListener('DOMContentLoaded', _);
|
|
||||||
new MutationObserver((_, observer) => {
|
|
||||||
if (!document.getElementById('pagination')) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
observer.disconnect();
|
|
||||||
const category = '&' + location.search.match(/category=[^&]+/)[0];
|
|
||||||
const links = document.querySelectorAll('#pagination a[href*="page="]:not([href*="category="])');
|
|
||||||
for (let i = 0; i < links.length; i++) {
|
|
||||||
links[i].href += category;
|
|
||||||
}
|
|
||||||
}).observe(document, {childList: true, subtree: true});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (/^https?:\/\/userstyles\.org\/styles\/\d{3,}/.test(location.href)) {
|
|
||||||
new MutationObserver((_, observer) => {
|
|
||||||
const cssButton = document.getElementsByClassName('css_button');
|
|
||||||
if (cssButton.length) {
|
|
||||||
// Click on the "Show CSS Code" button to workaround the JS error
|
|
||||||
cssButton[0].click();
|
|
||||||
cssButton[0].click();
|
|
||||||
observer.disconnect();
|
|
||||||
}
|
}
|
||||||
}).observe(document, {childList: true, subtree: true});
|
return json;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,12 @@
|
||||||
}
|
}
|
||||||
.CodeMirror {
|
.CodeMirror {
|
||||||
border: solid #CCC 1px;
|
border: solid #CCC 1px;
|
||||||
|
transition: box-shadow .1s;
|
||||||
|
}
|
||||||
|
#stylus#stylus .CodeMirror {
|
||||||
|
/* Using a specificity hack to override userstyles */
|
||||||
|
/* Not using the ring-color hack as it became ugly in new Chrome */
|
||||||
|
outline: none !important;
|
||||||
}
|
}
|
||||||
.CodeMirror-lint-mark-warning {
|
.CodeMirror-lint-mark-warning {
|
||||||
background: none;
|
background: none;
|
||||||
|
@ -14,9 +20,6 @@
|
||||||
.CodeMirror-dialog {
|
.CodeMirror-dialog {
|
||||||
-webkit-animation: highlight 3s cubic-bezier(.18, .02, 0, .94);
|
-webkit-animation: highlight 3s cubic-bezier(.18, .02, 0, .94);
|
||||||
}
|
}
|
||||||
.CodeMirror-focused {
|
|
||||||
outline: #7dadd9 auto 1px; /* not using the ring-color hack as it became ugly in new Chrome */
|
|
||||||
}
|
|
||||||
.CodeMirror-bookmark {
|
.CodeMirror-bookmark {
|
||||||
background: linear-gradient(to right, currentColor, transparent);
|
background: linear-gradient(to right, currentColor, transparent);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -611,6 +611,9 @@ body:not(.find-open) [data-match-highlight-count="1"] .CodeMirror-selection-high
|
||||||
right: 4px;
|
right: 4px;
|
||||||
top: .5em;
|
top: .5em;
|
||||||
}
|
}
|
||||||
|
#help-popup input[type="search"] {
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
.keymap-list {
|
.keymap-list {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -788,6 +791,10 @@ body:not(.find-open) [data-match-highlight-count="1"] .CodeMirror-selection-high
|
||||||
justify-items: normal;
|
justify-items: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.usercss .CodeMirror-focused {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
html:not(.usercss) .usercss-only,
|
html:not(.usercss) .usercss-only,
|
||||||
.usercss #mozilla-format-container,
|
.usercss #mozilla-format-container,
|
||||||
.usercss #sections > h2 {
|
.usercss #sections > h2 {
|
||||||
|
|
12
edit/edit.js
12
edit/edit.js
|
@ -352,8 +352,7 @@ function isUsercss(style) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initStyleData() {
|
function initStyleData() {
|
||||||
// TODO: remove .replace(/^\?/, '') when minimum_chrome_version >= 52 (https://crbug.com/601425)
|
const params = new URLSearchParams(location.search);
|
||||||
const params = new URLSearchParams(location.search.replace(/^\?/, ''));
|
|
||||||
const id = Number(params.get('id'));
|
const id = Number(params.get('id'));
|
||||||
const createEmptyStyle = () => ({
|
const createEmptyStyle = () => ({
|
||||||
name: params.get('domain') ||
|
name: params.get('domain') ||
|
||||||
|
@ -409,7 +408,7 @@ function showHelp(title = '', body) {
|
||||||
!event ||
|
!event ||
|
||||||
event.type === 'click' ||
|
event.type === 'click' ||
|
||||||
(
|
(
|
||||||
event.which === 27 &&
|
event.key === 'Escape' &&
|
||||||
!event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey &&
|
!event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey &&
|
||||||
!$('.CodeMirror-hints, #message-box') &&
|
!$('.CodeMirror-hints, #message-box') &&
|
||||||
(
|
(
|
||||||
|
@ -470,7 +469,7 @@ function showCodeMirrorPopup(title, html, options) {
|
||||||
popup.style.pointerEvents = 'auto';
|
popup.style.pointerEvents = 'auto';
|
||||||
|
|
||||||
const onKeyDown = event => {
|
const onKeyDown = event => {
|
||||||
if (event.which === 9 && !event.ctrlKey && !event.altKey && !event.metaKey) {
|
if (event.key === 'Tab' && !event.ctrlKey && !event.altKey && !event.metaKey) {
|
||||||
const search = $('#search-replace-dialog');
|
const search = $('#search-replace-dialog');
|
||||||
const area = search && search.contains(document.activeElement) ? search : popup;
|
const area = search && search.contains(document.activeElement) ? search : popup;
|
||||||
moveFocus(area, event.shiftKey ? -1 : 1);
|
moveFocus(area, event.shiftKey ? -1 : 1);
|
||||||
|
@ -479,13 +478,12 @@ function showCodeMirrorPopup(title, html, options) {
|
||||||
};
|
};
|
||||||
window.addEventListener('keydown', onKeyDown, true);
|
window.addEventListener('keydown', onKeyDown, true);
|
||||||
|
|
||||||
window.addEventListener('closeHelp', function _() {
|
window.addEventListener('closeHelp', () => {
|
||||||
window.removeEventListener('closeHelp', _);
|
|
||||||
window.removeEventListener('keydown', onKeyDown, true);
|
window.removeEventListener('keydown', onKeyDown, true);
|
||||||
document.documentElement.style.removeProperty('pointer-events');
|
document.documentElement.style.removeProperty('pointer-events');
|
||||||
rerouteHotkeys(true);
|
rerouteHotkeys(true);
|
||||||
cm = popup.codebox = null;
|
cm = popup.codebox = null;
|
||||||
});
|
}, {once: true});
|
||||||
|
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,11 +53,10 @@
|
||||||
cm.on('changes', updateButtonState);
|
cm.on('changes', updateButtonState);
|
||||||
|
|
||||||
rerouteHotkeys(false);
|
rerouteHotkeys(false);
|
||||||
window.addEventListener('closeHelp', function _() {
|
window.addEventListener('closeHelp', () => {
|
||||||
window.removeEventListener('closeHelp', _);
|
|
||||||
rerouteHotkeys(true);
|
rerouteHotkeys(true);
|
||||||
cm = null;
|
cm = null;
|
||||||
});
|
}, {once: true});
|
||||||
|
|
||||||
loadScript([
|
loadScript([
|
||||||
'/vendor/codemirror/mode/javascript/javascript.js',
|
'/vendor/codemirror/mode/javascript/javascript.js',
|
||||||
|
|
|
@ -10,7 +10,7 @@ function createLivePreview(preprocess) {
|
||||||
const errorContainer = $('#preview-errors');
|
const errorContainer = $('#preview-errors');
|
||||||
|
|
||||||
prefs.subscribe(['editor.livePreview'], (key, value) => {
|
prefs.subscribe(['editor.livePreview'], (key, value) => {
|
||||||
if (value && data && data.id && data.enabled) {
|
if (value && data && data.id && (data.enabled || editor.dirty.has('enabled'))) {
|
||||||
previewer = createPreviewer();
|
previewer = createPreviewer();
|
||||||
previewer.update(data);
|
previewer.update(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,36 +206,32 @@ function createSection({
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleKeydown(cm, event) {
|
function handleKeydown(cm, event) {
|
||||||
const key = event.which;
|
if (event.shiftKey || event.altKey || event.metaKey) {
|
||||||
if (key < 37 || key > 40 || event.shiftKey || event.altKey || event.metaKey) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const {key} = event;
|
||||||
const {line, ch} = cm.getCursor();
|
const {line, ch} = cm.getCursor();
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 37:
|
case 'ArrowLeft':
|
||||||
// arrow Left
|
|
||||||
if (line || ch) {
|
if (line || ch) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// fallthrough to arrow Up
|
// fallthrough
|
||||||
case 38:
|
case 'ArrowUp':
|
||||||
// arrow Up
|
|
||||||
cm = line === 0 && prevEditor(cm, false);
|
cm = line === 0 && prevEditor(cm, false);
|
||||||
if (!cm) {
|
if (!cm) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
cm.setCursor(cm.doc.size - 1, key === 37 ? 1e20 : ch);
|
cm.setCursor(cm.doc.size - 1, key === 'ArrowLeft' ? 1e20 : ch);
|
||||||
break;
|
break;
|
||||||
case 39:
|
case 'ArrowRight':
|
||||||
// arrow Right
|
|
||||||
if (line < cm.doc.size - 1 || ch < cm.getLine(line).length - 1) {
|
if (line < cm.doc.size - 1 || ch < cm.getLine(line).length - 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// fallthrough to arrow Down
|
// fallthrough
|
||||||
case 40:
|
case 'ArrowDown':
|
||||||
// arrow Down
|
|
||||||
cm = line === cm.doc.size - 1 && nextEditor(cm, false);
|
cm = line === cm.doc.size - 1 && nextEditor(cm, false);
|
||||||
if (!cm) {
|
if (!cm) {
|
||||||
return;
|
return;
|
||||||
|
@ -245,13 +241,6 @@ function createSection({
|
||||||
cm.setCursor(0, 0);
|
cm.setCursor(0, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// FIXME: what is this?
|
|
||||||
// const animation = (cm.getSection().firstElementChild.getAnimations() || [])[0];
|
|
||||||
// if (animation) {
|
|
||||||
// animation.playbackRate = -1;
|
|
||||||
// animation.currentTime = 2000;
|
|
||||||
// animation.play();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAppliesToHelp(event) {
|
function showAppliesToHelp(event) {
|
||||||
|
|
18
global.css
18
global.css
|
@ -54,18 +54,20 @@ button:active {
|
||||||
border-color: hsl(0, 0%, 50%);
|
border-color: hsl(0, 0%, 50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
|
border: 1px solid hsl(0, 0%, 66%);
|
||||||
|
transition: border-color .1s, box-shadow .1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:not([type]) {
|
input:not([type]),
|
||||||
|
input[type=search] {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
color: #000;
|
color: #000;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
min-height: 22px!important;
|
min-height: 22px!important;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
font: inherit;
|
|
||||||
border: 1px solid hsl(0, 0%, 66%);
|
border: 1px solid hsl(0, 0%, 66%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,9 +210,19 @@ select[disabled] + .select-arrow {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:focus,
|
||||||
|
.CodeMirror-focused,
|
||||||
|
[data-focused-via-click] input[type="text"]:focus,
|
||||||
|
[data-focused-via-click] input[type="number"]:focus {
|
||||||
|
/* Using box-shadow instead of the ugly outline in new Chrome */
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 1px hsl(180, 100%, 38%), 0 0 3px hsla(180, 100%, 60%, .5);
|
||||||
|
}
|
||||||
|
|
||||||
[data-focused-via-click] :focus,
|
[data-focused-via-click] :focus,
|
||||||
[data-focused-via-click]:focus {
|
[data-focused-via-click]:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@supports (-moz-appearance: none) {
|
@supports (-moz-appearance: none) {
|
||||||
|
|
|
@ -288,9 +288,7 @@ li {
|
||||||
|
|
||||||
#header:not(.meta-init) > *:not(.lds-spinner),
|
#header:not(.meta-init) > *:not(.lds-spinner),
|
||||||
#header.meta-init > .lds-spinner {
|
#header.meta-init > .lds-spinner {
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
@ -299,9 +297,7 @@ li {
|
||||||
#header.meta-init > * {
|
#header.meta-init > * {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transition: opacity .5s;
|
transition: opacity .5s;
|
||||||
-webkit-user-select: auto;
|
|
||||||
-moz-user-select: auto;
|
-moz-user-select: auto;
|
||||||
-ms-user-select: auto;
|
|
||||||
user-select: auto;
|
user-select: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
// TODO: remove .replace(/^\?/, '') when minimum_chrome_version >= 52 (https://crbug.com/601425)
|
const params = new URLSearchParams(location.search);
|
||||||
const params = new URLSearchParams(location.search.replace(/^\?/, ''));
|
|
||||||
const tabId = params.has('tabId') ? Number(params.get('tabId')) : -1;
|
const tabId = params.has('tabId') ? Number(params.get('tabId')) : -1;
|
||||||
const initialUrl = params.get('updateUrl');
|
const initialUrl = params.get('updateUrl');
|
||||||
|
|
||||||
|
|
31
js/dom.js
31
js/dom.js
|
@ -20,6 +20,9 @@ for (const type of [NodeList, NamedNodeMap, HTMLCollection, HTMLAllCollection])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$.isTextLikeInput = el =>
|
||||||
|
el.localName === 'input' && /^(text|search|number)$/.test(el.type);
|
||||||
|
|
||||||
$.remove = (selector, base = document) => {
|
$.remove = (selector, base = document) => {
|
||||||
const el = selector && typeof selector === 'string' ? $(selector, base) : selector;
|
const el = selector && typeof selector === 'string' ? $(selector, base) : selector;
|
||||||
if (el) {
|
if (el) {
|
||||||
|
@ -112,15 +115,9 @@ document.addEventListener('wheel', event => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function onDOMready() {
|
function onDOMready() {
|
||||||
if (document.readyState !== 'loading') {
|
return document.readyState !== 'loading'
|
||||||
return Promise.resolve();
|
? Promise.resolve()
|
||||||
}
|
: new Promise(resolve => document.addEventListener('DOMContentLoaded', resolve, {once: true}));
|
||||||
return new Promise(resolve => {
|
|
||||||
document.addEventListener('DOMContentLoaded', function _() {
|
|
||||||
document.removeEventListener('DOMContentLoaded', _);
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,8 +141,7 @@ function animateElement(
|
||||||
onComplete,
|
onComplete,
|
||||||
} = {}) {
|
} = {}) {
|
||||||
return element && new Promise(resolve => {
|
return element && new Promise(resolve => {
|
||||||
element.addEventListener('animationend', function _() {
|
element.addEventListener('animationend', () => {
|
||||||
element.removeEventListener('animationend', _);
|
|
||||||
element.classList.remove(
|
element.classList.remove(
|
||||||
className,
|
className,
|
||||||
// In Firefox, `resolve()` might be called one frame later.
|
// In Firefox, `resolve()` might be called one frame later.
|
||||||
|
@ -157,7 +153,7 @@ function animateElement(
|
||||||
onComplete.call(element);
|
onComplete.call(element);
|
||||||
}
|
}
|
||||||
resolve();
|
resolve();
|
||||||
});
|
}, {once: true});
|
||||||
element.classList.add(className);
|
element.classList.add(className);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -355,20 +351,23 @@ function focusAccessibility() {
|
||||||
'a',
|
'a',
|
||||||
'button',
|
'button',
|
||||||
'input',
|
'input',
|
||||||
'textarea',
|
|
||||||
'label',
|
'label',
|
||||||
'select',
|
'select',
|
||||||
'summary',
|
'summary',
|
||||||
];
|
];
|
||||||
// try to find a focusable parent for this many parentElement jumps:
|
// try to find a focusable parent for this many parentElement jumps:
|
||||||
const GIVE_UP_DEPTH = 4;
|
const GIVE_UP_DEPTH = 4;
|
||||||
|
// allow outline on text/search inputs in addition to textareas
|
||||||
|
const isOutlineAllowed = el =>
|
||||||
|
!focusAccessibility.ELEMENTS.includes(el.localName) ||
|
||||||
|
$.isTextLikeInput(el);
|
||||||
|
|
||||||
addEventListener('mousedown', suppressOutlineOnClick, {passive: true});
|
addEventListener('mousedown', suppressOutlineOnClick, {passive: true});
|
||||||
addEventListener('keydown', keepOutlineOnTab, {passive: true});
|
addEventListener('keydown', keepOutlineOnTab, {passive: true});
|
||||||
|
|
||||||
function suppressOutlineOnClick({target}) {
|
function suppressOutlineOnClick({target}) {
|
||||||
for (let el = target, i = 0; el && i++ < GIVE_UP_DEPTH; el = el.parentElement) {
|
for (let el = target, i = 0; el && i++ < GIVE_UP_DEPTH; el = el.parentElement) {
|
||||||
if (focusAccessibility.ELEMENTS.includes(el.localName)) {
|
if (!isOutlineAllowed(el)) {
|
||||||
focusAccessibility.lastFocusedViaClick = true;
|
focusAccessibility.lastFocusedViaClick = true;
|
||||||
if (el.dataset.focusedViaClick === undefined) {
|
if (el.dataset.focusedViaClick === undefined) {
|
||||||
el.dataset.focusedViaClick = '';
|
el.dataset.focusedViaClick = '';
|
||||||
|
@ -379,7 +378,7 @@ function focusAccessibility() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function keepOutlineOnTab(event) {
|
function keepOutlineOnTab(event) {
|
||||||
if (event.which === 9) {
|
if (event.key === 'Tab') {
|
||||||
focusAccessibility.lastFocusedViaClick = false;
|
focusAccessibility.lastFocusedViaClick = false;
|
||||||
setTimeout(keepOutlineOnTab, 0, true);
|
setTimeout(keepOutlineOnTab, 0, true);
|
||||||
return;
|
return;
|
||||||
|
@ -387,7 +386,7 @@ function focusAccessibility() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let el = document.activeElement;
|
let el = document.activeElement;
|
||||||
if (!el || !focusAccessibility.ELEMENTS.includes(el.localName)) {
|
if (!el || isOutlineAllowed(el)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (el.dataset.focusedViaClick !== undefined) {
|
if (el.dataset.focusedViaClick !== undefined) {
|
||||||
|
|
|
@ -62,5 +62,20 @@ self.INJECTED !== 1 && (() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(new URLSearchParams({foo: 1})).get('foo')) {
|
||||||
|
// TODO: remove when minimum_chrome_version >= 61
|
||||||
|
window.URLSearchParams = class extends URLSearchParams {
|
||||||
|
constructor(init) {
|
||||||
|
if (init && typeof init === 'object') {
|
||||||
|
super();
|
||||||
|
for (const [key, val] of Object.entries(init)) {
|
||||||
|
this.set(key, val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super(...arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
})();
|
})();
|
||||||
|
|
20
js/router.js
20
js/router.js
|
@ -31,18 +31,9 @@ const router = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSearch(key, value) {
|
function updateSearch(key, value) {
|
||||||
const search = new URLSearchParams(location.search.replace(/^\?/, ''));
|
const u = new URL(location);
|
||||||
if (!value) {
|
u.searchParams[value ? 'set' : 'delete'](key, value);
|
||||||
search.delete(key);
|
history.replaceState(history.state, null, `${u}`);
|
||||||
} else {
|
|
||||||
search.set(key, value);
|
|
||||||
}
|
|
||||||
const finalSearch = search.toString();
|
|
||||||
if (finalSearch) {
|
|
||||||
history.replaceState(history.state, null, `?${finalSearch}${location.hash}`);
|
|
||||||
} else {
|
|
||||||
history.replaceState(history.state, null, `${location.pathname}${location.hash}`);
|
|
||||||
}
|
|
||||||
update(true);
|
update(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +57,7 @@ const router = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSearch(key) {
|
function getSearch(key) {
|
||||||
return new URLSearchParams(location.search.replace(/^\?/, '')).get(key);
|
return new URLSearchParams(location.search).get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
function update(replace) {
|
function update(replace) {
|
||||||
|
@ -86,8 +77,7 @@ const router = (() => {
|
||||||
if (options.hash) {
|
if (options.hash) {
|
||||||
state = options.hash === location.hash;
|
state = options.hash === location.hash;
|
||||||
} else if (options.search) {
|
} else if (options.search) {
|
||||||
// TODO: remove .replace(/^\?/, '') when minimum_chrome_version >= 52 (https://crbug.com/601425)
|
const search = new URLSearchParams(location.search);
|
||||||
const search = new URLSearchParams(location.search.replace(/^\?/, ''));
|
|
||||||
state = options.search.map(key => search.get(key));
|
state = options.search.map(key => search.get(key));
|
||||||
}
|
}
|
||||||
if (!deepEqual(state, options.currentState)) {
|
if (!deepEqual(state, options.currentState)) {
|
||||||
|
|
|
@ -82,7 +82,7 @@ const loadScript = (() => {
|
||||||
for (const {addedNodes} of mutations) {
|
for (const {addedNodes} of mutations) {
|
||||||
for (const n of addedNodes) {
|
for (const n of addedNodes) {
|
||||||
if (n.src && getSubscribersForSrc(n.src)) {
|
if (n.src && getSubscribersForSrc(n.src)) {
|
||||||
n.addEventListener('load', notifySubscribers);
|
n.addEventListener('load', notifySubscribers, {once: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,6 @@ const loadScript = (() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function notifySubscribers(event) {
|
function notifySubscribers(event) {
|
||||||
this.removeEventListener('load', notifySubscribers);
|
|
||||||
for (let data; (data = getSubscribersForSrc(this.src));) {
|
for (let data; (data = getSubscribersForSrc(this.src));) {
|
||||||
data.listeners.forEach(fn => fn(event));
|
data.listeners.forEach(fn => fn(event));
|
||||||
if (emptyAfterCleanup(data.suffix)) {
|
if (emptyAfterCleanup(data.suffix)) {
|
||||||
|
|
|
@ -24,12 +24,12 @@ onDOMready().then(() => {
|
||||||
document.body.appendChild(input);
|
document.body.appendChild(input);
|
||||||
window.addEventListener('keydown', maybeRefocus, true);
|
window.addEventListener('keydown', maybeRefocus, true);
|
||||||
|
|
||||||
function incrementalSearch({which}, immediately) {
|
function incrementalSearch({key}, immediately) {
|
||||||
if (!immediately) {
|
if (!immediately) {
|
||||||
debounce(incrementalSearch, 100, {}, true);
|
debounce(incrementalSearch, 100, {}, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const direction = which === 38 ? -1 : which === 40 ? 1 : 0;
|
const direction = key === 'ArrowUp' ? -1 : key === 'ArrowDown' ? 1 : 0;
|
||||||
const text = input.value.toLocaleLowerCase();
|
const text = input.value.toLocaleLowerCase();
|
||||||
if (!text.trim() || !direction && (text === prevText || focusedName.startsWith(text))) {
|
if (!text.trim() || !direction && (text === prevText || focusedName.startsWith(text))) {
|
||||||
prevText = text;
|
prevText = text;
|
||||||
|
@ -76,40 +76,31 @@ onDOMready().then(() => {
|
||||||
if (event.altKey || event.metaKey || $('#message-box')) {
|
if (event.altKey || event.metaKey || $('#message-box')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const inTextInput = event.target.matches('[type=text], [type=search], [type=number]');
|
const inTextInput = $.isTextLikeInput(event.target);
|
||||||
const {which: k, key} = event;
|
const {key, code, ctrlKey: ctrl} = event;
|
||||||
// focus search field on "/" or Ctrl-F key
|
// `code` is independent of the current keyboard language
|
||||||
if (event.ctrlKey
|
if ((code === 'KeyF' && ctrl && !event.shiftKey) ||
|
||||||
? (event.code === 'KeyF' || !event.code && k === 70) && !event.shiftKey
|
(code === 'Slash' || key === '/') && !ctrl && !inTextInput) {
|
||||||
: (key === '/' || !key && k === 191 && !event.shiftKey) && !inTextInput) {
|
// focus search field on "/" or Ctrl-F key
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
$('#search').focus();
|
$('#search').focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.ctrlKey || inTextInput) {
|
if (ctrl || inTextInput) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const time = performance.now();
|
const time = performance.now();
|
||||||
if (
|
if (key.length === 1) {
|
||||||
// 0-9
|
|
||||||
k >= 48 && k <= 57 ||
|
|
||||||
// a-z
|
|
||||||
k >= 65 && k <= 90 ||
|
|
||||||
// numpad keys
|
|
||||||
k >= 96 && k <= 111 ||
|
|
||||||
// marks
|
|
||||||
k >= 186
|
|
||||||
) {
|
|
||||||
input.focus();
|
input.focus();
|
||||||
if (time - prevTime > 1000) {
|
if (time - prevTime > 1000) {
|
||||||
input.value = '';
|
input.value = '';
|
||||||
}
|
}
|
||||||
prevTime = time;
|
prevTime = time;
|
||||||
} else
|
} else
|
||||||
if (k === 13 && focusedLink) {
|
if (key === 'Enter' && focusedLink) {
|
||||||
focusedLink.dispatchEvent(new MouseEvent('click', {bubbles: true}));
|
focusedLink.dispatchEvent(new MouseEvent('click', {bubbles: true}));
|
||||||
} else
|
} else
|
||||||
if ((k === 38 || k === 40) && !event.shiftKey &&
|
if ((key === 'ArrowUp' || key === 'ArrowDown') && !event.shiftKey &&
|
||||||
time - prevTime < 5000 && incrementalSearch(event, true)) {
|
time - prevTime < 5000 && incrementalSearch(event, true)) {
|
||||||
prevTime = time;
|
prevTime = time;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -550,8 +550,6 @@ a:hover {
|
||||||
.newUI .update-done .updated svg {
|
.newUI .update-done .updated svg {
|
||||||
top: -4px;
|
top: -4px;
|
||||||
position: relative;
|
position: relative;
|
||||||
/* unprefixed since Chrome 53 */
|
|
||||||
-webkit-filter: drop-shadow(0 4px 0 currentColor);
|
|
||||||
filter: drop-shadow(0 5px 0 currentColor);
|
filter: drop-shadow(0 5px 0 currentColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,8 +661,6 @@ a:hover {
|
||||||
margin-left: -20px;
|
margin-left: -20px;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
transition: opacity .5s, filter .5s;
|
transition: opacity .5s, filter .5s;
|
||||||
/* unprefixed since Chrome 53 */
|
|
||||||
-webkit-filter: grayscale(1);
|
|
||||||
filter: grayscale(1);
|
filter: grayscale(1);
|
||||||
/* workaround for the buggy CSS filter: images in the hidden overflow are shown on Mac */
|
/* workaround for the buggy CSS filter: images in the hidden overflow are shown on Mac */
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
|
@ -682,9 +678,7 @@ a:hover {
|
||||||
|
|
||||||
.newUI .entry:hover .target img {
|
.newUI .entry:hover .target img {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
/* unprefixed since Chrome 53 */
|
filter: none;
|
||||||
-webkit-filter: grayscale(0);
|
|
||||||
filter: grayscale(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default, no update buttons */
|
/* Default, no update buttons */
|
||||||
|
|
|
@ -631,13 +631,11 @@ function switchUI({styleOnly} = {}) {
|
||||||
}
|
}
|
||||||
` + (newUI.faviconsGray ? `
|
` + (newUI.faviconsGray ? `
|
||||||
.newUI .target img {
|
.newUI .target img {
|
||||||
-webkit-filter: grayscale(1);
|
|
||||||
filter: grayscale(1);
|
filter: grayscale(1);
|
||||||
opacity: .25;
|
opacity: .25;
|
||||||
}
|
}
|
||||||
` : `
|
` : `
|
||||||
.newUI .target img {
|
.newUI .target img {
|
||||||
-webkit-filter: none;
|
|
||||||
filter: none;
|
filter: none;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,12 +135,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.danger #message-box-buttons > button:not([data-focused-via-click]):first-child:focus {
|
.danger #message-box-buttons > button:not([data-focused-via-click]):first-child:focus {
|
||||||
outline: red auto 1px;
|
box-shadow: 0 0 0 1px red; /* Using box-shadow instead of the ugly outline in new Chrome */
|
||||||
}
|
|
||||||
|
|
||||||
/* FF ignores color with 'auto' */
|
|
||||||
.firefox .danger #message-box-buttons > button:not([data-focused-via-click]):first-child:focus {
|
|
||||||
outline: red solid 1px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.non-windows #message-box-buttons {
|
.non-windows #message-box-buttons {
|
||||||
|
|
|
@ -62,28 +62,28 @@ function messageBox({
|
||||||
resolveWith({button: this.buttonIndex});
|
resolveWith({button: this.buttonIndex});
|
||||||
},
|
},
|
||||||
key(event) {
|
key(event) {
|
||||||
const {which, shiftKey, ctrlKey, altKey, metaKey, target} = event;
|
const {key, shiftKey, ctrlKey, altKey, metaKey, target} = event;
|
||||||
if (shiftKey && which !== 9 || ctrlKey || altKey || metaKey) {
|
if (shiftKey && key !== 'Tab' || ctrlKey || altKey || metaKey) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (which) {
|
switch (key) {
|
||||||
case 13:
|
case 'Enter':
|
||||||
if (target.closest(focusAccessibility.ELEMENTS.join(','))) {
|
if (target.closest(focusAccessibility.ELEMENTS.join(','))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 27:
|
case 'Escape':
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 'Tab':
|
||||||
moveFocus(messageBox.element, shiftKey ? -1 : 1);
|
moveFocus(messageBox.element, shiftKey ? -1 : 1);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
resolveWith(which === 13 ? {enter: true} : {esc: true});
|
resolveWith(key === 'Enter' ? {enter: true} : {esc: true});
|
||||||
},
|
},
|
||||||
scroll() {
|
scroll() {
|
||||||
scrollTo(blockScroll.x, blockScroll.y);
|
scrollTo(blockScroll.x, blockScroll.y);
|
||||||
|
|
|
@ -3,9 +3,8 @@
|
||||||
.onoffswitch {
|
.onoffswitch {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 1ex 0;
|
margin: 1ex 0;
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.onoffswitch input {
|
.onoffswitch input {
|
||||||
|
@ -17,6 +16,7 @@
|
||||||
bottom: -10px;
|
bottom: -10px;
|
||||||
left: -10px;
|
left: -10px;
|
||||||
width: calc(100% + 12px);
|
width: calc(100% + 12px);
|
||||||
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#message-box .onoffswitch input {
|
#message-box .onoffswitch input {
|
||||||
|
|
|
@ -298,7 +298,7 @@ function customizeHotkeys() {
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onkeydown = event => {
|
window.onkeydown = event => {
|
||||||
if (event.keyCode === 27) {
|
if (event.key === 'Escape') {
|
||||||
top.dispatchEvent(new CustomEvent('closeOptions'));
|
top.dispatchEvent(new CustomEvent('closeOptions'));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,14 +9,13 @@ const hotkeys = (() => {
|
||||||
let enabled = false;
|
let enabled = false;
|
||||||
let ready = false;
|
let ready = false;
|
||||||
|
|
||||||
window.addEventListener('showStyles:done', function _() {
|
window.addEventListener('showStyles:done', () => {
|
||||||
window.removeEventListener('showStyles:done', _);
|
|
||||||
togglablesShown = true;
|
togglablesShown = true;
|
||||||
togglables = getTogglables();
|
togglables = getTogglables();
|
||||||
ready = true;
|
ready = true;
|
||||||
setState(true);
|
setState(true);
|
||||||
initHotkeyInfo();
|
initHotkeyInfo();
|
||||||
});
|
}, {once: true});
|
||||||
|
|
||||||
window.addEventListener('resize', adjustInfoPosition);
|
window.addEventListener('resize', adjustInfoPosition);
|
||||||
|
|
||||||
|
@ -38,40 +37,27 @@ const hotkeys = (() => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let entry;
|
let entry;
|
||||||
const {which: k, key, code} = event;
|
let {key, code, shiftKey} = event;
|
||||||
|
|
||||||
if (code.startsWith('Digit') || code.startsWith('Numpad') && code.length === 7) {
|
if (key >= '0' && key <= '9') {
|
||||||
|
entry = entries[(Number(key) || 10) - 1];
|
||||||
|
} else if (code >= 'Digit0' && code <= 'Digit9') {
|
||||||
entry = entries[(Number(code.slice(-1)) || 10) - 1];
|
entry = entries[(Number(code.slice(-1)) || 10) - 1];
|
||||||
|
} else if (key === '`' || key === '*' || code === 'Backquote' || code === 'NumpadMultiply') {
|
||||||
} else if (
|
|
||||||
code === 'Backquote' || code === 'NumpadMultiply' ||
|
|
||||||
key && (key === '`' || key === '*') ||
|
|
||||||
k === 192 || k === 106) {
|
|
||||||
invertTogglables();
|
invertTogglables();
|
||||||
|
} else if (key === '-' || code === 'NumpadSubtract') {
|
||||||
} else if (
|
|
||||||
code === 'NumpadSubtract' ||
|
|
||||||
key && key === '-' ||
|
|
||||||
k === 109) {
|
|
||||||
toggleState(entries, 'enabled', false);
|
toggleState(entries, 'enabled', false);
|
||||||
|
} else if (key === '+' || code === 'NumpadAdd') {
|
||||||
} else if (
|
|
||||||
code === 'NumpadAdd' ||
|
|
||||||
key && key === '+' ||
|
|
||||||
k === 107) {
|
|
||||||
toggleState(entries, 'disabled', true);
|
toggleState(entries, 'disabled', true);
|
||||||
|
} else if (key.length === 1) {
|
||||||
} else if (
|
shiftKey = false; // typing ':' etc. needs Shift so we hide it here to avoid opening editor
|
||||||
// any single character
|
key = key.toLocaleLowerCase();
|
||||||
key && key.length === 1 ||
|
entry = [...entries].find(e => e.innerText.toLocaleLowerCase().startsWith(key));
|
||||||
k >= 65 && k <= 90) {
|
|
||||||
const letter = new RegExp(key ? '^' + key : '^\\x' + k.toString(16), 'i');
|
|
||||||
entry = [...entries].find(entry => letter.test(entry.textContent));
|
|
||||||
}
|
}
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const target = $(event.shiftKey ? '.style-edit-link' : '.checker', entry);
|
const target = $(shiftKey ? '.style-edit-link' : '.checker', entry);
|
||||||
target.dispatchEvent(new MouseEvent('click', {cancelable: true}));
|
target.dispatchEvent(new MouseEvent('click', {cancelable: true}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -342,11 +342,7 @@ a.configure[target="_blank"] .svg-icon.config {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
#confirm button[data-cmd="ok"]:not([data-focused-via-click]):focus {
|
#confirm button[data-cmd="ok"]:not([data-focused-via-click]):focus {
|
||||||
outline: red auto 1px;
|
box-shadow: 0 0 0 1px red; /* Using box-shadow instead of the ugly outline in new Chrome */
|
||||||
}
|
|
||||||
/* FF ignores color with 'auto' */
|
|
||||||
.firefox #confirm button[data-cmd="ok"]:not([data-focused-via-click]):focus {
|
|
||||||
outline: red solid 1px;
|
|
||||||
}
|
}
|
||||||
.menu-items-wrapper {
|
.menu-items-wrapper {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
|
|
|
@ -507,16 +507,15 @@ Object.assign(handleEvent, {
|
||||||
window.onkeydown = event => {
|
window.onkeydown = event => {
|
||||||
const close = $('.menu-close', entry);
|
const close = $('.menu-close', entry);
|
||||||
const checkbox = $('.exclude-by-domain-checkbox', entry);
|
const checkbox = $('.exclude-by-domain-checkbox', entry);
|
||||||
const keyCode = event.keyCode || event.which;
|
if (document.activeElement === close && (event.key === 'Tab') && !event.shiftKey) {
|
||||||
if (document.activeElement === close && (keyCode === 9) && !event.shiftKey) {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
checkbox.focus();
|
checkbox.focus();
|
||||||
}
|
}
|
||||||
if (document.activeElement === checkbox && (keyCode === 9) && event.shiftKey) {
|
if (document.activeElement === checkbox && (event.key === 'Tab') && event.shiftKey) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
close.focus();
|
close.focus();
|
||||||
}
|
}
|
||||||
if (keyCode === 27) {
|
if (event.key === 'Escape') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
close.click();
|
close.click();
|
||||||
}
|
}
|
||||||
|
@ -542,20 +541,20 @@ Object.assign(handleEvent, {
|
||||||
const close = $('.menu-close', entry);
|
const close = $('.menu-close', entry);
|
||||||
const checkbox = $('.exclude-by-domain-checkbox', entry);
|
const checkbox = $('.exclude-by-domain-checkbox', entry);
|
||||||
const confirmActive = $('#confirm[data-display="true"]');
|
const confirmActive = $('#confirm[data-display="true"]');
|
||||||
const keyCode = event.keyCode || event.which;
|
const {key} = event;
|
||||||
if (document.activeElement === cancel && (keyCode === 9)) {
|
if (document.activeElement === cancel && (key === 'Tab')) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
affirm.focus();
|
affirm.focus();
|
||||||
}
|
}
|
||||||
if (document.activeElement === close && (keyCode === 9) && !event.shiftKey) {
|
if (document.activeElement === close && (key === 'Tab') && !event.shiftKey) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
checkbox.focus();
|
checkbox.focus();
|
||||||
}
|
}
|
||||||
if (document.activeElement === checkbox && (keyCode === 9) && event.shiftKey) {
|
if (document.activeElement === checkbox && (key === 'Tab') && event.shiftKey) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
close.focus();
|
close.focus();
|
||||||
}
|
}
|
||||||
if (keyCode === 27) {
|
if (key === 'Escape') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (confirmActive) {
|
if (confirmActive) {
|
||||||
box.dataset.display = false;
|
box.dataset.display = false;
|
||||||
|
|
|
@ -271,9 +271,7 @@ body.search-results-shown {
|
||||||
|
|
||||||
/* spinner: https://github.com/loadingio/css-spinner */
|
/* spinner: https://github.com/loadingio/css-spinner */
|
||||||
.lds-spinner {
|
.lds-spinner {
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -54,7 +54,7 @@ window.addEventListener('showStyles:done', () => {
|
||||||
href: URLS.usoArchive,
|
href: URLS.usoArchive,
|
||||||
onclick(event) {
|
onclick(event) {
|
||||||
if (!prefs.get('popup.findStylesInline') || dom.container) {
|
if (!prefs.get('popup.findStylesInline') || dom.container) {
|
||||||
this.search = `${new URLSearchParams({category, search: $('#search-query').value})}`;
|
this.search = new URLSearchParams({category, search: $('#search-query').value});
|
||||||
handleEvent.openURLandHide.call(this, event);
|
handleEvent.openURLandHide.call(this, event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,9 @@ window.addEventListener('showStyles:done', () => {
|
||||||
const n = Number(m[2]);
|
const n = Number(m[2]);
|
||||||
query.push(n >= 2000 && n <= thisYear ? n : m[1] || m[2]);
|
query.push(n >= 2000 && n <= thisYear ? n : m[1] || m[2]);
|
||||||
}
|
}
|
||||||
|
if (category === STYLUS_CATEGORY && !query.includes('stylus')) {
|
||||||
|
query.push('stylus');
|
||||||
|
}
|
||||||
ready = ready.then(start);
|
ready = ready.then(start);
|
||||||
};
|
};
|
||||||
$('#search-order').value = order;
|
$('#search-order').value = order;
|
||||||
|
@ -464,13 +467,18 @@ window.addEventListener('showStyles:done', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isResultMatching(res) {
|
function isResultMatching(res) {
|
||||||
|
// We're trying to call calcHaystack only when needed, not on all 100K items
|
||||||
|
const {c} = res;
|
||||||
return (
|
return (
|
||||||
res.c === category ||
|
c === category ||
|
||||||
searchGlobals && res.c === 'global' && (query.length || calcHaystack(res)._nLC.includes(category))
|
category !== STYLUS_CATEGORY && (
|
||||||
|
searchGlobals &&
|
||||||
|
c === 'global' &&
|
||||||
|
(query.length || calcHaystack(res)._nLC.includes(category))
|
||||||
|
)
|
||||||
) && (
|
) && (
|
||||||
category === STYLUS_CATEGORY
|
!query.length || // to skip calling calcHaystack
|
||||||
? /\bStylus\b/.test(res.n)
|
query.every(isInHaystack, calcHaystack(res))
|
||||||
: !query.length || query.every(isInHaystack, calcHaystack(res))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,10 +86,7 @@
|
||||||
border: 1px solid var(--main-border-color);
|
border: 1px solid var(--main-border-color);
|
||||||
background-color: var(--main-background-color);
|
background-color: var(--main-background-color);
|
||||||
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.12);
|
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.12);
|
||||||
-webkit-user-select: none;
|
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
|
||||||
-o-user-select: none;
|
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,10 +292,7 @@
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-webkit-user-select: text;
|
|
||||||
-moz-user-select: text;
|
-moz-user-select: text;
|
||||||
-ms-user-select: text;
|
|
||||||
-o-user-select: text;
|
|
||||||
user-select: text;
|
user-select: text;
|
||||||
border: 1px solid var(--input-border-color);
|
border: 1px solid var(--input-border-color);
|
||||||
background-color: var(--input-background-color);
|
background-color: var(--input-background-color);
|
||||||
|
@ -306,7 +300,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.colorpicker-theme-dark .colorpicker-input::-webkit-inner-spin-button {
|
.colorpicker-theme-dark .colorpicker-input::-webkit-inner-spin-button {
|
||||||
-webkit-filter: invert(1);
|
|
||||||
filter: invert(1);
|
filter: invert(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -355,29 +355,29 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function setFromKeyboard(event) {
|
function setFromKeyboard(event) {
|
||||||
const {which, ctrlKey: ctrl, altKey: alt, shiftKey: shift, metaKey: meta} = event;
|
const {key, ctrlKey: ctrl, altKey: alt, shiftKey: shift, metaKey: meta} = event;
|
||||||
switch (which) {
|
switch (key) {
|
||||||
case 9: // Tab
|
case 'Tab':
|
||||||
case 33: // PgUp
|
case 'PageUp':
|
||||||
case 34: // PgDn
|
case 'PageDown':
|
||||||
if (!ctrl && !alt && !meta) {
|
if (!ctrl && !alt && !meta) {
|
||||||
const el = document.activeElement;
|
const el = document.activeElement;
|
||||||
const inputs = $inputs[currentFormat];
|
const inputs = $inputs[currentFormat];
|
||||||
const lastInput = inputs[inputs.length - 1];
|
const lastInput = inputs[inputs.length - 1];
|
||||||
if (which === 9 && shift && el === inputs[0]) {
|
if (key === 'Tab' && shift && el === inputs[0]) {
|
||||||
maybeFocus(lastInput);
|
maybeFocus(lastInput);
|
||||||
} else if (which === 9 && !shift && el === lastInput) {
|
} else if (key === 'Tab' && !shift && el === lastInput) {
|
||||||
maybeFocus(inputs[0]);
|
maybeFocus(inputs[0]);
|
||||||
} else if (which !== 9 && !shift) {
|
} else if (key !== 'Tab' && !shift) {
|
||||||
setFromFormatElement({shift: which === 33 || shift});
|
setFromFormatElement({shift: key === 'PageUp' || shift});
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 38: // Up
|
case 'ArrowUp':
|
||||||
case 40: // Down
|
case 'ArrowDown':
|
||||||
if (!event.metaKey &&
|
if (!event.metaKey &&
|
||||||
document.activeElement.localName === 'input' &&
|
document.activeElement.localName === 'input' &&
|
||||||
document.activeElement.checkValidity()) {
|
document.activeElement.checkValidity()) {
|
||||||
|
@ -389,8 +389,8 @@
|
||||||
|
|
||||||
function setFromKeyboardIncrement(event) {
|
function setFromKeyboardIncrement(event) {
|
||||||
const el = document.activeElement;
|
const el = document.activeElement;
|
||||||
const {which, ctrlKey: ctrl, altKey: alt, shiftKey: shift} = event;
|
const {key, ctrlKey: ctrl, altKey: alt, shiftKey: shift} = event;
|
||||||
const dir = which === 38 ? 1 : -1;
|
const dir = key === 'ArrowUp' ? 1 : -1;
|
||||||
let value, newValue;
|
let value, newValue;
|
||||||
if (currentFormat === 'hex') {
|
if (currentFormat === 'hex') {
|
||||||
value = el.value.trim();
|
value = el.value.trim();
|
||||||
|
@ -617,9 +617,9 @@
|
||||||
|
|
||||||
function onKeyDown(e) {
|
function onKeyDown(e) {
|
||||||
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
||||||
switch (e.which) {
|
switch (e.key) {
|
||||||
case 13:
|
case 'Enter':
|
||||||
case 27:
|
case 'Escape':
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
hide();
|
hide();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user