2018-01-01 17:02:49 +00:00
|
|
|
/*
|
2018-11-07 06:09:29 +00:00
|
|
|
global messageBox getStyleWithNoCode
|
2020-02-02 04:36:54 +00:00
|
|
|
filterAndAppend showFiltersStats
|
2018-11-07 06:09:29 +00:00
|
|
|
checkUpdate handleUpdateInstalled
|
|
|
|
objectDiff
|
|
|
|
configDialog
|
|
|
|
sorter msg prefs API onDOMready $ $$ $create template setupLivePrefs
|
|
|
|
URLS enforceInputRange t tWordBreak formatDate
|
|
|
|
getOwnTab getActiveTab openURL animateElement sessionStorageHash debounce
|
2020-02-02 04:36:54 +00:00
|
|
|
scrollElementIntoView CHROME VIVALDI FIREFOX router
|
2020-06-01 00:14:42 +00:00
|
|
|
bulkChangeTime:true bulkChangeQueue
|
2018-01-01 17:02:49 +00:00
|
|
|
*/
|
2017-03-26 02:30:59 +00:00
|
|
|
'use strict';
|
2015-01-30 17:31:20 +00:00
|
|
|
|
2017-04-08 11:03:54 +00:00
|
|
|
let installed;
|
|
|
|
|
2017-06-27 20:13:11 +00:00
|
|
|
const ENTRY_ID_PREFIX_RAW = 'style-';
|
|
|
|
const ENTRY_ID_PREFIX = '#' + ENTRY_ID_PREFIX_RAW;
|
|
|
|
|
2020-06-01 00:14:42 +00:00
|
|
|
const BULK_THROTTLE_MS = 100;
|
|
|
|
|
2017-04-05 13:14:59 +00:00
|
|
|
const newUI = {
|
|
|
|
enabled: prefs.get('manage.newUI'),
|
|
|
|
favicons: prefs.get('manage.newUI.favicons'),
|
2017-04-18 18:49:04 +00:00
|
|
|
faviconsGray: prefs.get('manage.newUI.faviconsGray'),
|
2017-04-05 13:14:59 +00:00
|
|
|
targets: prefs.get('manage.newUI.targets'),
|
2017-04-08 11:03:54 +00:00
|
|
|
renderClass() {
|
|
|
|
document.documentElement.classList.toggle('newUI', newUI.enabled);
|
|
|
|
},
|
2017-04-05 13:14:59 +00:00
|
|
|
};
|
2017-04-08 11:03:54 +00:00
|
|
|
newUI.renderClass();
|
2017-04-05 13:14:59 +00:00
|
|
|
|
2017-03-21 01:32:38 +00:00
|
|
|
const TARGET_TYPES = ['domains', 'urls', 'urlPrefixes', 'regexps'];
|
2017-04-13 08:03:45 +00:00
|
|
|
const GET_FAVICON_URL = 'https://www.google.com/s2/favicons?domain=';
|
2017-04-09 06:43:51 +00:00
|
|
|
const OWN_ICON = chrome.runtime.getManifest().icons['16'];
|
2017-04-05 13:14:59 +00:00
|
|
|
|
2017-04-03 04:13:10 +00:00
|
|
|
const handleEvent = {};
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2017-04-08 11:03:54 +00:00
|
|
|
Promise.all([
|
2018-11-07 06:09:29 +00:00
|
|
|
API.getAllStyles(true),
|
2020-02-02 04:36:54 +00:00
|
|
|
// FIXME: integrate this into filter.js
|
|
|
|
router.getSearch('search') && API.searchDB({query: router.getSearch('search')}),
|
2018-11-07 06:09:29 +00:00
|
|
|
Promise.all([
|
|
|
|
onDOMready(),
|
|
|
|
prefs.initializing,
|
|
|
|
])
|
|
|
|
.then(() => {
|
|
|
|
initGlobalEvents();
|
|
|
|
if (!VIVALDI) {
|
|
|
|
$$('#header select').forEach(el => el.adjustWidth());
|
|
|
|
}
|
|
|
|
if (FIREFOX && 'update' in (chrome.commands || {})) {
|
|
|
|
const btn = $('#manage-shortcuts-button');
|
|
|
|
btn.classList.remove('chromium-only');
|
|
|
|
btn.onclick = API.optionsCustomizeHotkeys;
|
|
|
|
}
|
|
|
|
}),
|
2018-01-01 17:02:49 +00:00
|
|
|
]).then(args => {
|
|
|
|
showStyles(...args);
|
2017-04-08 11:03:54 +00:00
|
|
|
});
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2018-11-07 06:09:29 +00:00
|
|
|
msg.onExtension(onRuntimeMessage);
|
2017-04-11 10:51:40 +00:00
|
|
|
|
|
|
|
function onRuntimeMessage(msg) {
|
2017-03-21 01:32:38 +00:00
|
|
|
switch (msg.method) {
|
|
|
|
case 'styleUpdated':
|
|
|
|
case 'styleAdded':
|
|
|
|
case 'styleDeleted':
|
2020-06-01 00:14:42 +00:00
|
|
|
bulkChangeQueue.push(msg);
|
|
|
|
if (performance.now() - bulkChangeTime < BULK_THROTTLE_MS) {
|
|
|
|
debounce(handleBulkChange, BULK_THROTTLE_MS);
|
|
|
|
} else {
|
|
|
|
handleBulkChange();
|
|
|
|
}
|
2017-03-21 01:32:38 +00:00
|
|
|
break;
|
2018-05-15 13:24:28 +00:00
|
|
|
case 'styleApply':
|
|
|
|
case 'styleReplaceAll':
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
2017-03-21 01:32:38 +00:00
|
|
|
}
|
2018-05-15 13:24:28 +00:00
|
|
|
setTimeout(sorter.updateStripes, 0, {onlyWhenColumnsChanged: true});
|
2017-04-11 10:51:40 +00:00
|
|
|
}
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2015-01-30 17:31:20 +00:00
|
|
|
|
2017-03-21 01:32:38 +00:00
|
|
|
function initGlobalEvents() {
|
2017-04-08 11:03:54 +00:00
|
|
|
installed = $('#installed');
|
2017-04-05 13:14:59 +00:00
|
|
|
installed.onclick = handleEvent.entryClicked;
|
2020-08-24 16:27:23 +00:00
|
|
|
$('#manage-options-button').onclick = () => router.updateHash('#stylus-options');
|
|
|
|
$('#sync-styles').onclick = () => router.updateHash('#stylus-options');
|
2018-04-12 18:02:34 +00:00
|
|
|
{
|
|
|
|
const btn = $('#manage-shortcuts-button');
|
|
|
|
btn.onclick = btn.onclick || (() => openURL({url: URLS.configureCommands}));
|
|
|
|
}
|
2017-04-03 04:13:10 +00:00
|
|
|
$$('#header a[href^="http"]').forEach(a => (a.onclick = handleEvent.external));
|
2017-12-23 00:11:46 +00:00
|
|
|
// show date installed & last update on hover
|
|
|
|
installed.addEventListener('mouseover', handleEvent.lazyAddEntryTitle);
|
|
|
|
installed.addEventListener('mouseout', handleEvent.lazyAddEntryTitle);
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2018-08-02 18:10:43 +00:00
|
|
|
document.addEventListener('visibilitychange', onVisibilityChange);
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2017-04-13 08:03:45 +00:00
|
|
|
$$('[data-toggle-on-click]').forEach(el => {
|
2017-04-18 18:38:22 +00:00
|
|
|
// dataset on SVG doesn't work in Chrome 49-??, works in 57+
|
|
|
|
const target = $(el.getAttribute('data-toggle-on-click'));
|
2017-12-06 06:39:45 +00:00
|
|
|
el.onclick = event => {
|
|
|
|
event.preventDefault();
|
|
|
|
target.classList.toggle('hidden');
|
|
|
|
if (target.classList.contains('hidden')) {
|
|
|
|
el.removeAttribute('open');
|
|
|
|
} else {
|
|
|
|
el.setAttribute('open', '');
|
|
|
|
}
|
|
|
|
};
|
2017-04-13 08:03:45 +00:00
|
|
|
});
|
|
|
|
|
2017-04-18 18:49:04 +00:00
|
|
|
// triggered automatically by setupLivePrefs() below
|
2017-04-13 07:54:56 +00:00
|
|
|
enforceInputRange($('#manage.newUI.targets'));
|
2017-04-05 13:14:59 +00:00
|
|
|
|
2017-04-18 18:49:04 +00:00
|
|
|
// N.B. triggers existing onchange listeners
|
2017-04-21 16:39:34 +00:00
|
|
|
setupLivePrefs();
|
2017-12-23 00:11:46 +00:00
|
|
|
sorter.init();
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2018-11-30 01:34:06 +00:00
|
|
|
prefs.subscribe([
|
|
|
|
'manage.newUI',
|
|
|
|
'manage.newUI.favicons',
|
|
|
|
'manage.newUI.faviconsGray',
|
|
|
|
'manage.newUI.targets',
|
|
|
|
], () => switchUI());
|
2017-04-05 13:14:59 +00:00
|
|
|
|
|
|
|
switchUI({styleOnly: true});
|
2017-08-27 09:56:09 +00:00
|
|
|
|
|
|
|
// translate CSS manually
|
2017-12-03 21:12:09 +00:00
|
|
|
document.head.appendChild($create('style', `
|
2017-08-27 09:56:09 +00:00
|
|
|
.disabled h2::after {
|
|
|
|
content: "${t('genericDisabledLabel')}";
|
|
|
|
}
|
2018-08-27 14:20:33 +00:00
|
|
|
#update-all-no-updates[data-skipped-edited="true"]::after {
|
2017-08-27 09:56:09 +00:00
|
|
|
content: " ${t('updateAllCheckSucceededSomeEdited')}";
|
|
|
|
}
|
2018-08-27 14:20:33 +00:00
|
|
|
body.all-styles-hidden-by-filters::after {
|
2017-12-03 23:38:44 +00:00
|
|
|
content: "${t('filteredStylesAllHidden')}";
|
|
|
|
}
|
2017-12-03 21:12:09 +00:00
|
|
|
`));
|
2015-01-30 17:31:20 +00:00
|
|
|
}
|
|
|
|
|
2018-01-01 17:02:49 +00:00
|
|
|
function showStyles(styles = [], matchUrlIds) {
|
2017-12-23 00:11:46 +00:00
|
|
|
const sorted = sorter.sort({
|
|
|
|
styles: styles.map(style => ({
|
|
|
|
style,
|
2018-11-07 06:09:29 +00:00
|
|
|
name: (style.name || '').toLocaleLowerCase() + '\n' + style.name,
|
2017-12-23 00:11:46 +00:00
|
|
|
})),
|
|
|
|
});
|
2017-04-22 12:09:48 +00:00
|
|
|
let index = 0;
|
2017-12-26 05:52:19 +00:00
|
|
|
let firstRun = true;
|
2017-12-23 00:11:46 +00:00
|
|
|
installed.dataset.total = styles.length;
|
2017-04-27 19:12:32 +00:00
|
|
|
const scrollY = (history.state || {}).scrollY;
|
2017-06-27 20:01:17 +00:00
|
|
|
const shouldRenderAll = scrollY > window.innerHeight || sessionStorage.justEditedStyleId;
|
2017-03-21 01:32:38 +00:00
|
|
|
const renderBin = document.createDocumentFragment();
|
2017-04-27 19:12:32 +00:00
|
|
|
if (scrollY) {
|
2017-04-22 12:09:48 +00:00
|
|
|
renderStyles();
|
|
|
|
} else {
|
|
|
|
requestAnimationFrame(renderStyles);
|
|
|
|
}
|
2017-04-10 08:26:30 +00:00
|
|
|
|
2017-04-22 12:09:48 +00:00
|
|
|
function renderStyles() {
|
2017-03-21 01:32:38 +00:00
|
|
|
const t0 = performance.now();
|
2017-04-19 20:54:05 +00:00
|
|
|
let rendered = 0;
|
2017-07-12 20:44:59 +00:00
|
|
|
while (
|
|
|
|
index < sorted.length &&
|
|
|
|
// eslint-disable-next-line no-unmodified-loop-condition
|
2017-12-24 07:03:13 +00:00
|
|
|
(shouldRenderAll || ++rendered < 20 || performance.now() - t0 < 10)
|
2017-07-12 20:44:59 +00:00
|
|
|
) {
|
2018-01-01 17:02:49 +00:00
|
|
|
const info = sorted[index++];
|
|
|
|
const entry = createStyleElement(info);
|
|
|
|
if (matchUrlIds && !matchUrlIds.includes(info.style.id)) {
|
|
|
|
entry.classList.add('not-matching');
|
|
|
|
rendered--;
|
|
|
|
}
|
|
|
|
renderBin.appendChild(entry);
|
2017-03-25 02:35:54 +00:00
|
|
|
}
|
2018-05-15 13:24:28 +00:00
|
|
|
filterAndAppend({container: renderBin}).then(sorter.updateStripes);
|
2017-03-21 01:32:38 +00:00
|
|
|
if (index < sorted.length) {
|
2017-04-22 12:09:48 +00:00
|
|
|
requestAnimationFrame(renderStyles);
|
2018-08-24 11:02:31 +00:00
|
|
|
if (firstRun) setTimeout(getFaviconImgSrc);
|
2017-12-26 05:52:19 +00:00
|
|
|
firstRun = false;
|
2017-04-22 12:09:48 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-08-24 11:02:31 +00:00
|
|
|
setTimeout(getFaviconImgSrc);
|
|
|
|
if (sessionStorage.justEditedStyleId) {
|
|
|
|
highlightEditedStyle();
|
|
|
|
} else if ('scrollY' in (history.state || {})) {
|
2017-04-22 12:09:48 +00:00
|
|
|
setTimeout(window.scrollTo, 0, 0, history.state.scrollY);
|
2017-03-21 01:32:38 +00:00
|
|
|
}
|
2017-06-27 20:01:17 +00:00
|
|
|
}
|
2015-01-30 17:31:20 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2018-05-15 13:24:28 +00:00
|
|
|
function createStyleElement({style, name}) {
|
2017-04-10 08:26:30 +00:00
|
|
|
// query the sub-elements just once, then reuse the references
|
|
|
|
if ((createStyleElement.parts || {}).newUI !== newUI.enabled) {
|
2017-04-22 12:09:48 +00:00
|
|
|
const entry = template[`style${newUI.enabled ? 'Compact' : ''}`];
|
2017-04-10 08:26:30 +00:00
|
|
|
createStyleElement.parts = {
|
|
|
|
newUI: newUI.enabled,
|
|
|
|
entry,
|
|
|
|
entryClassBase: entry.className,
|
2017-04-14 18:30:55 +00:00
|
|
|
checker: $('.checker', entry) || {},
|
2017-04-10 08:26:30 +00:00
|
|
|
nameLink: $('.style-name-link', entry),
|
|
|
|
editLink: $('.style-edit-link', entry) || {},
|
2017-06-18 12:46:53 +00:00
|
|
|
editHrefBase: 'edit.html?id=',
|
2017-04-10 08:26:30 +00:00
|
|
|
homepage: $('.homepage', entry),
|
2017-04-22 12:09:48 +00:00
|
|
|
homepageIcon: template[`homepageIcon${newUI.enabled ? 'Small' : 'Big'}`],
|
2017-04-10 08:26:30 +00:00
|
|
|
appliesTo: $('.applies-to', entry),
|
|
|
|
targets: $('.targets', entry),
|
|
|
|
expander: $('.expander', entry),
|
|
|
|
decorations: {
|
|
|
|
urlPrefixesAfter: '*',
|
|
|
|
regexpsBefore: '/',
|
|
|
|
regexpsAfter: '/',
|
|
|
|
},
|
2018-01-04 19:35:12 +00:00
|
|
|
oldConfigure: !newUI.enabled && $('.configure-usercss', entry),
|
2017-12-29 14:53:11 +00:00
|
|
|
oldCheckUpdate: !newUI.enabled && $('.check-update', entry),
|
|
|
|
oldUpdate: !newUI.enabled && $('.update', entry),
|
2017-04-10 08:26:30 +00:00
|
|
|
};
|
2017-03-25 02:35:54 +00:00
|
|
|
}
|
2017-04-10 08:26:30 +00:00
|
|
|
const parts = createStyleElement.parts;
|
2018-11-07 06:09:29 +00:00
|
|
|
const configurable = style.usercssData && style.usercssData.vars && Object.keys(style.usercssData.vars).length > 0;
|
2017-04-14 18:30:55 +00:00
|
|
|
parts.checker.checked = style.enabled;
|
2017-12-07 20:21:27 +00:00
|
|
|
parts.nameLink.textContent = tWordBreak(style.name);
|
2017-04-10 08:26:30 +00:00
|
|
|
parts.nameLink.href = parts.editLink.href = parts.editHrefBase + style.id;
|
|
|
|
parts.homepage.href = parts.homepage.title = style.url || '';
|
2017-12-29 14:53:11 +00:00
|
|
|
if (!newUI.enabled) {
|
2018-01-04 19:35:12 +00:00
|
|
|
parts.oldConfigure.classList.toggle('hidden', !configurable);
|
2017-12-29 14:53:11 +00:00
|
|
|
parts.oldCheckUpdate.classList.toggle('hidden', !style.updateUrl);
|
|
|
|
parts.oldUpdate.classList.toggle('hidden', !style.updateUrl);
|
|
|
|
}
|
2017-04-10 08:26:30 +00:00
|
|
|
|
2018-01-04 19:47:29 +00:00
|
|
|
// clear the code to free up some memory
|
|
|
|
// (note, style is already a deep copy)
|
|
|
|
style.sourceCode = null;
|
|
|
|
style.sections.forEach(section => (section.code = null));
|
|
|
|
|
2017-04-14 18:30:55 +00:00
|
|
|
const entry = parts.entry.cloneNode(true);
|
2017-06-27 20:13:11 +00:00
|
|
|
entry.id = ENTRY_ID_PREFIX_RAW + style.id;
|
2017-04-14 18:30:55 +00:00
|
|
|
entry.styleId = style.id;
|
|
|
|
entry.styleNameLowerCase = name || style.name.toLocaleLowerCase();
|
2018-01-04 19:47:29 +00:00
|
|
|
entry.styleMeta = style;
|
2017-04-14 18:30:55 +00:00
|
|
|
entry.className = parts.entryClassBase + ' ' +
|
|
|
|
(style.enabled ? 'enabled' : 'disabled') +
|
2017-11-22 14:21:50 +00:00
|
|
|
(style.updateUrl ? ' updatable' : '') +
|
|
|
|
(style.usercssData ? ' usercss' : '');
|
2017-04-14 18:30:55 +00:00
|
|
|
|
2017-09-01 10:24:32 +00:00
|
|
|
if (style.url) {
|
2017-04-22 12:09:48 +00:00
|
|
|
$('.homepage', entry).appendChild(parts.homepageIcon.cloneNode(true));
|
|
|
|
}
|
|
|
|
if (style.updateUrl && newUI.enabled) {
|
|
|
|
$('.actions', entry).appendChild(template.updaterIcons.cloneNode(true));
|
|
|
|
}
|
2018-01-04 19:35:12 +00:00
|
|
|
if (configurable && newUI.enabled) {
|
2017-08-05 16:49:25 +00:00
|
|
|
$('.actions', entry).appendChild(template.configureIcon.cloneNode(true));
|
|
|
|
}
|
2017-04-22 12:09:48 +00:00
|
|
|
|
2017-12-24 06:42:07 +00:00
|
|
|
createStyleTargetsElement({entry, style});
|
2017-04-14 18:30:55 +00:00
|
|
|
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-24 11:02:31 +00:00
|
|
|
function createStyleTargetsElement({entry, style}) {
|
2017-04-14 18:30:55 +00:00
|
|
|
const parts = createStyleElement.parts;
|
2017-12-26 05:52:19 +00:00
|
|
|
const entryTargets = $('.targets', entry);
|
2018-08-24 11:02:31 +00:00
|
|
|
const targets = parts.targets.cloneNode(true);
|
2017-04-10 08:26:30 +00:00
|
|
|
let container = targets;
|
2017-04-05 13:14:59 +00:00
|
|
|
let numTargets = 0;
|
2017-04-10 08:26:30 +00:00
|
|
|
const displayed = new Set();
|
2017-04-05 13:14:59 +00:00
|
|
|
for (const type of TARGET_TYPES) {
|
2017-03-26 02:30:59 +00:00
|
|
|
for (const section of style.sections) {
|
2017-04-05 13:14:59 +00:00
|
|
|
for (const targetValue of section[type] || []) {
|
|
|
|
if (displayed.has(targetValue)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
displayed.add(targetValue);
|
2018-08-24 11:02:31 +00:00
|
|
|
const element = template.appliesToTarget.cloneNode(true);
|
2017-04-09 04:53:16 +00:00
|
|
|
if (!newUI.enabled) {
|
2017-07-16 18:02:00 +00:00
|
|
|
if (numTargets === 10) {
|
2017-04-10 08:26:30 +00:00
|
|
|
container = container.appendChild(template.extraAppliesTo.cloneNode(true));
|
2018-08-24 11:02:31 +00:00
|
|
|
} else if (numTargets > 0) {
|
2017-04-09 04:53:16 +00:00
|
|
|
container.appendChild(template.appliesToSeparator.cloneNode(true));
|
|
|
|
}
|
2017-04-05 13:14:59 +00:00
|
|
|
}
|
2018-08-24 11:02:31 +00:00
|
|
|
element.dataset.type = type;
|
|
|
|
element.appendChild(
|
|
|
|
document.createTextNode(
|
|
|
|
(parts.decorations[type + 'Before'] || '') +
|
|
|
|
targetValue +
|
|
|
|
(parts.decorations[type + 'After'] || '')));
|
|
|
|
container.appendChild(element);
|
2017-04-09 04:53:16 +00:00
|
|
|
numTargets++;
|
2017-03-25 02:35:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-04-05 13:14:59 +00:00
|
|
|
if (newUI.enabled) {
|
2017-04-14 18:30:55 +00:00
|
|
|
if (numTargets > newUI.targets) {
|
|
|
|
$('.applies-to', entry).classList.add('has-more');
|
|
|
|
}
|
2017-04-05 13:14:59 +00:00
|
|
|
}
|
2017-04-10 08:26:30 +00:00
|
|
|
if (numTargets) {
|
2018-08-24 11:02:31 +00:00
|
|
|
entryTargets.parentElement.replaceChild(targets, entryTargets);
|
2018-03-19 04:10:59 +00:00
|
|
|
} else if (!entry.classList.contains('global') ||
|
|
|
|
!entryTargets.firstElementChild) {
|
|
|
|
if (entryTargets.firstElementChild) {
|
|
|
|
entryTargets.textContent = '';
|
|
|
|
}
|
2017-04-14 18:30:55 +00:00
|
|
|
entryTargets.appendChild(template.appliesToEverything.cloneNode(true));
|
2017-04-10 08:26:30 +00:00
|
|
|
}
|
2017-04-14 18:30:55 +00:00
|
|
|
entry.classList.toggle('global', !numTargets);
|
2015-01-30 17:31:20 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2018-01-11 21:53:22 +00:00
|
|
|
function getFaviconImgSrc(container = installed) {
|
2018-08-24 11:02:31 +00:00
|
|
|
if (!newUI.enabled || !newUI.favicons) return;
|
2018-01-01 05:17:43 +00:00
|
|
|
const regexpRemoveNegativeLookAhead = /(\?!([^)]+\))|\(\?![\w(]+[^)]+[\w|)]+)/g;
|
|
|
|
// replace extra characters & all but the first group entry "(abc|def|ghi)xyz" => abcxyz
|
|
|
|
const regexpReplaceExtraCharacters = /[\\(]|((\|\w+)+\))/g;
|
2018-07-28 18:05:20 +00:00
|
|
|
const regexpMatchRegExp = /[\w-]+[.(]+(com|org|co|net|im|io|edu|gov|biz|info|de|cn|uk|nl|eu|ru)\b/g;
|
2018-01-01 05:17:43 +00:00
|
|
|
const regexpMatchDomain = /^.*?:\/\/([^/]+)/;
|
2018-07-28 18:05:20 +00:00
|
|
|
for (const target of $$('.target', container)) {
|
2018-01-01 05:17:43 +00:00
|
|
|
const type = target.dataset.type;
|
|
|
|
const targetValue = target.textContent;
|
2018-07-28 18:04:29 +00:00
|
|
|
if (!targetValue) continue;
|
2018-01-01 05:17:43 +00:00
|
|
|
let favicon = '';
|
|
|
|
if (type === 'domains') {
|
|
|
|
favicon = GET_FAVICON_URL + targetValue;
|
|
|
|
} else if (targetValue.includes('chrome-extension:') || targetValue.includes('moz-extension:')) {
|
|
|
|
favicon = OWN_ICON;
|
|
|
|
} else if (type === 'regexps') {
|
|
|
|
favicon = targetValue
|
|
|
|
.replace(regexpRemoveNegativeLookAhead, '')
|
|
|
|
.replace(regexpReplaceExtraCharacters, '')
|
|
|
|
.match(regexpMatchRegExp);
|
|
|
|
favicon = favicon ? GET_FAVICON_URL + favicon.shift() : '';
|
|
|
|
} else {
|
|
|
|
favicon = targetValue.includes('://') && targetValue.match(regexpMatchDomain);
|
|
|
|
favicon = favicon ? GET_FAVICON_URL + favicon[1] : '';
|
|
|
|
}
|
|
|
|
if (favicon) {
|
|
|
|
const img = target.children[0];
|
|
|
|
if (!img || img.localName !== 'img') {
|
|
|
|
target.insertAdjacentElement('afterbegin', document.createElement('img'))
|
|
|
|
.dataset.src = favicon;
|
|
|
|
} else if ((img.dataset.src || img.src) !== favicon) {
|
|
|
|
img.src = '';
|
|
|
|
img.dataset.src = favicon;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
handleEvent.loadFavicons();
|
|
|
|
}
|
|
|
|
|
2017-12-26 05:52:19 +00:00
|
|
|
|
2017-04-03 04:13:10 +00:00
|
|
|
Object.assign(handleEvent, {
|
|
|
|
|
2017-04-05 13:14:59 +00:00
|
|
|
ENTRY_ROUTES: {
|
|
|
|
'.checker, .enable, .disable': 'toggle',
|
2018-01-04 19:25:03 +00:00
|
|
|
'.style-name': 'name',
|
2017-04-05 13:14:59 +00:00
|
|
|
'.homepage': 'external',
|
|
|
|
'.check-update': 'check',
|
|
|
|
'.update': 'update',
|
|
|
|
'.delete': 'delete',
|
|
|
|
'.applies-to .expander': 'expandTargets',
|
2017-10-12 08:10:17 +00:00
|
|
|
'.configure-usercss': 'config'
|
2017-08-05 16:49:25 +00:00
|
|
|
},
|
|
|
|
|
2017-04-05 13:14:59 +00:00
|
|
|
entryClicked(event) {
|
|
|
|
const target = event.target;
|
|
|
|
const entry = target.closest('.entry');
|
|
|
|
for (const selector in handleEvent.ENTRY_ROUTES) {
|
2017-07-16 18:02:00 +00:00
|
|
|
for (let el = target; el && el !== entry; el = el.parentElement) {
|
2017-04-05 13:14:59 +00:00
|
|
|
if (el.matches(selector)) {
|
|
|
|
const handler = handleEvent.ENTRY_ROUTES[selector];
|
|
|
|
return handleEvent[handler].call(el, event, entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2018-01-04 19:25:03 +00:00
|
|
|
name(event) {
|
|
|
|
if (newUI.enabled) handleEvent.edit(event);
|
|
|
|
},
|
|
|
|
|
2017-04-03 04:13:10 +00:00
|
|
|
edit(event) {
|
2017-03-21 01:32:38 +00:00
|
|
|
if (event.altKey) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
2017-07-16 18:02:00 +00:00
|
|
|
const left = event.button === 0;
|
|
|
|
const middle = event.button === 1;
|
2017-03-26 02:30:59 +00:00
|
|
|
const shift = event.shiftKey;
|
|
|
|
const ctrl = event.ctrlKey;
|
2017-03-21 01:32:38 +00:00
|
|
|
const openWindow = left && shift && !ctrl;
|
|
|
|
const openBackgroundTab = (middle && !shift) || (left && ctrl && !shift);
|
|
|
|
const openForegroundTab = (middle && shift) || (left && ctrl && shift);
|
2017-11-26 17:25:25 +00:00
|
|
|
const url = $('[href]', event.target.closest('.entry')).href;
|
2017-03-21 01:32:38 +00:00
|
|
|
if (openWindow || openBackgroundTab || openForegroundTab) {
|
2017-11-25 13:24:07 +00:00
|
|
|
if (chrome.windows && openWindow) {
|
2017-03-21 01:32:38 +00:00
|
|
|
chrome.windows.create(Object.assign(prefs.get('windowPosition'), {url}));
|
|
|
|
} else {
|
2018-07-11 16:02:49 +00:00
|
|
|
getOwnTab().then(({index}) => {
|
|
|
|
openURL({
|
|
|
|
url,
|
|
|
|
index: index + 1,
|
|
|
|
active: openForegroundTab
|
|
|
|
});
|
|
|
|
});
|
2017-03-21 01:32:38 +00:00
|
|
|
}
|
|
|
|
} else {
|
2018-08-02 18:10:43 +00:00
|
|
|
onVisibilityChange();
|
2017-03-21 01:32:38 +00:00
|
|
|
getActiveTab().then(tab => {
|
|
|
|
sessionStorageHash('manageStylesHistory').set(tab.id, url);
|
|
|
|
location.href = url;
|
|
|
|
});
|
|
|
|
}
|
2017-04-03 04:13:10 +00:00
|
|
|
},
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2017-04-05 13:14:59 +00:00
|
|
|
toggle(event, entry) {
|
2018-11-07 06:09:29 +00:00
|
|
|
API.toggleStyle(entry.styleId, this.matches('.enable') || this.checked);
|
2017-04-03 04:13:10 +00:00
|
|
|
},
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2017-04-05 13:14:59 +00:00
|
|
|
check(event, entry) {
|
2017-12-09 15:25:44 +00:00
|
|
|
event.preventDefault();
|
2018-01-01 17:02:49 +00:00
|
|
|
checkUpdate(entry, {single: true});
|
2017-04-03 04:13:10 +00:00
|
|
|
},
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2017-04-05 13:14:59 +00:00
|
|
|
update(event, entry) {
|
2017-12-09 15:25:44 +00:00
|
|
|
event.preventDefault();
|
2018-01-01 17:02:49 +00:00
|
|
|
const json = entry.updatedCode;
|
|
|
|
json.id = entry.styleId;
|
2018-11-07 06:09:29 +00:00
|
|
|
API[json.usercssData ? 'installUsercss' : 'installStyle'](json);
|
2017-04-03 04:13:10 +00:00
|
|
|
},
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2017-04-05 13:14:59 +00:00
|
|
|
delete(event, entry) {
|
2017-12-09 15:25:44 +00:00
|
|
|
event.preventDefault();
|
2017-04-05 13:14:59 +00:00
|
|
|
const id = entry.styleId;
|
2017-06-27 20:00:24 +00:00
|
|
|
animateElement(entry);
|
2017-03-25 19:50:37 +00:00
|
|
|
messageBox({
|
|
|
|
title: t('deleteStyleConfirm'),
|
2018-01-01 17:02:49 +00:00
|
|
|
contents: entry.styleMeta.name,
|
2017-03-25 19:50:37 +00:00
|
|
|
className: 'danger center',
|
|
|
|
buttons: [t('confirmDelete'), t('confirmCancel')],
|
|
|
|
})
|
2017-12-09 15:25:44 +00:00
|
|
|
.then(({button}) => {
|
|
|
|
if (button === 0) {
|
2018-11-07 06:09:29 +00:00
|
|
|
API.deleteStyle(id);
|
2017-03-25 19:50:37 +00:00
|
|
|
}
|
|
|
|
});
|
2020-06-02 06:33:07 +00:00
|
|
|
const deleteButton = $('#message-box-buttons > button');
|
|
|
|
if (deleteButton) deleteButton.removeAttribute('data-focused-via-click');
|
2017-04-03 04:13:10 +00:00
|
|
|
},
|
2017-03-31 22:49:51 +00:00
|
|
|
|
2017-04-03 04:13:10 +00:00
|
|
|
external(event) {
|
2018-07-11 16:02:49 +00:00
|
|
|
if (event.shiftKey && !event.altKey && !event.ctrlKey && !event.metaKey) {
|
|
|
|
// Shift-click = the built-in 'open in a new window' action
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
getOwnTab().then(({index}) => {
|
|
|
|
openURL({
|
|
|
|
url: event.target.closest('a').href,
|
|
|
|
index: index + 1,
|
|
|
|
active: !event.ctrlKey || event.shiftKey,
|
|
|
|
});
|
|
|
|
});
|
2017-03-31 22:49:51 +00:00
|
|
|
event.preventDefault();
|
2017-04-03 04:13:10 +00:00
|
|
|
},
|
2017-04-05 13:14:59 +00:00
|
|
|
|
2017-12-09 15:25:44 +00:00
|
|
|
expandTargets(event) {
|
|
|
|
event.preventDefault();
|
2017-04-05 13:14:59 +00:00
|
|
|
this.closest('.applies-to').classList.toggle('expanded');
|
|
|
|
},
|
|
|
|
|
2017-12-24 06:42:07 +00:00
|
|
|
loadFavicons({all = false} = {}) {
|
|
|
|
if (!installed.firstElementChild) return;
|
|
|
|
let favicons = [];
|
|
|
|
if (all) {
|
|
|
|
favicons = $$('img[data-src]', installed);
|
|
|
|
} else {
|
|
|
|
const {left, top} = installed.firstElementChild.getBoundingClientRect();
|
|
|
|
const x = Math.max(0, left);
|
|
|
|
const y = Math.max(0, top);
|
|
|
|
const first = document.elementFromPoint(x, y);
|
|
|
|
const lastOffset = first.offsetTop + window.innerHeight;
|
|
|
|
const numTargets = prefs.get('manage.newUI.targets');
|
|
|
|
let entry = first && first.closest('.entry') || installed.children[0];
|
|
|
|
while (entry && entry.offsetTop <= lastOffset) {
|
|
|
|
favicons.push(...$$('img', entry).slice(0, numTargets).filter(img => img.dataset.src));
|
|
|
|
entry = entry.nextElementSibling;
|
2017-04-05 13:14:59 +00:00
|
|
|
}
|
|
|
|
}
|
2017-12-24 06:42:07 +00:00
|
|
|
let i = 0;
|
|
|
|
for (const img of favicons) {
|
|
|
|
img.src = img.dataset.src;
|
|
|
|
delete img.dataset.src;
|
|
|
|
// loading too many icons at once will block the page while the new layout is recalculated
|
|
|
|
if (++i > 100) break;
|
|
|
|
}
|
|
|
|
if ($('img[data-src]', installed)) {
|
|
|
|
debounce(handleEvent.loadFavicons, 1, {all: true});
|
|
|
|
}
|
2017-04-16 11:24:49 +00:00
|
|
|
},
|
2017-11-27 11:51:51 +00:00
|
|
|
|
|
|
|
config(event, {styleMeta}) {
|
2017-12-18 06:57:00 +00:00
|
|
|
event.preventDefault();
|
2017-11-27 11:51:51 +00:00
|
|
|
configDialog(styleMeta);
|
|
|
|
},
|
2017-12-23 00:11:46 +00:00
|
|
|
|
|
|
|
lazyAddEntryTitle({type, target}) {
|
|
|
|
const cell = target.closest('h2.style-name');
|
|
|
|
if (cell) {
|
|
|
|
const link = $('.style-name-link', cell);
|
|
|
|
if (type === 'mouseover' && !link.title) {
|
|
|
|
debounce(handleEvent.addEntryTitle, 50, link);
|
|
|
|
} else {
|
|
|
|
debounce.unregister(handleEvent.addEntryTitle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
addEntryTitle(link) {
|
|
|
|
const entry = link.closest('.entry');
|
|
|
|
link.title = [
|
|
|
|
{prop: 'installDate', name: 'dateInstalled'},
|
|
|
|
{prop: 'updateDate', name: 'dateUpdated'},
|
|
|
|
].map(({prop, name}) =>
|
|
|
|
t(name) + ': ' + (formatDate(entry.styleMeta[prop]) || '—')).join('\n');
|
|
|
|
}
|
2017-04-03 04:13:10 +00:00
|
|
|
});
|
2015-01-30 17:31:20 +00:00
|
|
|
|
|
|
|
|
2020-06-01 00:14:42 +00:00
|
|
|
function handleBulkChange() {
|
|
|
|
for (const msg of bulkChangeQueue) {
|
|
|
|
const {id} = msg.style;
|
|
|
|
if (msg.method === 'styleDeleted') {
|
|
|
|
handleDelete(id);
|
|
|
|
bulkChangeTime = performance.now();
|
|
|
|
} else {
|
|
|
|
handleUpdateForId(id, msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bulkChangeQueue.length = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleUpdateForId(id, opts) {
|
|
|
|
return API.getStyle(id, true).then(style => {
|
|
|
|
handleUpdate(style, opts);
|
|
|
|
bulkChangeTime = performance.now();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-07-21 18:04:47 +00:00
|
|
|
function handleUpdate(style, {reason, method} = {}) {
|
2018-11-07 06:09:29 +00:00
|
|
|
if (reason === 'editPreview' || reason === 'editPreviewEnd') return;
|
2017-04-26 10:56:32 +00:00
|
|
|
let entry;
|
2017-06-27 20:13:11 +00:00
|
|
|
let oldEntry = $(ENTRY_ID_PREFIX + style.id);
|
2017-07-16 18:02:00 +00:00
|
|
|
if (oldEntry && method === 'styleUpdated') {
|
2017-04-26 15:35:00 +00:00
|
|
|
handleToggledOrCodeOnly();
|
2017-04-26 10:56:32 +00:00
|
|
|
}
|
|
|
|
entry = entry || createStyleElement({style});
|
2017-04-16 11:24:49 +00:00
|
|
|
if (oldEntry) {
|
2017-07-16 18:02:00 +00:00
|
|
|
if (oldEntry.styleNameLowerCase === entry.styleNameLowerCase) {
|
2017-04-16 11:24:49 +00:00
|
|
|
installed.replaceChild(entry, oldEntry);
|
2017-03-26 08:43:45 +00:00
|
|
|
} else {
|
2017-04-16 11:24:49 +00:00
|
|
|
oldEntry.remove();
|
2017-03-26 08:43:45 +00:00
|
|
|
}
|
2017-04-26 10:56:32 +00:00
|
|
|
}
|
2018-01-07 13:53:41 +00:00
|
|
|
if ((reason === 'update' || reason === 'install') && entry.matches('.updatable')) {
|
2017-12-02 04:07:12 +00:00
|
|
|
handleUpdateInstalled(entry, reason);
|
2017-03-21 01:32:38 +00:00
|
|
|
}
|
2018-05-15 11:56:12 +00:00
|
|
|
filterAndAppend({entry}).then(sorter.update);
|
2020-04-28 14:06:57 +00:00
|
|
|
if (!entry.matches('.hidden') && reason !== 'import' && reason !== 'sync') {
|
2017-06-27 20:00:24 +00:00
|
|
|
animateElement(entry);
|
2018-01-01 17:02:49 +00:00
|
|
|
requestAnimationFrame(() => scrollElementIntoView(entry));
|
2017-04-05 13:14:59 +00:00
|
|
|
}
|
2018-08-24 11:02:31 +00:00
|
|
|
getFaviconImgSrc(entry);
|
2017-04-26 10:56:32 +00:00
|
|
|
|
2017-04-26 15:35:00 +00:00
|
|
|
function handleToggledOrCodeOnly() {
|
2017-04-26 10:56:32 +00:00
|
|
|
const newStyleMeta = getStyleWithNoCode(style);
|
2018-02-26 19:56:42 +00:00
|
|
|
const diff = objectDiff(oldEntry.styleMeta, newStyleMeta)
|
|
|
|
.filter(({key, path}) => path || (!key.startsWith('original') && !key.endsWith('Date')));
|
2017-07-16 18:02:00 +00:00
|
|
|
if (diff.length === 0) {
|
2017-04-26 10:56:32 +00:00
|
|
|
// only code was modified
|
|
|
|
entry = oldEntry;
|
|
|
|
oldEntry = null;
|
|
|
|
}
|
2017-07-16 18:02:00 +00:00
|
|
|
if (diff.length === 1 && diff[0].key === 'enabled') {
|
2017-04-26 10:56:32 +00:00
|
|
|
oldEntry.classList.toggle('enabled', style.enabled);
|
|
|
|
oldEntry.classList.toggle('disabled', !style.enabled);
|
|
|
|
$$('.checker', oldEntry).forEach(el => (el.checked = style.enabled));
|
|
|
|
oldEntry.styleMeta = newStyleMeta;
|
|
|
|
entry = oldEntry;
|
|
|
|
oldEntry = null;
|
|
|
|
}
|
|
|
|
}
|
2015-01-30 17:31:20 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 01:32:38 +00:00
|
|
|
|
2015-01-30 17:31:20 +00:00
|
|
|
function handleDelete(id) {
|
2017-06-27 20:13:11 +00:00
|
|
|
const node = $(ENTRY_ID_PREFIX + id);
|
2017-03-21 01:32:38 +00:00
|
|
|
if (node) {
|
|
|
|
node.remove();
|
2017-04-16 11:24:49 +00:00
|
|
|
if (node.matches('.can-update')) {
|
|
|
|
const btnApply = $('#apply-all-updates');
|
|
|
|
btnApply.dataset.value = Number(btnApply.dataset.value) - 1;
|
|
|
|
}
|
2018-02-26 20:16:10 +00:00
|
|
|
showFiltersStats();
|
2017-03-21 01:32:38 +00:00
|
|
|
}
|
2015-01-30 17:31:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-05 13:14:59 +00:00
|
|
|
function switchUI({styleOnly} = {}) {
|
2017-04-18 18:49:04 +00:00
|
|
|
const current = {};
|
|
|
|
const changed = {};
|
|
|
|
let someChanged = false;
|
|
|
|
// ensure the global option is processed first
|
|
|
|
for (const el of [$('#manage.newUI'), ...$$('[id^="manage.newUI."]')]) {
|
|
|
|
const id = el.id.replace(/^manage\.newUI\.?/, '') || 'enabled';
|
2017-07-16 18:02:00 +00:00
|
|
|
const value = el.type === 'checkbox' ? el.checked : Number(el.value);
|
|
|
|
const valueChanged = value !== newUI[id] && (id === 'enabled' || current.enabled);
|
2017-04-18 18:49:04 +00:00
|
|
|
current[id] = value;
|
|
|
|
changed[id] = valueChanged;
|
|
|
|
someChanged |= valueChanged;
|
|
|
|
}
|
2017-04-05 13:14:59 +00:00
|
|
|
|
2017-04-18 18:49:04 +00:00
|
|
|
if (!styleOnly && !someChanged) {
|
2017-04-05 13:14:59 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-04-18 18:49:04 +00:00
|
|
|
Object.assign(newUI, current);
|
2017-04-08 11:03:54 +00:00
|
|
|
newUI.renderClass();
|
2017-04-18 18:49:04 +00:00
|
|
|
installed.classList.toggle('has-favicons', newUI.favicons);
|
2017-04-05 13:14:59 +00:00
|
|
|
$('#style-overrides').textContent = `
|
|
|
|
.newUI .targets {
|
|
|
|
max-height: ${newUI.targets * 18}px;
|
|
|
|
}
|
2018-02-28 02:04:35 +00:00
|
|
|
` + (newUI.faviconsGray ? `
|
2017-04-18 18:49:04 +00:00
|
|
|
.newUI .target img {
|
|
|
|
-webkit-filter: grayscale(1);
|
|
|
|
filter: grayscale(1);
|
|
|
|
opacity: .25;
|
|
|
|
}
|
2018-02-28 02:04:35 +00:00
|
|
|
` : `
|
2017-04-18 18:49:04 +00:00
|
|
|
.newUI .target img {
|
|
|
|
-webkit-filter: none;
|
|
|
|
filter: none;
|
|
|
|
opacity: 1;
|
|
|
|
}
|
2020-05-31 05:43:56 +00:00
|
|
|
`) + (CHROME >= 58 ? `
|
2018-02-28 02:04:35 +00:00
|
|
|
.newUI .entry {
|
|
|
|
contain: strict;
|
|
|
|
}
|
|
|
|
.newUI .entry > * {
|
|
|
|
contain: content;
|
|
|
|
}
|
|
|
|
.newUI .entry .actions {
|
|
|
|
contain: none;
|
|
|
|
}
|
|
|
|
.newUI .target {
|
|
|
|
contain: layout style;
|
|
|
|
}
|
|
|
|
.newUI .target img {
|
|
|
|
contain: layout style size;
|
|
|
|
}
|
|
|
|
.newUI .entry.can-update,
|
|
|
|
.newUI .entry.update-problem,
|
|
|
|
.newUI .entry.update-done {
|
|
|
|
contain: none;
|
|
|
|
}
|
|
|
|
` : '');
|
2017-04-05 13:14:59 +00:00
|
|
|
|
2017-04-14 18:30:55 +00:00
|
|
|
if (styleOnly) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-04-18 18:49:04 +00:00
|
|
|
const missingFavicons = newUI.enabled && newUI.favicons && !$('.applies-to img');
|
|
|
|
if (changed.enabled || (missingFavicons && !createStyleElement.parts)) {
|
2017-07-19 08:19:15 +00:00
|
|
|
installed.textContent = '';
|
2018-11-07 06:09:29 +00:00
|
|
|
API.getAllStyles(true).then(showStyles);
|
2017-04-14 18:30:55 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-04-18 18:49:04 +00:00
|
|
|
if (changed.targets) {
|
2017-04-10 08:26:30 +00:00
|
|
|
for (const targets of $$('.entry .targets')) {
|
|
|
|
const hasMore = targets.children.length > newUI.targets;
|
|
|
|
targets.parentElement.classList.toggle('has-more', hasMore);
|
|
|
|
}
|
2017-04-14 18:30:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (missingFavicons) {
|
2018-08-24 11:02:31 +00:00
|
|
|
debounce(getFaviconImgSrc);
|
2017-04-14 18:30:55 +00:00
|
|
|
return;
|
2017-04-05 13:14:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-02 18:10:43 +00:00
|
|
|
function onVisibilityChange() {
|
|
|
|
switch (document.visibilityState) {
|
|
|
|
// page restored without reloading via history navigation (currently only in FF)
|
2018-08-30 06:23:55 +00:00
|
|
|
// the catch here is that DOM may be outdated so we'll at least refresh the just edited style
|
|
|
|
// assuming other changes aren't important enough to justify making a complicated DOM sync
|
2020-06-01 00:14:42 +00:00
|
|
|
case 'visible': {
|
|
|
|
const id = sessionStorage.justEditedStyleId;
|
|
|
|
if (id) {
|
|
|
|
handleUpdateForId(Number(id), {method: 'styleUpdated'});
|
2018-08-30 06:23:55 +00:00
|
|
|
delete sessionStorage.justEditedStyleId;
|
|
|
|
}
|
2018-08-02 18:10:43 +00:00
|
|
|
break;
|
2020-06-01 00:14:42 +00:00
|
|
|
}
|
2018-08-02 18:10:43 +00:00
|
|
|
// going away
|
|
|
|
case 'hidden':
|
|
|
|
history.replaceState({scrollY: window.scrollY}, document.title);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function highlightEditedStyle() {
|
|
|
|
if (!sessionStorage.justEditedStyleId) return;
|
|
|
|
const entry = $(ENTRY_ID_PREFIX + sessionStorage.justEditedStyleId);
|
|
|
|
delete sessionStorage.justEditedStyleId;
|
|
|
|
if (entry) {
|
|
|
|
animateElement(entry);
|
|
|
|
requestAnimationFrame(() => scrollElementIntoView(entry));
|
|
|
|
}
|
2017-03-26 08:43:45 +00:00
|
|
|
}
|
2020-02-02 04:36:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
function embedOptions() {
|
|
|
|
let options = $('#stylus-embedded-options');
|
|
|
|
if (!options) {
|
|
|
|
options = document.createElement('iframe');
|
|
|
|
options.id = 'stylus-embedded-options';
|
|
|
|
options.src = '/options.html';
|
|
|
|
document.documentElement.appendChild(options);
|
|
|
|
}
|
|
|
|
options.focus();
|
|
|
|
}
|
|
|
|
|
|
|
|
function unembedOptions() {
|
|
|
|
const options = $('#stylus-embedded-options');
|
|
|
|
if (options) {
|
|
|
|
options.contentWindow.document.body.classList.add('scaleout');
|
|
|
|
options.classList.add('fadeout');
|
|
|
|
animateElement(options, {
|
|
|
|
className: 'fadeout',
|
|
|
|
onComplete: () => options.remove(),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
router.watch({hash: '#stylus-options'}, state => {
|
|
|
|
if (state) {
|
|
|
|
embedOptions();
|
|
|
|
} else {
|
|
|
|
unembedOptions();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
window.addEventListener('closeOptions', () => {
|
|
|
|
router.updateHash('');
|
|
|
|
});
|