dom.js: extract common DOM functions
This commit is contained in:
parent
0f8fd5c07c
commit
4936426fa3
|
@ -35,6 +35,12 @@ globals:
|
|||
importStyles: true
|
||||
getActiveTabRealURL: true
|
||||
openURL: true
|
||||
$: true
|
||||
$$: true
|
||||
animateElement: true
|
||||
scrollElementIntoView: true
|
||||
getClickedStyleElement: true
|
||||
getClickedStyleId: true
|
||||
onDOMready: true
|
||||
getDomains: true
|
||||
webSqlStorage: true
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
/* globals getStyles, saveStyle, invalidateCache, refreshAllTabs, handleUpdate */
|
||||
/* globals getStyles, saveStyle, invalidateCache, refreshAllTabs */
|
||||
'use strict';
|
||||
|
||||
const STYLISH_DUMP_FILE_EXT = '.txt';
|
||||
const STYLUS_BACKUP_FILE_EXT = '.json';
|
||||
|
||||
|
||||
function importFromFile({fileTypeFilter, file} = {}) {
|
||||
return new Promise(resolve => {
|
||||
const fileInput = document.createElement('input');
|
||||
|
@ -44,6 +45,7 @@ function importFromFile({fileTypeFilter, file} = {}) {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
function importFromString(jsonString) {
|
||||
const json = runTryCatch(() => Array.from(JSON.parse(jsonString))) || [];
|
||||
const oldStyles = json.length && deepCopyStyles();
|
||||
|
@ -177,14 +179,14 @@ function importFromString(jsonString) {
|
|||
}
|
||||
|
||||
function bindClick(box) {
|
||||
for (let block of [...box.querySelectorAll('details')]) {
|
||||
for (let block of $$('details')) {
|
||||
if (block.dataset.id != 'invalid') {
|
||||
block.style.cursor = 'pointer';
|
||||
block.onclick = event => {
|
||||
const styleElement = $(`[style-id="${event.target.dataset.id}"]`);
|
||||
if (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) {
|
||||
const text = JSON.stringify(styles, null, '\t');
|
||||
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});
|
||||
};
|
||||
|
||||
|
@ -264,11 +267,9 @@ Object.assign(document.body, {
|
|||
}
|
||||
},
|
||||
ondragend(event) {
|
||||
this.classList.add('fadeout');
|
||||
this.addEventListener('animationend', function _() {
|
||||
this.removeEventListener('animationend', _);
|
||||
animateElement(this, {className: 'fadeout'}).then(() => {
|
||||
this.style.animationDuration = '';
|
||||
this.classList.remove('dropzone', 'fadeout');
|
||||
this.classList.remove('dropzone');
|
||||
});
|
||||
},
|
||||
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="messaging.js"></script>
|
||||
<script src="apply.js"></script>
|
||||
<script src="dom.js"></script>
|
||||
<script src="localization.js"></script>
|
||||
</head>
|
||||
|
||||
|
|
45
manage.js
45
manage.js
|
@ -230,7 +230,7 @@ class EntryOnClick {
|
|||
function handleUpdate(style, {reason} = {}) {
|
||||
const element = createStyleElement(style);
|
||||
const oldElement = $(`[style-id="${style.id}"]`, installed);
|
||||
highlightElement(element);
|
||||
animateElement(element, {className: 'highlight'});
|
||||
if (!oldElement) {
|
||||
installed.appendChild(element);
|
||||
} else {
|
||||
|
@ -260,8 +260,7 @@ function applyUpdateAll() {
|
|||
btnApply.disabled = false;
|
||||
}, 1000);
|
||||
|
||||
[...document.querySelectorAll('.can-update .update')]
|
||||
.forEach(button => {
|
||||
$$('.can-update .update').forEach(button => {
|
||||
// align to the bottom of the visible area if wasn't visible
|
||||
button.scrollIntoView(false);
|
||||
button.click();
|
||||
|
@ -278,8 +277,7 @@ function checkUpdateAll() {
|
|||
btnApply.classList.add('hidden');
|
||||
noUpdates.classList.add('hidden');
|
||||
|
||||
const elements = document.querySelectorAll('[style-update-url]');
|
||||
Promise.all([...elements].map(checkUpdate))
|
||||
Promise.all($$('[style-update-url]').map(checkUpdate))
|
||||
.then(updatables => {
|
||||
btnCheck.disabled = false;
|
||||
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() {
|
||||
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) {
|
||||
return new RegExp(s.replace(/[{}()\[\]\/\\.+?^$:=*!|]/g, '\\$&'), flags);
|
||||
}
|
||||
|
|
|
@ -29,11 +29,8 @@ function confirmDelete(event, {float = false} = {}) {
|
|||
function doDelete(confirmed) {
|
||||
window.removeEventListener('keydown', onKey);
|
||||
window.removeEventListener('scroll', preventScroll);
|
||||
box.classList.add('lights-on');
|
||||
box.addEventListener('animationend', function _() {
|
||||
box.removeEventListener('animationend', _);
|
||||
animateElement(box, {className: 'lights-on'}).then(() => {
|
||||
box.dataset.display = false;
|
||||
box.classList.remove('lights-on');
|
||||
});
|
||||
Promise.resolve(confirmed && deleteStyle(id))
|
||||
.then(resolveMe);
|
||||
|
|
|
@ -31,12 +31,7 @@ function messageBox({title, contents, buttons, onclick}) {
|
|||
|| event.type == 'click'
|
||||
|| event.keyCode == 27 && !event.altKey && !event.ctrlKey && !event.shiftKey && !event.metaKey)
|
||||
&& messageBox.element) {
|
||||
const box = messageBox.element;
|
||||
box.classList.add('fadeout');
|
||||
box.addEventListener('animationend', function _() {
|
||||
box.removeEventListener('animationend', _);
|
||||
box.remove();
|
||||
});
|
||||
animateElement(messageBox.element, {className: 'fadeout', remove: true});
|
||||
document.removeEventListener('keydown', messageBox.close);
|
||||
$(`#${id}-buttons`).onclick = null;
|
||||
messageBox.element = null;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
<script src="storage.js"></script>
|
||||
<script src="messaging.js"></script>
|
||||
<script src="apply.js"></script>
|
||||
<script src="dom.js"></script>
|
||||
<script src="msgbox/confirm.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) {
|
||||
if (!prefs.get('openEditInWindow', false)) {
|
||||
openURLandHide(event);
|
||||
|
@ -272,12 +262,3 @@ function handleDelete(id) {
|
|||
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