diff options
| author | 2025-11-05 03:51:33 -0700 | |
|---|---|---|
| committer | 2025-11-05 11:51:33 +0100 | |
| commit | 63fe7438784cd56b9291d2a0dee3f872a53c7ae0 (patch) | |
| tree | 3e6302181e6fdaa012c6c043c7ec5de1a6fb2e2f | |
| parent | 0587ccaff844701b08306440c96c89cefa21b2c9 (diff) | |
Fix 7307 - Scroll after load (#7962)
* Fix 7307 - Scroll after load
Closes https://github.com/FreshRSS/FreshRSS/issues/7307
- Wrap the body of `loadDynamicTags()` into a Promise
- inside `mylabels()`, wait for the promise to complete, then scroll
- when `loadDynamicTags()` is not being called, return a self-resolving promise
How to test the feature manually:
1. Click on an long article
2. press keyboard shortcut `l` to go to "My labels"
3. page should scroll down
4. the `My labels` popup should be fully visible
* Rewritten as async/await
* Explicit HTTP Accept application/json
---------
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
| -rw-r--r-- | p/scripts/main.js | 149 |
1 files changed, 74 insertions, 75 deletions
diff --git a/p/scripts/main.js b/p/scripts/main.js index fe5e81f6d..73848060b 100644 --- a/p/scripts/main.js +++ b/p/scripts/main.js @@ -740,7 +740,7 @@ function user_filter(key) { } } -function show_labels_menu(el) { +async function show_labels_menu(el) { const div = el.parentElement; const dropdownMenu = div.querySelector('.dropdown-menu'); @@ -754,7 +754,7 @@ function show_labels_menu(el) { const template = document.getElementById(templateId).innerHTML; div.insertAdjacentHTML('beforeend', template); - loadDynamicTags(div.closest('.dynamictags')); + return loadDynamicTags(div.closest('.dynamictags')); } return true; } @@ -790,7 +790,7 @@ function show_share_menu(el) { return true; } -function mylabels(key) { +async function mylabels(key) { const mylabelsDropdown = document.querySelector('.flux.current.active .dropdown-target[id^="dropdown-labels"]'); if (!mylabelsDropdown) { @@ -798,7 +798,7 @@ function mylabels(key) { } if (typeof key === 'undefined') { - show_labels_menu(mylabelsDropdown); + await show_labels_menu(mylabelsDropdown); } // Display the mylabels div location.hash = mylabelsDropdown.id; @@ -1539,94 +1539,93 @@ function init_nav_entries() { // purpose of this flag: minimize the network traffic. let forceReloadLabelsList = false; -function loadDynamicTags(div) { +async function loadDynamicTags(div) { div.querySelectorAll('li.item').forEach(function (li) { li.remove(); }); const entryId = div.closest('div.flux').id.replace(/^flux_/, ''); - const req = new XMLHttpRequest(); - req.open('GET', './?c=tag&a=getTagsForEntry&id_entry=' + entryId, true); - req.responseType = 'json'; - req.onerror = function (e) { - div.querySelectorAll('li.item').forEach(function (li) { li.remove(); }); - }; - req.onload = function (e) { - if (this.status != 200) { - return req.onerror(e); - } - const json = xmlHttpRequestJson(this); - if (!json) { - return req.onerror(e); + let json; + try { + const response = await fetch('./?c=tag&a=getTagsForEntry&id_entry=' + entryId, { + headers: { + 'Accept': 'application/json', + } + }); + if (!response.ok) { + throw new Error('HTTP error ' + response.status); } + json = await response.json(); + } catch (ex) { + div.querySelectorAll('li.item').forEach(function (li) { li.remove(); }); + throw ex; + } - if (!context.anonymous) { - const li_item0 = document.createElement('li'); - li_item0.setAttribute('class', 'item addItem'); + if (!context.anonymous) { + const li_item0 = document.createElement('li'); + li_item0.setAttribute('class', 'item addItem'); - const label = document.createElement('label'); - label.setAttribute('class', 'noHover'); + const label = document.createElement('label'); + label.setAttribute('class', 'noHover'); - const input_checkboxTag = document.createElement('input'); - input_checkboxTag.setAttribute('class', 'checkboxTag checkboxNewTag'); - input_checkboxTag.setAttribute('name', 't_0'); - input_checkboxTag.setAttribute('type', 'checkbox'); + const input_checkboxTag = document.createElement('input'); + input_checkboxTag.setAttribute('class', 'checkboxTag checkboxNewTag'); + input_checkboxTag.setAttribute('name', 't_0'); + input_checkboxTag.setAttribute('type', 'checkbox'); - const input_newTag = document.createElement('input'); - input_newTag.setAttribute('type', 'text'); - input_newTag.setAttribute('name', 'newTag'); - input_newTag.setAttribute('class', 'newTag'); - input_newTag.setAttribute('list', 'datalist-labels'); - input_newTag.addEventListener('keydown', function (ev) { if (ev.key.toUpperCase() == 'ENTER') { this.parentNode.previousSibling.click(); } }); + const input_newTag = document.createElement('input'); + input_newTag.setAttribute('type', 'text'); + input_newTag.setAttribute('name', 'newTag'); + input_newTag.setAttribute('class', 'newTag'); + input_newTag.setAttribute('list', 'datalist-labels'); + input_newTag.addEventListener('keydown', function (ev) { if (ev.key.toUpperCase() == 'ENTER') { this.parentNode.previousSibling.click(); } }); - const button_btn = document.createElement('button'); - button_btn.setAttribute('type', 'button'); - button_btn.setAttribute('class', 'btn'); - button_btn.addEventListener('click', function () { this.parentNode.parentNode.click(); }); + const button_btn = document.createElement('button'); + button_btn.setAttribute('type', 'button'); + button_btn.setAttribute('class', 'btn'); + button_btn.addEventListener('click', function () { this.parentNode.parentNode.click(); }); - const text_plus = document.createTextNode('+'); + const text_plus = document.createTextNode('+'); - const div_stick = document.createElement('div'); - div_stick.setAttribute('class', 'stick'); + const div_stick = document.createElement('div'); + div_stick.setAttribute('class', 'stick'); - button_btn.appendChild(text_plus); - div_stick.appendChild(input_newTag); - div_stick.appendChild(button_btn); - label.appendChild(input_checkboxTag); - label.appendChild(div_stick); - li_item0.appendChild(label); + button_btn.appendChild(text_plus); + div_stick.appendChild(input_newTag); + div_stick.appendChild(button_btn); + label.appendChild(input_checkboxTag); + label.appendChild(div_stick); + li_item0.appendChild(label); - div.querySelector('.dropdown-menu-scrollable').appendChild(li_item0); - } + div.querySelector('.dropdown-menu-scrollable').appendChild(li_item0); + } - let html = ''; - let datalist = ''; - if (json && json.length) { - let nbLabelsChecked = 0; - for (let i = 0; i < json.length; i++) { - const tag = json[i]; - if (context.anonymous && !tag.checked) { - // In anomymous mode, show only the used tags - continue; - } - if (tag.checked) { - nbLabelsChecked++; - } - html += '<li class="item"><label><input ' + - (context.anonymous ? '' : 'class="checkboxTag" ') + - 'name="t_' + tag.id + '"type="checkbox" ' + - (context.anonymous ? 'disabled="disabled" ' : '') + - (tag.checked ? 'checked="checked" ' : '') + '/>' + tag.name + '</label></li>'; - datalist += '<option value="' + tag.name + '"></option>'; + let html = ''; + let datalist = ''; + if (json && json.length) { + let nbLabelsChecked = 0; + for (let i = 0; i < json.length; i++) { + const tag = json[i]; + if (context.anonymous && !tag.checked) { + // In anonymous mode, show only the used tags + continue; } - if (context.anonymous && nbLabelsChecked === 0) { - html += '<li class="item"><span class="emptyLabels">' + context.i18n.labels_empty + '</span></li>'; + if (tag.checked) { + nbLabelsChecked++; } + html += '<li class="item"><label><input ' + + (context.anonymous ? '' : 'class="checkboxTag" ') + + 'name="t_' + tag.id + '"type="checkbox" ' + + (context.anonymous ? 'disabled="disabled" ' : '') + + (tag.checked ? 'checked="checked" ' : '') + '/>' + tag.name + '</label></li>'; + datalist += '<option value="' + tag.name + '"></option>'; } - div.querySelector('.dropdown-menu-scrollable').insertAdjacentHTML('beforeend', html); - const datalistLabels = document.getElementById('datalist-labels'); - datalistLabels.innerHTML = ''; // clear before add the (updated) labels list - datalistLabels.insertAdjacentHTML('beforeend', datalist); - }; - req.send(); + if (context.anonymous && nbLabelsChecked === 0) { + html += '<li class="item"><span class="emptyLabels">' + context.i18n.labels_empty + '</span></li>'; + } + } + div.querySelector('.dropdown-menu-scrollable').insertAdjacentHTML('beforeend', html); + const datalistLabels = document.getElementById('datalist-labels'); + datalistLabels.innerHTML = ''; // clear before add the (updated) labels list + datalistLabels.insertAdjacentHTML('beforeend', datalist); } // <actualize> |
