2019-07-18 05:27:39 +02:00
|
|
|
// OnClick attaches a listener to the elements that match the selector.
|
|
|
|
function onClick(selector, callback, noPreventDefault) {
|
|
|
|
let elements = document.querySelectorAll(selector);
|
|
|
|
elements.forEach((element) => {
|
|
|
|
element.onclick = (event) => {
|
|
|
|
if (!noPreventDefault) {
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
|
|
|
|
callback(event);
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-04-27 14:45:05 +02:00
|
|
|
function onAuxClick(selector, callback, noPreventDefault) {
|
|
|
|
let elements = document.querySelectorAll(selector);
|
|
|
|
elements.forEach((element) => {
|
|
|
|
element.onauxclick = (event) => {
|
|
|
|
if (!noPreventDefault) {
|
|
|
|
event.preventDefault();
|
|
|
|
}
|
|
|
|
|
|
|
|
callback(event);
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2024-02-07 09:54:11 +01:00
|
|
|
// make logo element as button on mobile layout
|
|
|
|
function checkMenuToggleModeByLayout() {
|
|
|
|
const logoElement = document.querySelector(".logo");
|
2024-03-11 04:32:39 +01:00
|
|
|
const homePageLinkElement = document.querySelector(".logo > a");
|
|
|
|
if (!logoElement) return;
|
|
|
|
const logoToggleButtonLabel = logoElement.getAttribute("data-toggle-button-label");
|
2024-02-07 09:54:11 +01:00
|
|
|
|
|
|
|
const navMenuElement = document.getElementById("header-menu");
|
2024-03-11 04:32:39 +01:00
|
|
|
const navMenuElementIsExpanded = navMenuElement.classList.contains("js-menu-show");
|
2024-02-07 09:54:11 +01:00
|
|
|
|
|
|
|
if (document.documentElement.clientWidth < 620) {
|
|
|
|
logoElement.setAttribute("role", "button");
|
|
|
|
logoElement.setAttribute("tabindex", "0");
|
2024-03-11 04:32:39 +01:00
|
|
|
logoElement.setAttribute("aria-label", logoToggleButtonLabel);
|
2024-02-07 09:54:11 +01:00
|
|
|
if (navMenuElementIsExpanded) {
|
2024-03-11 04:32:39 +01:00
|
|
|
logoElement.setAttribute("aria-expanded", "true");
|
2024-02-07 09:54:11 +01:00
|
|
|
} else {
|
2024-03-11 04:32:39 +01:00
|
|
|
logoElement.setAttribute("aria-expanded", "false");
|
2024-02-07 09:54:11 +01:00
|
|
|
}
|
2024-03-11 04:32:39 +01:00
|
|
|
homePageLinkElement.setAttribute("tabindex", "-1");
|
2024-02-07 09:54:11 +01:00
|
|
|
} else {
|
|
|
|
logoElement.removeAttribute("role");
|
|
|
|
logoElement.removeAttribute("tabindex");
|
|
|
|
logoElement.removeAttribute("aria-expanded");
|
2024-03-11 04:32:39 +01:00
|
|
|
logoElement.removeAttribute("aria-label");
|
2024-02-07 09:54:11 +01:00
|
|
|
homePageLinkElement.removeAttribute("tabindex");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-14 10:07:56 +01:00
|
|
|
function fixVoiceOverDetailsSummaryBug() {
|
2024-03-11 04:32:39 +01:00
|
|
|
const detailsElements = document.querySelectorAll("details");
|
2024-02-14 10:07:56 +01:00
|
|
|
detailsElements.forEach((details) => {
|
2024-03-11 04:32:39 +01:00
|
|
|
const summaryElement = details.querySelector("summary");
|
|
|
|
summaryElement.setAttribute("role", "button");
|
|
|
|
setSummaryAriaExpandedByDetails(details, summaryElement);
|
2024-02-14 10:07:56 +01:00
|
|
|
|
|
|
|
details.addEventListener("toggle", () => {
|
2024-03-11 04:32:39 +01:00
|
|
|
setSummaryAriaExpandedByDetails(details, summaryElement);
|
|
|
|
});
|
|
|
|
});
|
2024-02-14 10:07:56 +01:00
|
|
|
|
|
|
|
function setSummaryAriaExpandedByDetails(details, summary) {
|
|
|
|
if (details.open) {
|
2024-03-11 04:32:39 +01:00
|
|
|
summary.setAttribute("aria-expanded", "true");
|
2024-02-14 10:07:56 +01:00
|
|
|
} else {
|
2024-03-11 04:32:39 +01:00
|
|
|
summary.setAttribute("aria-expanded", "false");
|
2024-02-14 10:07:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 05:27:39 +02:00
|
|
|
// Show and hide the main menu on mobile devices.
|
2024-02-07 09:54:11 +01:00
|
|
|
function toggleMainMenu(event) {
|
|
|
|
if (event.type === "keydown" && !(event.key === "Enter" || event.key === " ")) {
|
2024-03-11 04:32:39 +01:00
|
|
|
return;
|
2024-02-07 09:54:11 +01:00
|
|
|
}
|
2024-03-11 04:32:39 +01:00
|
|
|
|
2024-02-07 09:54:11 +01:00
|
|
|
if (event.currentTarget.getAttribute("role")) {
|
2024-03-11 04:32:39 +01:00
|
|
|
event.preventDefault();
|
2024-02-07 09:54:11 +01:00
|
|
|
}
|
|
|
|
|
2019-07-18 05:27:39 +02:00
|
|
|
let menu = document.querySelector(".header nav ul");
|
2024-02-07 09:54:11 +01:00
|
|
|
let menuToggleButton = document.querySelector(".logo");
|
2024-01-25 09:36:10 +01:00
|
|
|
if (menu.classList.contains("js-menu-show")) {
|
2024-03-11 04:32:39 +01:00
|
|
|
menu.classList.remove("js-menu-show");
|
|
|
|
menuToggleButton.setAttribute("aria-expanded", false);
|
2019-07-18 05:27:39 +02:00
|
|
|
} else {
|
2024-03-11 04:32:39 +01:00
|
|
|
menu.classList.add("js-menu-show");
|
|
|
|
menuToggleButton.setAttribute("aria-expanded", true);
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle click events for the main menu (<li> and <a>).
|
|
|
|
function onClickMainMenuListItem(event) {
|
|
|
|
let element = event.target;
|
|
|
|
|
|
|
|
if (element.tagName === "A") {
|
|
|
|
window.location.href = element.getAttribute("href");
|
|
|
|
} else {
|
|
|
|
window.location.href = element.querySelector("a").getAttribute("href");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Change the button label when the page is loading.
|
|
|
|
function handleSubmitButtons() {
|
|
|
|
let elements = document.querySelectorAll("form");
|
|
|
|
elements.forEach((element) => {
|
|
|
|
element.onsubmit = () => {
|
2019-08-16 07:08:24 +02:00
|
|
|
let button = element.querySelector("button");
|
2019-07-18 05:27:39 +02:00
|
|
|
|
|
|
|
if (button) {
|
2024-03-11 01:16:36 +01:00
|
|
|
button.textContent = button.dataset.labelLoading;
|
2019-07-18 05:27:39 +02:00
|
|
|
button.disabled = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show modal dialog with the list of keyboard shortcuts.
|
|
|
|
function showKeyboardShortcuts() {
|
|
|
|
let template = document.getElementById("keyboard-shortcuts");
|
|
|
|
if (template !== null) {
|
2023-07-02 22:28:02 +02:00
|
|
|
ModalHandler.open(template.content, "dialog-title");
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark as read visible items of the current page.
|
|
|
|
function markPageAsRead() {
|
|
|
|
let items = DomHelper.getVisibleElements(".items .item");
|
|
|
|
let entryIDs = [];
|
|
|
|
|
|
|
|
items.forEach((element) => {
|
|
|
|
element.classList.add("item-status-read");
|
|
|
|
entryIDs.push(parseInt(element.dataset.id, 10));
|
|
|
|
});
|
|
|
|
|
|
|
|
if (entryIDs.length > 0) {
|
|
|
|
updateEntriesStatus(entryIDs, "read", () => {
|
|
|
|
// Make sure the Ajax request reach the server before we reload the page.
|
|
|
|
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let element = document.querySelector(":is(a, button)[data-action=markPageAsRead]");
|
2019-07-18 05:27:39 +02:00
|
|
|
let showOnlyUnread = false;
|
|
|
|
if (element) {
|
2019-07-18 06:07:29 +02:00
|
|
|
showOnlyUnread = element.dataset.showOnlyUnread || false;
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (showOnlyUnread) {
|
2021-03-04 17:13:51 +01:00
|
|
|
window.location.href = window.location.href;
|
2019-07-18 05:27:39 +02:00
|
|
|
} else {
|
|
|
|
goToPage("next", true);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-01 04:57:14 +01:00
|
|
|
/**
|
|
|
|
* Handle entry status changes from the list view and entry view.
|
|
|
|
* Focus the next or the previous entry if it exists.
|
|
|
|
* @param {string} item Item to focus: "previous" or "next".
|
|
|
|
* @param {Element} element
|
|
|
|
* @param {boolean} setToRead
|
|
|
|
*/
|
|
|
|
function handleEntryStatus(item, element, setToRead) {
|
2022-01-29 22:53:10 +01:00
|
|
|
let toasting = !element;
|
|
|
|
let currentEntry = findEntry(element);
|
|
|
|
if (currentEntry) {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
if (!setToRead || currentEntry.querySelector(":is(a, button)[data-toggle-status]").dataset.value == "unread") {
|
2022-01-29 22:53:10 +01:00
|
|
|
toggleEntryStatus(currentEntry, toasting);
|
|
|
|
}
|
|
|
|
if (isListView() && currentEntry.classList.contains('current-item')) {
|
2022-02-01 04:57:14 +01:00
|
|
|
switch (item) {
|
|
|
|
case "previous":
|
|
|
|
goToListItem(-1);
|
|
|
|
break;
|
|
|
|
case "next":
|
|
|
|
goToListItem(1);
|
|
|
|
break;
|
|
|
|
}
|
2022-01-29 22:53:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 05:27:39 +02:00
|
|
|
// Change the entry status to the opposite value.
|
2019-10-07 05:55:15 +02:00
|
|
|
function toggleEntryStatus(element, toasting) {
|
2019-07-18 05:27:39 +02:00
|
|
|
let entryID = parseInt(element.dataset.id, 10);
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let link = element.querySelector(":is(a, button)[data-toggle-status]");
|
2019-07-18 05:27:39 +02:00
|
|
|
|
|
|
|
let currentStatus = link.dataset.value;
|
|
|
|
let newStatus = currentStatus === "read" ? "unread" : "read";
|
|
|
|
|
2024-03-11 01:16:36 +01:00
|
|
|
link.querySelector("span").textContent = link.dataset.labelLoading;
|
2021-06-12 22:00:05 +02:00
|
|
|
updateEntriesStatus([entryID], newStatus, () => {
|
|
|
|
let iconElement, label;
|
|
|
|
|
|
|
|
if (currentStatus === "read") {
|
|
|
|
iconElement = document.querySelector("template#icon-read");
|
|
|
|
label = link.dataset.labelRead;
|
|
|
|
if (toasting) {
|
|
|
|
showToast(link.dataset.toastUnread, iconElement);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
iconElement = document.querySelector("template#icon-unread");
|
|
|
|
label = link.dataset.labelUnread;
|
|
|
|
if (toasting) {
|
|
|
|
showToast(link.dataset.toastRead, iconElement);
|
|
|
|
}
|
2019-10-07 05:55:15 +02:00
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
|
2021-06-12 22:00:05 +02:00
|
|
|
link.innerHTML = iconElement.innerHTML + '<span class="icon-label">' + label + '</span>';
|
|
|
|
link.dataset.value = newStatus;
|
2020-12-30 05:47:18 +01:00
|
|
|
|
2021-06-12 22:00:05 +02:00
|
|
|
if (element.classList.contains("item-status-" + currentStatus)) {
|
|
|
|
element.classList.remove("item-status-" + currentStatus);
|
|
|
|
element.classList.add("item-status-" + newStatus);
|
|
|
|
}
|
|
|
|
});
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Mark a single entry as read.
|
|
|
|
function markEntryAsRead(element) {
|
|
|
|
if (element.classList.contains("item-status-unread")) {
|
|
|
|
element.classList.remove("item-status-unread");
|
|
|
|
element.classList.add("item-status-read");
|
|
|
|
|
|
|
|
let entryID = parseInt(element.dataset.id, 10);
|
|
|
|
updateEntriesStatus([entryID], "read");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-27 06:35:44 +02:00
|
|
|
// Send the Ajax request to refresh all feeds in the background
|
|
|
|
function handleRefreshAllFeeds() {
|
|
|
|
let url = document.body.dataset.refreshAllFeedsUrl;
|
|
|
|
|
2023-10-19 04:57:02 +02:00
|
|
|
if (url) {
|
|
|
|
window.location.href = url;
|
|
|
|
}
|
2020-05-27 06:35:44 +02:00
|
|
|
}
|
|
|
|
|
2019-07-18 05:27:39 +02:00
|
|
|
// Send the Ajax request to change entries statuses.
|
|
|
|
function updateEntriesStatus(entryIDs, status, callback) {
|
|
|
|
let url = document.body.dataset.entriesStatusUrl;
|
|
|
|
let request = new RequestBuilder(url);
|
2020-05-27 06:35:44 +02:00
|
|
|
request.withBody({entry_ids: entryIDs, status: status});
|
2021-06-03 02:39:47 +02:00
|
|
|
request.withCallback((resp) => {
|
|
|
|
resp.json().then(count => {
|
2023-08-01 06:11:39 +02:00
|
|
|
if (callback) {
|
|
|
|
callback(resp);
|
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
|
2021-06-03 02:39:47 +02:00
|
|
|
if (status === "read") {
|
|
|
|
decrementUnreadCounter(count);
|
|
|
|
} else {
|
|
|
|
incrementUnreadCounter(count);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
request.execute();
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle save entry from list view and entry view.
|
2019-07-26 04:02:39 +02:00
|
|
|
function handleSaveEntry(element) {
|
2019-10-07 05:55:15 +02:00
|
|
|
let toasting = !element;
|
2019-07-26 04:02:39 +02:00
|
|
|
let currentEntry = findEntry(element);
|
|
|
|
if (currentEntry) {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
saveEntry(currentEntry.querySelector(":is(a, button)[data-save-entry]"), toasting);
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the Ajax request to save an entry.
|
2019-10-07 05:55:15 +02:00
|
|
|
function saveEntry(element, toasting) {
|
2019-07-18 05:27:39 +02:00
|
|
|
if (!element) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (element.dataset.completed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-22 23:18:12 +01:00
|
|
|
element.innerHTML = '<span class="icon-label">' + element.dataset.labelLoading + '</span>';
|
2019-07-18 05:27:39 +02:00
|
|
|
|
|
|
|
let request = new RequestBuilder(element.dataset.saveUrl);
|
|
|
|
request.withCallback(() => {
|
2024-02-10 21:42:03 +01:00
|
|
|
element.innerHTML = '<span class="icon-label">' + element.dataset.labelDone + '</span>';
|
2019-07-18 05:27:39 +02:00
|
|
|
element.dataset.completed = true;
|
2019-10-07 05:55:15 +02:00
|
|
|
if (toasting) {
|
2021-03-07 20:55:43 +01:00
|
|
|
let iconElement = document.querySelector("template#icon-save");
|
|
|
|
showToast(element.dataset.toastDone, iconElement);
|
2019-10-07 05:55:15 +02:00
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
});
|
|
|
|
request.execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle bookmark from the list view and entry view.
|
2019-07-26 04:02:39 +02:00
|
|
|
function handleBookmark(element) {
|
2019-10-07 05:55:15 +02:00
|
|
|
let toasting = !element;
|
2019-07-26 04:02:39 +02:00
|
|
|
let currentEntry = findEntry(element);
|
|
|
|
if (currentEntry) {
|
2019-10-07 05:55:15 +02:00
|
|
|
toggleBookmark(currentEntry, toasting);
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the Ajax request and change the icon when bookmarking an entry.
|
2019-10-07 05:55:15 +02:00
|
|
|
function toggleBookmark(parentElement, toasting) {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let element = parentElement.querySelector(":is(a, button)[data-toggle-bookmark]");
|
2019-07-18 05:27:39 +02:00
|
|
|
if (!element) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-22 23:18:12 +01:00
|
|
|
element.innerHTML = '<span class="icon-label">' + element.dataset.labelLoading + '</span>';
|
2019-07-18 05:27:39 +02:00
|
|
|
|
|
|
|
let request = new RequestBuilder(element.dataset.bookmarkUrl);
|
|
|
|
request.withCallback(() => {
|
2020-12-30 05:47:18 +01:00
|
|
|
|
|
|
|
let currentStarStatus = element.dataset.value;
|
|
|
|
let newStarStatus = currentStarStatus === "star" ? "unstar" : "star";
|
|
|
|
|
2021-03-07 20:55:43 +01:00
|
|
|
let iconElement, label;
|
2020-12-30 05:47:18 +01:00
|
|
|
|
|
|
|
if (currentStarStatus === "star") {
|
2021-03-07 20:55:43 +01:00
|
|
|
iconElement = document.querySelector("template#icon-star");
|
2020-12-30 05:47:18 +01:00
|
|
|
label = element.dataset.labelStar;
|
2019-10-07 05:55:15 +02:00
|
|
|
if (toasting) {
|
2021-03-07 20:55:43 +01:00
|
|
|
showToast(element.dataset.toastUnstar, iconElement);
|
2019-10-07 05:55:15 +02:00
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
} else {
|
2021-03-07 20:55:43 +01:00
|
|
|
iconElement = document.querySelector("template#icon-unstar");
|
2020-12-30 05:47:18 +01:00
|
|
|
label = element.dataset.labelUnstar;
|
2019-10-07 05:55:15 +02:00
|
|
|
if (toasting) {
|
2021-03-07 20:55:43 +01:00
|
|
|
showToast(element.dataset.toastStar, iconElement);
|
2019-10-07 05:55:15 +02:00
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
2020-12-30 05:47:18 +01:00
|
|
|
|
2021-03-07 20:55:43 +01:00
|
|
|
element.innerHTML = iconElement.innerHTML + '<span class="icon-label">' + label + '</span>';
|
2020-12-30 05:47:18 +01:00
|
|
|
element.dataset.value = newStarStatus;
|
2019-07-18 05:27:39 +02:00
|
|
|
});
|
|
|
|
request.execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the Ajax request to download the original web page.
|
|
|
|
function handleFetchOriginalContent() {
|
|
|
|
if (isListView()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let element = document.querySelector(":is(a, button)[data-fetch-content-entry]");
|
2019-07-18 05:27:39 +02:00
|
|
|
if (!element) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-11 04:32:39 +01:00
|
|
|
let previousElement = element.cloneNode(true);
|
2020-03-22 23:18:12 +01:00
|
|
|
element.innerHTML = '<span class="icon-label">' + element.dataset.labelLoading + '</span>';
|
2019-07-18 05:27:39 +02:00
|
|
|
|
|
|
|
let request = new RequestBuilder(element.dataset.fetchContentUrl);
|
|
|
|
request.withCallback((response) => {
|
2024-03-11 01:16:36 +01:00
|
|
|
element.textContent = '';
|
|
|
|
element.appendChild(previousElement);
|
2019-07-18 05:27:39 +02:00
|
|
|
|
|
|
|
response.json().then((data) => {
|
2022-12-14 13:32:45 +01:00
|
|
|
if (data.hasOwnProperty("content") && data.hasOwnProperty("reading_time")) {
|
2019-07-18 05:27:39 +02:00
|
|
|
document.querySelector(".entry-content").innerHTML = data.content;
|
2023-10-07 02:15:09 +02:00
|
|
|
let entryReadingtimeElement = document.querySelector(".entry-reading-time");
|
|
|
|
if (entryReadingtimeElement) {
|
|
|
|
entryReadingtimeElement.innerHTML = data.reading_time;
|
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
request.execute();
|
|
|
|
}
|
|
|
|
|
2019-11-29 22:48:56 +01:00
|
|
|
function openOriginalLink(openLinkInCurrentTab) {
|
2019-07-18 05:27:39 +02:00
|
|
|
let entryLink = document.querySelector(".entry h1 a");
|
|
|
|
if (entryLink !== null) {
|
2019-11-29 22:48:56 +01:00
|
|
|
if (openLinkInCurrentTab) {
|
|
|
|
window.location.href = entryLink.getAttribute("href");
|
|
|
|
} else {
|
|
|
|
DomHelper.openNewTab(entryLink.getAttribute("href"));
|
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let currentItemOriginalLink = document.querySelector(".current-item :is(a, button)[data-original-link]");
|
2019-07-18 05:27:39 +02:00
|
|
|
if (currentItemOriginalLink !== null) {
|
|
|
|
DomHelper.openNewTab(currentItemOriginalLink.getAttribute("href"));
|
|
|
|
|
|
|
|
let currentItem = document.querySelector(".current-item");
|
2020-01-13 21:57:31 +01:00
|
|
|
// If we are not on the list of starred items, move to the next item
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
if (document.location.href != document.querySelector(':is(a, button)[data-page=starred]').href) {
|
2022-02-01 04:57:14 +01:00
|
|
|
goToListItem(1);
|
2020-01-13 21:57:31 +01:00
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
markEntryAsRead(currentItem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-07 07:02:02 +01:00
|
|
|
function openCommentLink(openLinkInCurrentTab) {
|
|
|
|
if (!isListView()) {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let entryLink = document.querySelector(":is(a, button)[data-comments-link]");
|
2020-01-07 07:02:02 +01:00
|
|
|
if (entryLink !== null) {
|
|
|
|
if (openLinkInCurrentTab) {
|
|
|
|
window.location.href = entryLink.getAttribute("href");
|
|
|
|
} else {
|
|
|
|
DomHelper.openNewTab(entryLink.getAttribute("href"));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let currentItemCommentsLink = document.querySelector(".current-item :is(a, button)[data-comments-link]");
|
2020-01-07 07:02:02 +01:00
|
|
|
if (currentItemCommentsLink !== null) {
|
|
|
|
DomHelper.openNewTab(currentItemCommentsLink.getAttribute("href"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 05:27:39 +02:00
|
|
|
function openSelectedItem() {
|
|
|
|
let currentItemLink = document.querySelector(".current-item .item-title a");
|
|
|
|
if (currentItemLink !== null) {
|
|
|
|
window.location.href = currentItemLink.getAttribute("href");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function unsubscribeFromFeed() {
|
|
|
|
let unsubscribeLinks = document.querySelectorAll("[data-action=remove-feed]");
|
|
|
|
if (unsubscribeLinks.length === 1) {
|
|
|
|
let unsubscribeLink = unsubscribeLinks[0];
|
|
|
|
|
|
|
|
let request = new RequestBuilder(unsubscribeLink.dataset.url);
|
|
|
|
request.withCallback(() => {
|
|
|
|
if (unsubscribeLink.dataset.redirectUrl) {
|
|
|
|
window.location.href = unsubscribeLink.dataset.redirectUrl;
|
|
|
|
} else {
|
|
|
|
window.location.reload();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
request.execute();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} page Page to redirect to.
|
|
|
|
* @param {boolean} fallbackSelf Refresh actual page if the page is not found.
|
|
|
|
*/
|
|
|
|
function goToPage(page, fallbackSelf) {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let element = document.querySelector(":is(a, button)[data-page=" + page + "]");
|
2019-07-18 05:27:39 +02:00
|
|
|
|
|
|
|
if (element) {
|
|
|
|
document.location.href = element.href;
|
|
|
|
} else if (fallbackSelf) {
|
|
|
|
window.location.reload();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function goToPrevious() {
|
|
|
|
if (isListView()) {
|
2022-02-01 04:57:14 +01:00
|
|
|
goToListItem(-1);
|
2019-07-18 05:27:39 +02:00
|
|
|
} else {
|
|
|
|
goToPage("previous");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function goToNext() {
|
|
|
|
if (isListView()) {
|
2022-02-01 04:57:14 +01:00
|
|
|
goToListItem(1);
|
2019-07-18 05:27:39 +02:00
|
|
|
} else {
|
|
|
|
goToPage("next");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function goToFeedOrFeeds() {
|
2020-10-07 03:06:12 +02:00
|
|
|
if (isEntry()) {
|
|
|
|
goToFeed();
|
|
|
|
} else {
|
|
|
|
goToPage('feeds');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function goToFeed() {
|
2019-07-18 05:27:39 +02:00
|
|
|
if (isEntry()) {
|
|
|
|
let feedAnchor = document.querySelector("span.entry-website a");
|
|
|
|
if (feedAnchor !== null) {
|
|
|
|
window.location.href = feedAnchor.href;
|
|
|
|
}
|
|
|
|
} else {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let currentItemFeed = document.querySelector(".current-item :is(a, button)[data-feed-link]");
|
2020-10-07 03:06:12 +02:00
|
|
|
if (currentItemFeed !== null) {
|
|
|
|
window.location.href = currentItemFeed.getAttribute("href");
|
|
|
|
}
|
2019-07-18 05:27:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-01 04:57:14 +01:00
|
|
|
/**
|
|
|
|
* @param {number} offset How many items to jump for focus.
|
|
|
|
*/
|
|
|
|
function goToListItem(offset) {
|
2022-01-29 22:53:10 +01:00
|
|
|
let items = DomHelper.getVisibleElements(".items .item");
|
|
|
|
if (items.length === 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (document.querySelector(".current-item") === null) {
|
|
|
|
items[0].classList.add("current-item");
|
2024-02-08 10:10:59 +01:00
|
|
|
items[0].focus();
|
2022-01-29 22:53:10 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let i = 0; i < items.length; i++) {
|
|
|
|
if (items[i].classList.contains("current-item")) {
|
|
|
|
items[i].classList.remove("current-item");
|
|
|
|
|
2022-02-01 04:57:14 +01:00
|
|
|
let item = items[(i + offset + items.length) % items.length];
|
2022-01-29 22:53:10 +01:00
|
|
|
|
2022-02-01 04:57:14 +01:00
|
|
|
item.classList.add("current-item");
|
|
|
|
DomHelper.scrollPageTo(item);
|
2024-02-08 10:10:59 +01:00
|
|
|
item.focus();
|
2022-01-29 22:53:10 +01:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-17 00:44:03 +02:00
|
|
|
function scrollToCurrentItem() {
|
|
|
|
let currentItem = document.querySelector(".current-item");
|
|
|
|
if (currentItem !== null) {
|
|
|
|
DomHelper.scrollPageTo(currentItem, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 05:27:39 +02:00
|
|
|
function decrementUnreadCounter(n) {
|
|
|
|
updateUnreadCounterValue((current) => {
|
|
|
|
return current - n;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function incrementUnreadCounter(n) {
|
|
|
|
updateUnreadCounterValue((current) => {
|
|
|
|
return current + n;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateUnreadCounterValue(callback) {
|
|
|
|
let counterElements = document.querySelectorAll("span.unread-counter");
|
|
|
|
counterElements.forEach((element) => {
|
|
|
|
let oldValue = parseInt(element.textContent, 10);
|
|
|
|
element.innerHTML = callback(oldValue);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (window.location.href.endsWith('/unread')) {
|
|
|
|
let oldValue = parseInt(document.title.split('(')[1], 10);
|
|
|
|
let newValue = callback(oldValue);
|
|
|
|
|
|
|
|
document.title = document.title.replace(
|
|
|
|
/(.*?)\(\d+\)(.*?)/,
|
|
|
|
function (match, prefix, suffix, offset, string) {
|
|
|
|
return prefix + '(' + newValue + ')' + suffix;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function isEntry() {
|
|
|
|
return document.querySelector("section.entry") !== null;
|
|
|
|
}
|
|
|
|
|
|
|
|
function isListView() {
|
|
|
|
return document.querySelector(".items") !== null;
|
|
|
|
}
|
|
|
|
|
2019-07-26 04:02:39 +02:00
|
|
|
function findEntry(element) {
|
|
|
|
if (isListView()) {
|
|
|
|
if (element) {
|
2024-03-11 04:32:39 +01:00
|
|
|
return element.closest(".item");
|
2019-07-26 04:02:39 +02:00
|
|
|
} else {
|
|
|
|
return document.querySelector(".current-item");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return document.querySelector(".entry");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 06:07:29 +02:00
|
|
|
function handleConfirmationMessage(linkElement, callback) {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
if (linkElement.tagName != 'A' && linkElement.tagName != "BUTTON") {
|
2020-06-15 04:00:41 +02:00
|
|
|
linkElement = linkElement.parentNode;
|
|
|
|
}
|
2019-07-18 06:07:29 +02:00
|
|
|
|
2020-06-15 04:00:41 +02:00
|
|
|
linkElement.style.display = "none";
|
2023-08-01 06:11:39 +02:00
|
|
|
|
2019-07-18 06:07:29 +02:00
|
|
|
let containerElement = linkElement.parentNode;
|
|
|
|
let questionElement = document.createElement("span");
|
|
|
|
|
2023-08-08 16:12:41 +02:00
|
|
|
function createLoadingElement() {
|
2019-07-18 06:07:29 +02:00
|
|
|
let loadingElement = document.createElement("span");
|
|
|
|
loadingElement.className = "loading";
|
|
|
|
loadingElement.appendChild(document.createTextNode(linkElement.dataset.labelLoading));
|
|
|
|
|
|
|
|
questionElement.remove();
|
|
|
|
containerElement.appendChild(loadingElement);
|
2023-08-08 16:12:41 +02:00
|
|
|
}
|
|
|
|
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let yesElement = document.createElement("button");
|
2023-08-08 16:12:41 +02:00
|
|
|
yesElement.appendChild(document.createTextNode(linkElement.dataset.labelYes));
|
|
|
|
yesElement.onclick = (event) => {
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
createLoadingElement();
|
2019-07-18 06:07:29 +02:00
|
|
|
|
|
|
|
callback(linkElement.dataset.url, linkElement.dataset.redirectUrl);
|
|
|
|
};
|
|
|
|
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let noElement = document.createElement("button");
|
2019-07-18 06:07:29 +02:00
|
|
|
noElement.appendChild(document.createTextNode(linkElement.dataset.labelNo));
|
|
|
|
noElement.onclick = (event) => {
|
|
|
|
event.preventDefault();
|
2023-08-08 16:12:41 +02:00
|
|
|
|
|
|
|
const noActionUrl = linkElement.dataset.noActionUrl;
|
|
|
|
if (noActionUrl) {
|
|
|
|
createLoadingElement();
|
|
|
|
|
|
|
|
callback(noActionUrl, linkElement.dataset.redirectUrl);
|
|
|
|
} else {
|
|
|
|
linkElement.style.display = "inline";
|
|
|
|
questionElement.remove();
|
|
|
|
}
|
2019-07-18 06:07:29 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
questionElement.className = "confirm";
|
|
|
|
questionElement.appendChild(document.createTextNode(linkElement.dataset.labelQuestion + " "));
|
|
|
|
questionElement.appendChild(yesElement);
|
|
|
|
questionElement.appendChild(document.createTextNode(", "));
|
|
|
|
questionElement.appendChild(noElement);
|
|
|
|
|
|
|
|
containerElement.appendChild(questionElement);
|
|
|
|
}
|
2019-10-07 05:55:15 +02:00
|
|
|
|
2021-03-07 20:55:43 +01:00
|
|
|
function showToast(label, iconElement) {
|
|
|
|
if (!label || !iconElement) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const toastMsgElement = document.getElementById("toast-msg");
|
|
|
|
if (toastMsgElement) {
|
|
|
|
toastMsgElement.innerHTML = iconElement.innerHTML + '<span class="icon-label">' + label + '</span>';
|
|
|
|
|
|
|
|
const toastElementWrapper = document.getElementById("toast-wrapper");
|
|
|
|
if (toastElementWrapper) {
|
|
|
|
toastElementWrapper.classList.remove('toast-animate');
|
|
|
|
setTimeout(function () {
|
|
|
|
toastElementWrapper.classList.add('toast-animate');
|
|
|
|
}, 100);
|
|
|
|
}
|
|
|
|
}
|
2019-10-07 05:55:15 +02:00
|
|
|
}
|
2022-02-28 03:33:53 +01:00
|
|
|
|
|
|
|
/** Navigate to the new subscription page. */
|
|
|
|
function goToAddSubscription() {
|
|
|
|
window.location.href = document.body.dataset.addSubscriptionUrl;
|
|
|
|
}
|
Add Media Player and resume to last playback position
In order to ease podcast listening, the player can be put on top of the feed entry as main content.
Use the `Use podcast player` option to enable that. It works on audio and video.
Also, when playing audio or video, progression will be saved in order to be able to resume listening later.
This position saving is done using the original attachement/enclosures player AND podcast player and do not rely on
the podcast player option ti be enabled.
Additionally, I made the player fill the width with the entry container to ease seeking and have a bigger video.
updateEnclosures now keep existing enclosures based on URL
When feeds get updated, enclosures entries are always wiped and re-created. This cause two issue
- enclosure progression get lost in the process
- enclosure ID changes
I used the URL as identifier of an enclosure. Not perfect but hopefully should work.
When an enclosure already exist, I simply do nothing and leave the entry as is in the database.
If anyone is listening/watching to this enclosure during the refresh, the id stay coherent and progression saving still works.
The updateEnclosures function got a bit more complex. I tried to make it the more clear I could.
Some optimisation are possible but would make the function harder to read in my opinion.
I'm not sure if this is often the case, but some feeds may include tracking or simply change the url each
time we update the feed. In those situation, enclosures ids and progression will be lost.
I have no idea how to handle this last situation. Use the size instead/alongside url to define the identity of an enclosure ?
Translation: english as placeholder for every language except French
Aside, I tested a video feed and fixed a few things for it. In fact, the MimeType was not working
at all on my side, and found a pretty old stackoverflow discussion that suggest to use an Apple non-standard MimeType for
m4v video format. I only did one substitution because I only have one feed to test. Any new video feed can make this go away
or evolve depending on the situation. Real video feeds does not tend to be easy to find and test extensively this.
Co-authored-by: toastal
2023-04-13 11:46:43 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* save player position to allow to resume playback later
|
|
|
|
* @param {Element} playerElement
|
|
|
|
*/
|
|
|
|
function handlePlayerProgressionSave(playerElement) {
|
|
|
|
const currentPositionInSeconds = Math.floor(playerElement.currentTime); // we do not need a precise value
|
|
|
|
const lastKnownPositionInSeconds = parseInt(playerElement.dataset.lastPosition, 10);
|
|
|
|
const recordInterval = 10;
|
|
|
|
|
|
|
|
// we limit the number of update to only one by interval. Otherwise, we would have multiple update per seconds
|
|
|
|
if (currentPositionInSeconds >= (lastKnownPositionInSeconds + recordInterval) ||
|
|
|
|
currentPositionInSeconds <= (lastKnownPositionInSeconds - recordInterval)
|
|
|
|
) {
|
|
|
|
playerElement.dataset.lastPosition = currentPositionInSeconds.toString();
|
|
|
|
let request = new RequestBuilder(playerElement.dataset.saveUrl);
|
|
|
|
request.withBody({progression: currentPositionInSeconds});
|
|
|
|
request.execute();
|
|
|
|
}
|
|
|
|
}
|
2023-08-01 06:11:39 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* handle new share entires and already shared entries
|
|
|
|
*/
|
|
|
|
function handleShare() {
|
Replace link has button role with button tag
# Change HTML tag to button
Replace the link tag with an HTML button to prevent some screen readers from having confusing announcements. By using the HTML button, users can use the Enter and Space keys to activate actions by default, instead of implementing them in JavaScript.
# Differentiate links and buttons visually
When activating the link element, the user may expect the web page to navigate to the URL and the page will refresh; when activating the button element, the user may expect the web page to still be on the same page, so that their current state, such as: input value, won't disappear.
Links and buttons should have different styles visually, so that users can't expect what will happen when they activate a link or a button.
I added the underline to the links, because that is the common pattern. Buttons have border and background color in a common pattern. But I think that will change the current layout drastically. So I added the focus, hover and active classes to the buttons instead.
2024-02-10 02:09:30 +01:00
|
|
|
let link = document.querySelector(':is(a, button)[data-share-status]');
|
2023-08-01 06:11:39 +02:00
|
|
|
let title = document.querySelector("body > main > section > header > h1 > a");
|
|
|
|
if (link.dataset.shareStatus === "shared") {
|
|
|
|
checkShareAPI(title, link.href);
|
|
|
|
}
|
|
|
|
if (link.dataset.shareStatus === "share") {
|
|
|
|
let request = new RequestBuilder(link.href);
|
|
|
|
request.withCallback((r) => {
|
|
|
|
checkShareAPI(title, r.url);
|
|
|
|
});
|
|
|
|
request.withHttpMethod("GET");
|
|
|
|
request.execute();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* wrapper for Web Share API
|
|
|
|
*/
|
|
|
|
function checkShareAPI(title, url) {
|
|
|
|
if (!navigator.canShare) {
|
|
|
|
console.error("Your browser doesn't support the Web Share API.");
|
|
|
|
window.location = url;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
navigator.share({
|
|
|
|
title: title,
|
|
|
|
url: url
|
|
|
|
});
|
|
|
|
window.location.reload();
|
|
|
|
} catch (err) {
|
|
|
|
console.error(err);
|
|
|
|
window.location.reload();
|
|
|
|
}
|
2023-11-06 18:28:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function getCsrfToken() {
|
|
|
|
let element = document.querySelector("body[data-csrf-token]");
|
|
|
|
if (element !== null) {
|
|
|
|
return element.dataset.csrfToken;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|