dom.js: extract common DOM functions

This commit is contained in:
tophf 2017-03-25 08:54:58 +03:00
parent 0f8fd5c07c
commit 4936426fa3
10 changed files with 88 additions and 97 deletions

View File

@ -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

View File

@ -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
View 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)];
}

View File

@ -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>

View File

@ -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,8 +260,7 @@ 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);
}
}

View File

@ -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);
} }

View File

@ -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);

View File

@ -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;

View File

@ -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>

View File

@ -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);
}
}