aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--boot.php2
-rw-r--r--view/js/main.js91
-rw-r--r--view/php/theme_init.php1
-rw-r--r--view/tpl/notifications_widget.tpl193
4 files changed, 144 insertions, 143 deletions
diff --git a/boot.php b/boot.php
index d0bdf24ba..45bdba95c 100644
--- a/boot.php
+++ b/boot.php
@@ -66,7 +66,7 @@ require_once('include/security.php');
define('PLATFORM_NAME', 'hubzilla');
-define('STD_VERSION', '10.1.2');
+define('STD_VERSION', '10.1.3');
define('ZOT_REVISION', '6.0');
define('DB_UPDATE_VERSION', 1263);
diff --git a/view/js/main.js b/view/js/main.js
index 658dd8b6f..d95e9f659 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -767,19 +767,12 @@ function updateConvItems(mode, data) {
mediaPlaying = event.type === 'playing';
}
- if (!preloadImages) {
- imagesLoaded(document.querySelectorAll('.wall-item-body, .wall-photo-item'), function () {
- collapseHeight();
- if (bParam_mid && mode === 'replace') {
- scrollToItem();
- }
- });
- } else {
+ 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");
@@ -799,16 +792,54 @@ function updateConvItems(mode, data) {
// Helper function for images loaded
function imagesLoaded(elements, callback) {
let loaded = 0;
- let count = elements.length;
+ let count = 0;
+
+ // Helper function to extract img elements from an HTML string
+ function extractImagesFromHtml(htmlString) {
+ const tempDiv = document.createElement('div');
+ tempDiv.innerHTML = htmlString;
+ return Array.from(tempDiv.getElementsByTagName('img'));
+ }
+
+ // If the elements is an HTML string, convert it to img elements
+ if (typeof elements === 'string') {
+ elements = extractImagesFromHtml(elements);
+ }
+
+ // 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;
+ }
- elements.forEach(element => {
+ // 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 no images are found, call the callback immediately
+ if (images.length === 0) {
+ callback();
+ return;
+ }
+
+ count = images.length;
+
+ // Process each image element
+ images.forEach(element => {
let img = new Image();
+
+ // 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();
}
};
+
+ // Set the source to the image's src attribute
img.src = element.src;
});
}
@@ -1076,10 +1107,7 @@ function liveUpdate(notify_id) {
if(update_mode === 'update' || preloadImages) {
console.log('LOADING images...');
- $('.wall-item-body, .wall-photo-item',data).imagesLoaded()
- .always( function( instance ) {
- //console.log('all images loaded');
-
+ imagesLoaded(data, function () {
var iready = new Date();
console.log('IMAGES ready in: ' + (iready - dready)/1000 + ' seconds.');
@@ -1088,23 +1116,7 @@ function liveUpdate(notify_id) {
updateConvItems(update_mode,data);
in_progress = false;
- $('#image_counter').html('');
-
- // remove modal backdrop in case the update was triggered from a modal
- $('.modal-backdrop').remove();
- })
- .done( function( instance ) {
- //console.log('all images successfully loaded');
- })
- .fail( function() {
- //console.log('all images loaded, at least one is broken');
- })
- .progress( function( instance, image ) {
- $('#image_counter').html(Math.floor((instance.progressedCount*100)/instance.images.length) + '%');
- //var result = image.isLoaded ? 'loaded' : 'broken';
- //console.log( 'image is ' + result + ' for ' + image.img.src );
});
-
}
else {
page_load = false;
@@ -1146,9 +1158,8 @@ function cache_next_page() {
console.log('cached: ' + update_url);
- $('.wall-item-body, .wall-photo-item', data).imagesLoaded()
- .always( function( instance ) {
- console.log('page_cache images loaded:');
+ imagesLoaded(data, function () {
+ console.log('page_cache: images loaded');
page_cache.data = data;
page_cache.page = bParam_page;
@@ -1156,19 +1167,7 @@ function cache_next_page() {
bParam_page--;
page_load = false;
- })
- .done( function( instance ) {
- console.log('success');
- })
- .fail( function() {
- console.log('at least one is broken');
- })
- .progress( function( instance, image ) {
- //console.log(instance.progressedCount + '/' + instance.images.length);
- //var result = image.isLoaded ? 'loaded' : 'broken';
- //console.log( 'image is ' + result + ' for ' + image.img.src );
});
-
});
}
diff --git a/view/php/theme_init.php b/view/php/theme_init.php
index abe4851af..e6bd09224 100644
--- a/view/php/theme_init.php
+++ b/view/php/theme_init.php
@@ -34,7 +34,6 @@ head_add_js('/library/colorbox/jquery.colorbox-min.js');
head_add_js('/library/jquery.AreYouSure/jquery.are-you-sure.js');
head_add_js('/library/tableofcontents/jquery.toc.js');
head_add_js('/library/Sortable/Sortable.min.js');
-head_add_js('/vendor/desandro/imagesloaded/imagesloaded.pkgd.min.js');
/**
* Those who require this feature will know what to do with it.
diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl
index cdef36eb3..f42ff21dc 100644
--- a/view/tpl/notifications_widget.tpl
+++ b/view/tpl/notifications_widget.tpl
@@ -183,122 +183,125 @@
});
});
- });
-
- document.addEventListener('hz:sse_setNotificationsStatus', function(e) {
- sse_setNotificationsStatus(e.detail);
- });
-
- document.addEventListener('hz:sse_bs_init', function() {
- sse_bs_init();
- });
-
- document.addEventListener('hz:sse_bs_counts', function() {
- sse_bs_counts();
- });
+ {{foreach $notifications as $notification}}
+ {{if $notification.filter}}
+ document.querySelectorAll('#tt-{{$notification.type}}-only').forEach(function (element) {
+ element.addEventListener('click', function(e) {
- {{foreach $notifications as $notification}}
- {{if $notification.filter}}
- document.addEventListener('click', function(e) {
- if (e.target.closest('div').matches('#tt-{{$notification.type}}-only')) {
- let element = e.target.closest('div');
- let menu = document.querySelector('#nav-{{$notification.type}}-menu');
- let notifications = menu.querySelectorAll('.notification[data-thread_top="false"]');
+ let element = e.target.closest('div');
+ let menu = document.querySelector('#nav-{{$notification.type}}-menu');
+ let notifications = menu.querySelectorAll('.notification[data-thread_top="false"]');
- // Function to check if an element is visible
- function isVisible(el) {
- return el.offsetWidth > 0 && el.offsetHeight > 0;
- }
+ // Function to check if an element is visible
+ function isVisible(el) {
+ return el.offsetWidth > 0 && el.offsetHeight > 0;
+ }
- if (element.classList.contains('active') && element.classList.contains('sticky-top')) {
- notifications.forEach(function(notification) {
- notification.classList.remove('tt-filter-active');
- });
- element.classList.remove('active', 'sticky-top');
- } else {
- notifications.forEach(function(notification) {
- notification.classList.add('tt-filter-active');
- });
- element.classList.add('active', 'sticky-top');
+ if (element.classList.contains('active') && element.classList.contains('sticky-top')) {
+ notifications.forEach(function(notification) {
+ notification.classList.remove('tt-filter-active');
+ });
+ element.classList.remove('active', 'sticky-top');
+ } else {
+ notifications.forEach(function(notification) {
+ notification.classList.add('tt-filter-active');
+ });
+ element.classList.add('active', 'sticky-top');
- // Count the visible notifications
- let visibleNotifications = Array.from(menu.querySelectorAll('.notification')).filter(isVisible).length;
+ // Count the visible notifications
+ let visibleNotifications = Array.from(menu.querySelectorAll('.notification')).filter(isVisible).length;
- // Load more notifications if the visible count is low
- if (sse_type && sse_offset !== -1 && visibleNotifications < 15) {
- sse_bs_notifications(sse_type, false, true);
+ // Load more notifications if the visible count is low
+ if (sse_type && sse_offset !== -1 && visibleNotifications < 15) {
+ sse_bs_notifications(sse_type, false, true);
+ }
}
- }
- }
-
- if (e.target.closest('div').matches('#cn-{{$notification.type}}-input-clear')) {
- // Clear the input value
- let input = document.querySelector('#cn-{{$notification.type}}-input');
- input.value = '';
-
- // Remove the 'active' and 'sticky-top' classes from the clear button
- let clearButton = e.target;
- clearButton.classList.remove('active', 'sticky-top');
- // Remove the 'cn-filter-active' class from all notifications
- let notifications = document.querySelectorAll("#nav-{{$notification.type}}-menu .notification");
- notifications.forEach(function(notification) {
- notification.classList.remove('cn-filter-active');
});
+ });
- // Add the 'd-none' class to hide the clear button
- clearButton.classList.add('d-none');
- }
-
- });
-
- document.addEventListener('input', function(e) {
- // Check if the input element matches the selector
- if (e.target.matches('#cn-{{$notification.type}}-input')) {
- let input = e.target;
- let val = input.value.toString().toLowerCase();
-
- // Check if there is input value
- if (val) {
- // Remove '%' if it's at the beginning of the input value
- val = val.indexOf('%') === 0 ? val.substring(1) : val;
-
- // Add 'active' and 'sticky-top' classes to the 'only' element
- let onlyElement = document.getElementById('cn-{{$notification.type}}-only');
- onlyElement.classList.add('active', 'sticky-top');
+ document.querySelectorAll('#cn-{{$notification.type}}-input-clear').forEach(function (element) {
+ element.addEventListener('click', function(e) {
+ let input = document.getElementById('cn-{{$notification.type}}-input');
+ input.value = '';
- // Remove 'd-none' class from the clear button
- let clearButton = document.getElementById('cn-{{$notification.type}}-input-clear');
- clearButton.classList.remove('d-none');
- } else {
- // Remove 'active' and 'sticky-top' classes from the 'only' element
+ // Remove 'active' and 'sticky-top' classes to the 'only' element
let onlyElement = document.getElementById('cn-{{$notification.type}}-only');
onlyElement.classList.remove('active', 'sticky-top');
- // Add 'd-none' class to the clear button
+ // Add 'd-none' class from the clear button
let clearButton = document.getElementById('cn-{{$notification.type}}-input-clear');
clearButton.classList.add('d-none');
- }
- // Loop through each notification and apply filter logic
- let notifications = document.querySelectorAll("#nav-{{$notification.type}}-menu .notification");
- notifications.forEach(function(el) {
- let cn = el.dataset.contact_name.toString().toLowerCase();
- let ca = el.dataset.contact_addr.toString().toLowerCase();
+ // Remove the 'cn-filter-active' class from all notifications
+ let notifications = document.querySelectorAll("#nav-{{$notification.type}}-menu .notification");
+ notifications.forEach(function(notification) {
+ notification.classList.remove('cn-filter-active');
+ });
+ });
+ });
+
+ document.querySelectorAll('#cn-{{$notification.type}}-input').forEach(function (element) {
+ element.addEventListener('input', function(e) {
+ let input = e.target;
+ let val = input.value.toString().toLowerCase();
+
+ // Check if there is input value
+ if (val) {
+ // Remove '%' if it's at the beginning of the input value
+ val = val.indexOf('%') === 0 ? val.substring(1) : val;
- // Check if the contact name or address matches the input value
- if (cn.indexOf(val) === -1 && ca.indexOf(val) === -1) {
- el.classList.add('cn-filter-active');
+ // Add 'active' and 'sticky-top' classes to the 'only' element
+ let onlyElement = document.getElementById('cn-{{$notification.type}}-only');
+ onlyElement.classList.add('active', 'sticky-top');
+
+ // Remove 'd-none' class from the clear button
+ let clearButton = document.getElementById('cn-{{$notification.type}}-input-clear');
+ clearButton.classList.remove('d-none');
} else {
- el.classList.remove('cn-filter-active');
+ // Remove 'active' and 'sticky-top' classes from the 'only' element
+ let onlyElement = document.getElementById('cn-{{$notification.type}}-only');
+ onlyElement.classList.remove('active', 'sticky-top');
+
+ // Add 'd-none' class to the clear button
+ let clearButton = document.getElementById('cn-{{$notification.type}}-input-clear');
+ clearButton.classList.add('d-none');
}
+
+ // Loop through each notification and apply filter logic
+ let notifications = document.querySelectorAll("#nav-{{$notification.type}}-menu .notification");
+ notifications.forEach(function(el) {
+ let cn = el.dataset.contact_name.toString().toLowerCase();
+ let ca = el.dataset.contact_addr.toString().toLowerCase();
+
+ // Check if the contact name or address matches the input value
+ if (cn.indexOf(val) === -1 && ca.indexOf(val) === -1) {
+ el.classList.add('cn-filter-active');
+ } else {
+ el.classList.remove('cn-filter-active');
+ }
+ });
});
- }
+ });
+
+ {{/if}}
+ {{/foreach}}
+
+ });
+
+ document.addEventListener('hz:sse_setNotificationsStatus', function(e) {
+ sse_setNotificationsStatus(e.detail);
+ });
+
+ document.addEventListener('hz:sse_bs_init', function() {
+ sse_bs_init();
+ });
+
+ document.addEventListener('hz:sse_bs_counts', function() {
+ sse_bs_counts();
});
- {{/if}}
- {{/foreach}}
function sse_bs_init() {
// Check if 'notification_open' exists in sessionStorage or if sse_type is defined
@@ -557,8 +560,8 @@
if (filter.indexOf('%') === 0) filter = filter.substring(1); // Remove the percent if it exists
let notifications = notify_menu.querySelectorAll('.notification');
notifications.forEach(notification => {
- let cn = notification.dataset.contactName.toString().toLowerCase();
- let ca = notification.dataset.contactAddr.toString().toLowerCase();
+ let cn = notification.dataset.contact_name.toString().toLowerCase();
+ let ca = notification.dataset.contact_addr.toString().toLowerCase();
if (cn.indexOf(filter) === -1 && ca.indexOf(filter) === -1) {
notification.classList.add('cn-filter-active');
} else {