dom.js: extract common DOM functions
This commit is contained in:
parent
0f8fd5c07c
commit
4936426fa3
|
@ -35,6 +35,12 @@ globals:
|
||||||
importStyles: true
|
importStyles: true
|
||||||
getActiveTabRealURL: true
|
getActiveTabRealURL: true
|
||||||
openURL: true
|
openURL: true
|
||||||
|
$: true
|
||||||
|
$$: true
|
||||||
|
animateElement: true
|
||||||
|
scrollElementIntoView: true
|
||||||
|
getClickedStyleElement: true
|
||||||
|
getClickedStyleId: true
|
||||||
onDOMready: true
|
onDOMready: true
|
||||||
getDomains: true
|
getDomains: true
|
||||||
webSqlStorage: true
|
webSqlStorage: true
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
/* globals getStyles, saveStyle, invalidateCache, refreshAllTabs, handleUpdate */
|
/* globals getStyles, saveStyle, invalidateCache, refreshAllTabs */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const STYLISH_DUMP_FILE_EXT = '.txt';
|
const STYLISH_DUMP_FILE_EXT = '.txt';
|
||||||
const STYLUS_BACKUP_FILE_EXT = '.json';
|
const STYLUS_BACKUP_FILE_EXT = '.json';
|
||||||
|
|
||||||
|
|
||||||
function importFromFile({fileTypeFilter, file} = {}) {
|
function importFromFile({fileTypeFilter, file} = {}) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const fileInput = document.createElement('input');
|
const fileInput = document.createElement('input');
|
||||||
|
@ -44,6 +45,7 @@ function importFromFile({fileTypeFilter, file} = {}) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function importFromString(jsonString) {
|
function importFromString(jsonString) {
|
||||||
const json = runTryCatch(() => Array.from(JSON.parse(jsonString))) || [];
|
const json = runTryCatch(() => Array.from(JSON.parse(jsonString))) || [];
|
||||||
const oldStyles = json.length && deepCopyStyles();
|
const oldStyles = json.length && deepCopyStyles();
|
||||||
|
@ -177,14 +179,14 @@ function importFromString(jsonString) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindClick(box) {
|
function bindClick(box) {
|
||||||
for (let block of [...box.querySelectorAll('details')]) {
|
for (let block of $$('details')) {
|
||||||
if (block.dataset.id != 'invalid') {
|
if (block.dataset.id != 'invalid') {
|
||||||
block.style.cursor = 'pointer';
|
block.style.cursor = 'pointer';
|
||||||
block.onclick = event => {
|
block.onclick = event => {
|
||||||
const styleElement = $(`[style-id="${event.target.dataset.id}"]`);
|
const styleElement = $(`[style-id="${event.target.dataset.id}"]`);
|
||||||
if (styleElement) {
|
if (styleElement) {
|
||||||
scrollElementIntoView(styleElement);
|
scrollElementIntoView(styleElement);
|
||||||
highlightElement(styleElement);
|
animateElement(styleElement, {className: 'highlight'});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -221,7 +223,8 @@ function importFromString(jsonString) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('file-all-styles').onclick = () => {
|
|
||||||
|
$('#file-all-styles').onclick = () => {
|
||||||
getStyles({}, function (styles) {
|
getStyles({}, function (styles) {
|
||||||
const text = JSON.stringify(styles, null, '\t');
|
const text = JSON.stringify(styles, null, '\t');
|
||||||
const fileName = generateFileName();
|
const fileName = generateFileName();
|
||||||
|
@ -248,7 +251,7 @@ document.getElementById('file-all-styles').onclick = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
document.getElementById('unfile-all-styles').onclick = () => {
|
$('#unfile-all-styles').onclick = () => {
|
||||||
importFromFile({fileTypeFilter: STYLUS_BACKUP_FILE_EXT});
|
importFromFile({fileTypeFilter: STYLUS_BACKUP_FILE_EXT});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -264,11 +267,9 @@ Object.assign(document.body, {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ondragend(event) {
|
ondragend(event) {
|
||||||
this.classList.add('fadeout');
|
animateElement(this, {className: 'fadeout'}).then(() => {
|
||||||
this.addEventListener('animationend', function _() {
|
|
||||||
this.removeEventListener('animationend', _);
|
|
||||||
this.style.animationDuration = '';
|
this.style.animationDuration = '';
|
||||||
this.classList.remove('dropzone', 'fadeout');
|
this.classList.remove('dropzone');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
ondragleave(event) {
|
ondragleave(event) {
|
||||||
|
|
61
dom.js
Normal file
61
dom.js
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function onDOMready() {
|
||||||
|
if (document.readyState != 'loading') {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return new Promise(resolve => {
|
||||||
|
document.addEventListener('DOMContentLoaded', function _() {
|
||||||
|
document.removeEventListener('DOMContentLoaded', _);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getClickedStyleId(event) {
|
||||||
|
return (getClickedStyleElement(event) || {}).styleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getClickedStyleElement(event) {
|
||||||
|
return event.target.closest('.entry');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function scrollElementIntoView(element) {
|
||||||
|
// align to the top/bottom of the visible area if wasn't visible
|
||||||
|
const bounds = element.getBoundingClientRect();
|
||||||
|
if (bounds.top < 0 || bounds.top > innerHeight - bounds.height) {
|
||||||
|
element.scrollIntoView(bounds.top < 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function animateElement(element, {className, remove = false}) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
element.addEventListener('animationend', function _() {
|
||||||
|
element.removeEventListener('animationend', _);
|
||||||
|
element.classList.remove(className);
|
||||||
|
// TODO: investigate why animation restarts if the elements is removed in .then()
|
||||||
|
if (remove) {
|
||||||
|
element.remove();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
element.classList.add(className);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function $(selector, base = document) {
|
||||||
|
// we have ids with . like #manage.onlyEdited which look like #id.class
|
||||||
|
// so since getElementById is superfast we'll try it anyway
|
||||||
|
const byId = selector.startsWith('#') && document.getElementById(selector.slice(1));
|
||||||
|
return byId || base.querySelector(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function $$(selector, base = document) {
|
||||||
|
return [...base.querySelectorAll(selector)];
|
||||||
|
}
|
|
@ -53,6 +53,7 @@
|
||||||
<script src="storage.js"></script>
|
<script src="storage.js"></script>
|
||||||
<script src="messaging.js"></script>
|
<script src="messaging.js"></script>
|
||||||
<script src="apply.js"></script>
|
<script src="apply.js"></script>
|
||||||
|
<script src="dom.js"></script>
|
||||||
<script src="localization.js"></script>
|
<script src="localization.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
53
manage.js
53
manage.js
|
@ -230,7 +230,7 @@ class EntryOnClick {
|
||||||
function handleUpdate(style, {reason} = {}) {
|
function handleUpdate(style, {reason} = {}) {
|
||||||
const element = createStyleElement(style);
|
const element = createStyleElement(style);
|
||||||
const oldElement = $(`[style-id="${style.id}"]`, installed);
|
const oldElement = $(`[style-id="${style.id}"]`, installed);
|
||||||
highlightElement(element);
|
animateElement(element, {className: 'highlight'});
|
||||||
if (!oldElement) {
|
if (!oldElement) {
|
||||||
installed.appendChild(element);
|
installed.appendChild(element);
|
||||||
} else {
|
} else {
|
||||||
|
@ -260,12 +260,11 @@ function applyUpdateAll() {
|
||||||
btnApply.disabled = false;
|
btnApply.disabled = false;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
[...document.querySelectorAll('.can-update .update')]
|
$$('.can-update .update').forEach(button => {
|
||||||
.forEach(button => {
|
// align to the bottom of the visible area if wasn't visible
|
||||||
// align to the bottom of the visible area if wasn't visible
|
button.scrollIntoView(false);
|
||||||
button.scrollIntoView(false);
|
button.click();
|
||||||
button.click();
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -278,8 +277,7 @@ function checkUpdateAll() {
|
||||||
btnApply.classList.add('hidden');
|
btnApply.classList.add('hidden');
|
||||||
noUpdates.classList.add('hidden');
|
noUpdates.classList.add('hidden');
|
||||||
|
|
||||||
const elements = document.querySelectorAll('[style-update-url]');
|
Promise.all($$('[style-update-url]').map(checkUpdate))
|
||||||
Promise.all([...elements].map(checkUpdate))
|
|
||||||
.then(updatables => {
|
.then(updatables => {
|
||||||
btnCheck.disabled = false;
|
btnCheck.disabled = false;
|
||||||
if (updatables.includes(true)) {
|
if (updatables.includes(true)) {
|
||||||
|
@ -445,43 +443,6 @@ function searchStyles(immediately, bin) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getClickedStyleId(event) {
|
|
||||||
return (getClickedStyleElement(event) || {}).styleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getClickedStyleElement(event) {
|
|
||||||
return event.target.closest('.entry');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function scrollElementIntoView(element) {
|
|
||||||
// align to the top/bottom of the visible area if wasn't visible
|
|
||||||
const bounds = element.getBoundingClientRect();
|
|
||||||
if (bounds.top < 0 || bounds.top > innerHeight - bounds.height) {
|
|
||||||
element.scrollIntoView(bounds.top < 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function highlightElement(element) {
|
|
||||||
element.addEventListener('animationend', function _() {
|
|
||||||
element.removeEventListener('animationend', _);
|
|
||||||
element.classList.remove('highlight');
|
|
||||||
});
|
|
||||||
element.classList.add('highlight');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function rememberScrollPosition() {
|
function rememberScrollPosition() {
|
||||||
history.replaceState({scrollY}, document.title);
|
history.replaceState({scrollY}, document.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function $(selector, base = document) {
|
|
||||||
if (selector.startsWith('#') && /^#[^,\s]+$/.test(selector)) {
|
|
||||||
return document.getElementById(selector.slice(1));
|
|
||||||
} else {
|
|
||||||
return base.querySelector(selector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
13
messaging.js
13
messaging.js
|
@ -163,19 +163,6 @@ function openURL({url}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function onDOMready() {
|
|
||||||
if (document.readyState != 'loading') {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
return new Promise(resolve => {
|
|
||||||
document.addEventListener('DOMContentLoaded', function _() {
|
|
||||||
document.removeEventListener('DOMContentLoaded', _);
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function stringAsRegExp(s, flags) {
|
function stringAsRegExp(s, flags) {
|
||||||
return new RegExp(s.replace(/[{}()\[\]\/\\.+?^$:=*!|]/g, '\\$&'), flags);
|
return new RegExp(s.replace(/[{}()\[\]\/\\.+?^$:=*!|]/g, '\\$&'), flags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,11 +29,8 @@ function confirmDelete(event, {float = false} = {}) {
|
||||||
function doDelete(confirmed) {
|
function doDelete(confirmed) {
|
||||||
window.removeEventListener('keydown', onKey);
|
window.removeEventListener('keydown', onKey);
|
||||||
window.removeEventListener('scroll', preventScroll);
|
window.removeEventListener('scroll', preventScroll);
|
||||||
box.classList.add('lights-on');
|
animateElement(box, {className: 'lights-on'}).then(() => {
|
||||||
box.addEventListener('animationend', function _() {
|
|
||||||
box.removeEventListener('animationend', _);
|
|
||||||
box.dataset.display = false;
|
box.dataset.display = false;
|
||||||
box.classList.remove('lights-on');
|
|
||||||
});
|
});
|
||||||
Promise.resolve(confirmed && deleteStyle(id))
|
Promise.resolve(confirmed && deleteStyle(id))
|
||||||
.then(resolveMe);
|
.then(resolveMe);
|
||||||
|
|
|
@ -31,12 +31,7 @@ function messageBox({title, contents, buttons, onclick}) {
|
||||||
|| event.type == 'click'
|
|| event.type == 'click'
|
||||||
|| event.keyCode == 27 && !event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey)
|
|| event.keyCode == 27 && !event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey)
|
||||||
&& messageBox.element) {
|
&& messageBox.element) {
|
||||||
const box = messageBox.element;
|
animateElement(messageBox.element, {className: 'fadeout', remove: true});
|
||||||
box.classList.add('fadeout');
|
|
||||||
box.addEventListener('animationend', function _() {
|
|
||||||
box.removeEventListener('animationend', _);
|
|
||||||
box.remove();
|
|
||||||
});
|
|
||||||
document.removeEventListener('keydown', messageBox.close);
|
document.removeEventListener('keydown', messageBox.close);
|
||||||
$(`#${id}-buttons`).onclick = null;
|
$(`#${id}-buttons`).onclick = null;
|
||||||
messageBox.element = null;
|
messageBox.element = null;
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
<script src="storage.js"></script>
|
<script src="storage.js"></script>
|
||||||
<script src="messaging.js"></script>
|
<script src="messaging.js"></script>
|
||||||
<script src="apply.js"></script>
|
<script src="apply.js"></script>
|
||||||
|
<script src="dom.js"></script>
|
||||||
<script src="msgbox/confirm.js"></script>
|
<script src="msgbox/confirm.js"></script>
|
||||||
|
|
||||||
<script src="popup.js"></script>
|
<script src="popup.js"></script>
|
||||||
|
|
19
popup.js
19
popup.js
|
@ -199,16 +199,6 @@ class EntryOnClick {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getClickedStyleId(event) {
|
|
||||||
return (getClickedStyleElement(event) || {}).styleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getClickedStyleElement(event) {
|
|
||||||
return event.target.closest('.entry');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function openLinkInTabOrWindow(event) {
|
function openLinkInTabOrWindow(event) {
|
||||||
if (!prefs.get('openEditInWindow', false)) {
|
if (!prefs.get('openEditInWindow', false)) {
|
||||||
openURLandHide(event);
|
openURLandHide(event);
|
||||||
|
@ -272,12 +262,3 @@ function handleDelete(id) {
|
||||||
installed.removeChild(styleElement);
|
installed.removeChild(styleElement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function $(selector, base = document) {
|
|
||||||
if (selector.startsWith('#') && /^#[^,\s]+$/.test(selector)) {
|
|
||||||
return document.getElementById(selector.slice(1));
|
|
||||||
} else {
|
|
||||||
return base.querySelector(selector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user