diff options
| author | 2021-01-13 14:34:45 -0500 | |
|---|---|---|
| committer | 2021-01-13 20:34:45 +0100 | |
| commit | e3457f7d7b56509048e3c1f53f05f278656e976c (patch) | |
| tree | f9bd9fb43436e7958b70bc0a91e0431afd480f17 /p/scripts/user.query.js | |
| parent | b43b94dff8b2d7e8f052907f2459d2ad54b5cb68 (diff) | |
Add drag & drop marker on user query list (#3355)
Before, it was nearly impossible to know exactly where the dragged
item will land when dropping it.
Now, there is a visual marker to show the drop location.
An HR tag is inserted dynamically in the DOM. It's possible to style
it if needed.
Diffstat (limited to 'p/scripts/user.query.js')
| -rw-r--r-- | p/scripts/user.query.js | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/p/scripts/user.query.js b/p/scripts/user.query.js index c828cef19..2652442c3 100644 --- a/p/scripts/user.query.js +++ b/p/scripts/user.query.js @@ -2,7 +2,7 @@ "use strict"; /* jshint esversion:6, strict:global */ -function init_draggable() { +const init_draggable = function() { if (!window.context) { if (window.console) { console.log('FreshRSS user query waiting for JS…'); @@ -13,32 +13,80 @@ function init_draggable() { let source; const configureQueries = document.querySelector('#configureQueries'); + const addMarker = (position, element) => { + const hr = configureQueries.querySelector('hr.drag-drop-marker'); + if (null === hr) { + element.insertAdjacentHTML(position, '<hr class="drag-drop-marker" />'); + } + }; + const removeMarker = () => { + const hr = configureQueries.querySelector('hr.drag-drop-marker'); + if (null !== hr) { + hr.remove(); + } + }; configureQueries.addEventListener('dragstart', event => { source = event.target.closest('[draggable="true"]'); event.dataTransfer.setData('text/html', source.outerHTML); event.dataTransfer.effectAllowed = 'move'; }); - configureQueries.addEventListener('dragover', event => event.preventDefault()); - configureQueries.addEventListener('dragleave', event => event.preventDefault()); + configureQueries.addEventListener('dragover', event => { + event.preventDefault(); + if (!event.target || !event.target.closest) { + return; + } + + const dropQuery = event.target.closest('[draggable="true"]'); + if (null === dropQuery || source === dropQuery) { + return; + } + + const rect = dropQuery.getBoundingClientRect(); + if (event.clientY < (rect.top + rect.height / 2)) { + addMarker('beforebegin', dropQuery); + } else { + addMarker('afterend', dropQuery); + } + }); + configureQueries.addEventListener('dragleave', event => { + event.preventDefault(); + removeMarker(); + }); configureQueries.addEventListener('drop', event => { event.preventDefault(); event.stopPropagation(); + if (!event.target || !event.target.closest) { + return; + } + const dropQuery = event.target.closest('[draggable="true"]'); - if (null === dropQuery) { - source.remove(); - configureQueries.querySelector('legend').insertAdjacentHTML('afterend', event.dataTransfer.getData('text/html')); - } else if (source !== dropQuery) { - source.remove(); + if (null === dropQuery || source === dropQuery) { + return; + } + + const rect = dropQuery.getBoundingClientRect(); + if (event.clientY < (rect.top + rect.height / 2)) { + dropQuery.insertAdjacentHTML('beforebegin', event.dataTransfer.getData('text/html')); + } else { dropQuery.insertAdjacentHTML('afterend', event.dataTransfer.getData('text/html')); } + source.remove(); + removeMarker(); }); // This is needed to work around a Firefox bug → https://bugzilla.mozilla.org/show_bug.cgi?id=800050 configureQueries.addEventListener('focusin', event => { - event.target.closest('input[id^="queries_"][id$="_name"]').select(); + if (!event.target || !event.target.closest) { + return; + } + + const queryName = event.target.closest('input[id^="queries_"][id$="_name"]'); + if (null !== queryName) { + queryName.select(); + } }); -} +}; if (document.readyState && document.readyState !== 'loading') { init_draggable(); |
