aboutsummaryrefslogtreecommitdiffstats
path: root/view
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2024-12-20 19:12:09 +0000
committerMario <mario@mariovavti.com>2024-12-20 19:12:09 +0000
commitb466932e37340e10fedc9b5b33a28db7ad25e4e8 (patch)
treedc6e5f22089377e260c3e5b51485f7a14537f9dc /view
parenta3248e8b3bf253c952e4bbe1f137ca9864192976 (diff)
downloadvolse-hubzilla-b466932e37340e10fedc9b5b33a28db7ad25e4e8.tar.gz
volse-hubzilla-b466932e37340e10fedc9b5b33a28db7ad25e4e8.tar.bz2
volse-hubzilla-b466932e37340e10fedc9b5b33a28db7ad25e4e8.zip
improved imagesLoaded() and formatting
Diffstat (limited to 'view')
-rw-r--r--view/js/main.js353
-rw-r--r--view/tpl/notifications_widget.tpl2
2 files changed, 189 insertions, 166 deletions
diff --git a/view/js/main.js b/view/js/main.js
index 334066a69..e796b29c2 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -628,62 +628,62 @@ function updatePageItems(mode, data) {
}
function updateConvItems(mode, data) {
- let scroll_position = window.scrollY;
- let b64mids = [];
+ let scroll_position = window.scrollY;
+ let b64mids = [];
- // Parse the data string into a DOM object
- let parser = new DOMParser();
- let doc = parser.parseFromString(data, 'text/html');
+ // Parse the data string into a DOM object
+ let parser = new DOMParser();
+ let doc = parser.parseFromString(data, 'text/html');
- if (mode !== 'update') {
- document.dispatchEvent(new Event('hz:updateConvItems'));
- }
+ if (mode !== 'update') {
+ document.dispatchEvent(new Event('hz:updateConvItems'));
+ }
- let prev, next;
- if (mode === 'update' || mode === 'replace') {
- prev = document.getElementById('threads-begin');
- }
- if (mode === 'append') {
- next = document.getElementById('threads-end');
- }
+ let prev, next;
+ if (mode === 'update' || mode === 'replace') {
+ prev = document.getElementById('threads-begin');
+ }
+ if (mode === 'append') {
+ next = document.getElementById('threads-end');
+ }
- doc.querySelectorAll('.thread-wrapper').forEach(function (elem) {
- if (elem.classList.contains('toplevel_item')) {
- let ident = elem.id;
- let convId = ident.replace('thread-wrapper-', '');
- let commentWrap = elem.querySelector('.collapsed-comments')?.id;
+ doc.querySelectorAll('.thread-wrapper').forEach(function (elem) {
+ if (elem.classList.contains('toplevel_item')) {
+ let ident = elem.id;
+ let convId = ident.replace('thread-wrapper-', '');
+ let commentWrap = elem.querySelector('.collapsed-comments')?.id;
- let itmId = 0;
- let isVisible = false;
+ let itmId = 0;
+ let isVisible = false;
- // figure out the comment state
- if (commentWrap !== undefined) {
- itmId = commentWrap.replace('collapsed-comments-', '');
- }
+ // figure out the comment state
+ if (commentWrap !== undefined) {
+ itmId = commentWrap.replace('collapsed-comments-', '');
+ }
- let collapsedComment = document.getElementById('collapsed-comments-' + itmId);
- if (collapsedComment && collapsedComment.style.display !== 'none') {
- isVisible = true;
- }
+ let collapsedComment = document.getElementById('collapsed-comments-' + itmId);
+ if (collapsedComment && collapsedComment.style.display !== 'none') {
+ isVisible = true;
+ }
- // insert the content according to the mode and first_page
- // and whether or not the content exists already (overwrite it)
- let existingElem = document.getElementById(ident);
- if (!existingElem) {
- if ((mode === 'update' || mode === 'replace') && profile_page == 1) {
- if (prev) {
- prev.after(elem);
- prev = elem;
- }
- }
- if (mode === 'append') {
- if (next) {
- next.before(elem);
- }
- }
- } else {
- existingElem.replaceWith(elem);
- }
+ // insert the content according to the mode and first_page
+ // and whether or not the content exists already (overwrite it)
+ let existingElem = document.getElementById(ident);
+ if (!existingElem) {
+ if ((mode === 'update' || mode === 'replace') && profile_page == 1) {
+ if (prev) {
+ prev.after(elem);
+ prev = elem;
+ }
+ }
+ if (mode === 'append') {
+ if (next) {
+ next.before(elem);
+ }
+ }
+ } else {
+ existingElem.replaceWith(elem);
+ }
// DOMParser will prevent scripts from execution for security reasons.
// We remove all scripts but possibly injected some from
@@ -695,155 +695,178 @@ function updateConvItems(mode, data) {
eval(scriptContent); // Execute the script
});
- // set the comment state to the state we discovered earlier
- if (isVisible) {
- showHideComments(itmId);
- }
+ // set the comment state to the state we discovered earlier
+ if (isVisible) {
+ showHideComments(itmId);
+ }
- let commentBody = localStorage.getItem("comment_body-" + convId);
- if (commentBody) {
- let commentElm = document.getElementById('comment-edit-text-' + convId);
- if (auto_save_draft && commentElm) {
- if (commentElm.value === '') {
- let commentForm = document.getElementById('comment-edit-form-' + convId);
- if (commentForm) {
- commentForm.style.display = 'block';
- }
- commentElm.classList.add("expanded");
- openMenu("comment-tools-" + convId);
- commentElm.value = commentBody;
- }
- } else {
- localStorage.removeItem("comment_body-" + convId);
- }
- }
+ let commentBody = localStorage.getItem("comment_body-" + convId);
+ if (commentBody) {
+ let commentElm = document.getElementById('comment-edit-text-' + convId);
+ if (auto_save_draft && commentElm) {
+ if (commentElm.value === '') {
+ let commentForm = document.getElementById('comment-edit-form-' + convId);
+ if (commentForm) {
+ commentForm.style.display = 'block';
+ }
+ commentElm.classList.add("expanded");
+ openMenu("comment-tools-" + convId);
+ commentElm.value = commentBody;
+ }
+ } else {
+ localStorage.removeItem("comment_body-" + convId);
+ }
+ }
- if ((mode === 'append' || mode === 'replace') && loadingPage) {
- loadingPage = false;
- }
+ if ((mode === 'append' || mode === 'replace') && loadingPage) {
+ loadingPage = false;
+ }
- // if single thread view and the item has a title, display it in the title bar
- if (mode === 'replace') {
- if (window.location.search.includes("mid=") || window.location.pathname.includes("display")) {
- let titleElem = document.querySelector(".wall-item-title");
- if (titleElem) {
- let title = titleElem.textContent.trim();
- if (title) {
- savedTitle = title + ' ' + savedTitle;
- document.title = title;
- }
- }
- }
- }
- }
+ // if single thread view and the item has a title, display it in the title bar
+ if (mode === 'replace') {
+ if (window.location.search.includes("mid=") || window.location.pathname.includes("display")) {
+ let titleElem = document.querySelector(".wall-item-title");
+ if (titleElem) {
+ let title = titleElem.textContent.trim();
+ if (title) {
+ savedTitle = title + ' ' + savedTitle;
+ document.title = title;
+ }
+ }
+ }
+ }
+ }
- b64mids.push(...JSON.parse(elem.dataset.b64mids));
- });
+ b64mids.push(...JSON.parse(elem.dataset.b64mids));
+ });
document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids }));
- window.scrollTo(0, scroll_position);
+ window.scrollTo(0, scroll_position);
- if (followUpPageLoad) {
- document.dispatchEvent(new Event('hz:sse_bs_counts'));
- } else {
- document.dispatchEvent(new Event('hz:sse_bs_init'));
- }
+ if (followUpPageLoad) {
+ document.dispatchEvent(new Event('hz:sse_bs_counts'));
+ } else {
+ document.dispatchEvent(new Event('hz:sse_bs_init'));
+ }
- if (commentBusy) {
- commentBusy = false;
- document.body.style.cursor = 'auto';
- }
+ if (commentBusy) {
+ commentBusy = false;
+ document.body.style.cursor = 'auto';
+ }
- // Setup to determine if the media player is playing. This affects some content loading decisions.
- ['playing', 'pause'].forEach(event => {
- document.querySelectorAll('video, audio').forEach(media => {
- media.removeEventListener(event, mediaHandler);
- media.addEventListener(event, mediaHandler);
- });
- });
+ // Setup to determine if the media player is playing. This affects some content loading decisions.
+ ['playing', 'pause'].forEach(event => {
+ document.querySelectorAll('video, audio').forEach(media => {
+ media.removeEventListener(event, mediaHandler);
+ media.addEventListener(event, mediaHandler);
+ });
+ });
- function mediaHandler(event) {
- mediaPlaying = event.type === 'playing';
- }
+ function mediaHandler(event) {
+ mediaPlaying = event.type === 'playing';
+ }
- imagesLoaded(document.querySelectorAll('.wall-item-body img, .wall-photo-item img'), function () {
- collapseHeight();
- if (bParam_mid && mode === 'replace') {
- scrollToItem();
- }
- });
+ imagesLoaded(document.querySelectorAll('.wall-item-body img, .wall-photo-item img'), function () {
+ collapseHeight();
+ if (bParam_mid && mode === 'replace') {
+ scrollToItem();
+ }
+ });
- // reset rotators and cursors we may have set before reaching this place
- let pageSpinner = document.getElementById("page-spinner");
- if (pageSpinner) {
- pageSpinner.style.display = 'none';
- }
- let profileJotTextLoading = document.getElementById("profile-jot-text-loading");
- if (profileJotTextLoading) {
- profileJotTextLoading.style.display = 'none';
- }
+ // reset rotators and cursors we may have set before reaching this place
+ let pageSpinner = document.getElementById("page-spinner");
+ if (pageSpinner) {
+ pageSpinner.style.display = 'none';
+ }
+ let profileJotTextLoading = document.getElementById("profile-jot-text-loading");
+ if (profileJotTextLoading) {
+ profileJotTextLoading.style.display = 'none';
+ }
- followUpPageLoad = true;
+ followUpPageLoad = true;
- updateRelativeTime('.autotime');
+ updateRelativeTime('.autotime');
}
-// Helper function for images loaded
function imagesLoaded(elements, callback) {
- let loaded = 0;
- let count = 0;
+ let loadedCount = 0;
+ let totalImages = 0;
+ let timeoutId;
+ let timeout = 10000;
- // Helper function to extract img elements from an HTML string
- function extractImagesFromHtml(htmlString) {
+ // Helper function to extract img elements from an HTML string
+ function extractImagesFromHtml(htmlString) {
let tempDiv = document.createElement('div');
tempDiv.innerHTML = htmlString;
return tempDiv.querySelectorAll('.wall-item-body img, .wall-photo-item img');
- }
+ }
- // If the elements is an HTML string, convert it to img elements
- if (typeof elements === 'string') {
- elements = extractImagesFromHtml(elements);
- }
+ function checkComplete() {
+ document.getElementById('image_counter').innerHTML = Math.round((loadedCount * 100) / totalImages) + '%';
+ if (loadedCount === totalImages) {
+ clearTimeout(timeoutId);
+ callback();
+ document.getElementById('image_counter').innerHTML = '';
+ }
+ }
- // If elements is not a valid array-like object, or is empty, exit early
- if (!elements || elements.length === 0) {
- callback(); // No images to load, immediately call the callback
- return;
- }
+ // If the elements is an HTML string, convert it to img elements
+ if (typeof elements === 'string') {
+ elements = extractImagesFromHtml(elements);
+ }
- // Filter out only img elements from the list
- const images = Array.from(elements).filter(element => {
- return element.tagName && element.tagName.toLowerCase() === 'img' && element.src;
- });
+ // If elements is not a valid array-like object, or is empty, exit early
+ if (!elements || elements.length === 0) {
+ callback(); // No images to load, immediately call the callback
+ return;
+ }
- // If no images are found, call the callback immediately
- if (images.length === 0) {
- callback();
- return;
- }
+ // Filter out only img elements from the list
+ let images = Array.from(elements).filter(element => {
+ return element.tagName && element.tagName.toLowerCase() === 'img' && element.src;
+ });
- count = images.length;
+ // If no images are found, call the callback immediately
+ if (images.length === 0) {
+ callback();
+ return;
+ }
- // Process each image element
- images.forEach(element => {
- let img = new Image();
+ // Set timeout
+ timeoutId = setTimeout(() => {
+ console.warn(`Image loading timed out after ${timeout}ms`);
+ callback(false);
+ }, timeout);
- // Handle both loading and error events
- img.onload = img.onerror = function () {
- loaded++;
- document.getElementById('image_counter').innerHTML = Math.round((loaded * 100) / count) + '%';
- if (loaded === count) {
- callback();
- document.getElementById('image_counter').innerHTML = '';
- }
- };
+ totalImages = images.length;
- // Set the source to the image's src attribute
- img.src = element.src;
- });
+ images.forEach((img) => {
+
+ img.loading = 'eager'; // Otherwise it will not load until visible
+ if (img.complete && img.naturalHeight !== 0) {
+ // Image is already loaded successfully
+ loadedCount++;
+ //console.log(`Image cached: ${img.src}`);
+ checkComplete();
+ } else {
+ // Add event listeners for load and error events
+ img.addEventListener('load', () => {
+ //console.log(`Image loaded: ${img.src}`);
+ loadedCount++;
+ checkComplete();
+ });
+
+ img.addEventListener('error', () => {
+ console.log(`Image failed to load: ${img.src}`);
+ loadedCount++;
+ checkComplete();
+ });
+ }
+ });
}
+
function updateRelativeTime(selector) {
// Get all elements with the given selector
const timeElements = document.querySelectorAll(selector);
diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl
index 16362691f..3347378b5 100644
--- a/view/tpl/notifications_widget.tpl
+++ b/view/tpl/notifications_widget.tpl
@@ -466,7 +466,7 @@
updateElement.textContent = count >= 100 ? '99+' : count;
}
} else {
- updateElement.textContent = '0';
+ if (updateElement) updateElement.textContent = '0';
if (subElement) subElement.classList.remove('show');
if (buttonElement) {
buttonElement.style.display = 'none'; // Fade-out effect replaced by display none