Преглед изворни кода

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>
Tommaso Ferrari пре 5 месеци
родитељ
комит
63fe743878
1 измењених фајлова са 74 додато и 75 уклоњено
  1. 74 75
      p/scripts/main.js

+ 74 - 75
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>