aboutsummaryrefslogtreecommitdiffstats
path: root/view/js/main.js
diff options
context:
space:
mode:
Diffstat (limited to 'view/js/main.js')
-rw-r--r--view/js/main.js757
1 files changed, 371 insertions, 386 deletions
diff --git a/view/js/main.js b/view/js/main.js
index 6fda3c8d0..ce1d71596 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -25,6 +25,7 @@ var savedTitle = '';
var followUpPageLoad = false;
var window_needs_alert = true;
var expanded_items = [];
+var updateTimeout = [];
var page_cache = {};
@@ -58,42 +59,18 @@ $.ajaxSetup({cache: false});
var tf = new Function('n', 's', 'var k = s.split("/")['+aStr['plural_func']+']; return (k ? k : s);');
-jQuery.timeago.settings.strings = {
- prefixAgo : aStr['t01'],
- prefixFromNow : aStr['t02'],
- suffixAgo : aStr['t03'],
- suffixFromNow : aStr['t04'],
- seconds : aStr['t05'],
- minute : aStr['t06'],
- minutes : function(value){return tf(value, aStr['t07']);},
- hour : aStr['t08'],
- hours : function(value){return tf(value, aStr['t09']);},
- day : aStr['t10'],
- days : function(value){return tf(value, aStr['t11']);},
- month : aStr['t12'],
- months : function(value){return tf(value, aStr['t13']);},
- year : aStr['t14'],
- years : function(value){return tf(value, aStr['t15']);},
- wordSeparator : aStr['t16'],
- numbers : aStr['t17'],
-};
-
-jQuery.timeago.settings.allowFuture = true;
-
$(document).ready(function() {
$(document).on('click focus', '.comment-edit-form', handle_comment_form);
$(document).on('click', '.conversation-settings-link', getConversationSettings);
$(document).on('click', '#settings_module_ajax_submit', postConversationSettings);
- $(document).on('click', '#expand-aside', function() {
- toggleAside();
- });
+ $(document).on('click', '#expand-aside', toggleAside);
$(document).on('click focus', '.comment-edit-form textarea', function(e) {
if(! this.autocomplete_handled) {
/* autocomplete @nicknames */
- $(this).editor_autocomplete(baseurl+"/acl?f=&n=1");
+ $(this).editor_autocomplete(baseurl+"/acl?n=1");
/* autocomplete bbcode */
$(this).bbco_autocomplete('bbcode');
@@ -114,7 +91,7 @@ $(document).ready(function() {
}
if ( typeof(window.tao.zin) == 'undefined' ) {
tao.zin = { syslc: '', syslcs: {}, htm: '', me: '', debug: '' };
- tao.zin.axim = '<div class="zinpax fa fa-sync fa-spin"> </div>';
+ tao.zin.axim = '<i class="zinpax bi bi-arrow-repeat"></i>';
$('.navbar-app[href*="/lang"]').attr({"aria-expand": "true", "id": "zintog"})
.removeAttr('href').addClass('zinlcx zinlcxp dropdown dropdown-toggle').css('cursor','pointer');
$('.nav-link[href*="/lang"]').addClass('zinlcxmi zinlcx').removeAttr('href').css('cursor','pointer');
@@ -129,9 +106,9 @@ $(document).ready(function() {
tao.zin.re = JSON.parse(re);
tao.zin.syslc = tao.zin.re.lc;
tao.zin.syslcs = tao.zin.re.lcs;
- tao.zin.htm = '<ul class="zinlcs fa-ul">';
+ tao.zin.htm = '<ul class="zinlcs">';
$.each( tao.zin.syslcs, function( k, v ) {
- tao.zin.htm += '<li><a id="zinlc' + k + '" class="zinlc nav-link fakelink">' + k + ' ' + v + '</a></li>';
+ tao.zin.htm += '<li><a id="zinlc' + k + '" class="zinlc fakelink">' + k + ' ' + v + '</a></li>';
});
tao.zin.htm += '</ul>';
$('.zinpax').remove();
@@ -175,14 +152,19 @@ $(document).ready(function() {
let singlethread_modules = ['display', 'hq'];
let redirect_modules = ['display', 'notify'];
- if(! b64mid && ! notify_id)
+ if (!b64mid && !notify_id) {
return;
+ }
- if(localUser && redirect_modules.indexOf(path) !== -1) {
+ if (document.querySelector('main').classList.contains('region_1-on')) {
+ toggleAside();
+ }
+
+ if (localUser && redirect_modules.indexOf(path) !== -1) {
path = 'hq';
}
- if(notify_id) {
+ if (notify_id) {
$.ajax({
type: 'post',
url: 'notify',
@@ -198,21 +180,17 @@ $(document).ready(function() {
window.location.href = path + '/' + b64mid;
}
else {
-
if (singlethread_modules.indexOf(module) !== -1) {
history.pushState(stateObj, '', module + '/' + b64mid);
-
}
if (b64mid) {
-
e.preventDefault();
-
- if(! page_load) {
+ if (!page_load) {
prepareLiveUpdate(b64mid, notify_id);
$('.message').removeClass('active');
$('[data-b64mid="' + b64mid + '"].message').addClass('active');
- $('[data-b64mid="' + b64mid + '"].message .badge').remove();
+ $('[data-b64mid="' + b64mid + '"].message .unseen_count').remove();
}
}
}
@@ -231,44 +209,44 @@ $(document).ready(function() {
updateInit();
- var e = document.getElementById('content-complete');
- if(e)
+ if (document.getElementById('content-complete')) {
pageHasMoreContent = false;
+ }
- $(document).on('hz:updateConvItems', function(event) {
- if(!bParam_mid)
+ document.addEventListener('hz:updateConvItems', function(e) {
+ if (!bParam_mid) {
cache_next_page();
+ }
});
- $(document).on('hz:handleNetworkNotificationsItems', function(e, obj) {
+ document.addEventListener('hz:handleNetworkNotificationsItems', function(e) {
push_notification(
- obj.name,
- $('<p>' + obj.message + '</p>').text(),
- obj.b64mid
+ e.detail.name,
+ $('<p>' + e.detail.message + '</p>').text(),
+ e.detail.b64mid
);
});
});
function getConversationSettings() {
- $.get('settings/conversation/?f=&aj=1',function(data) {
+ $.get('settings/conversation/?aj=1',function(data) {
$('#conversation_settings_body').html(data);
});
}
function postConversationSettings() {
- $.post(
- 'settings/conversation',
- $('#settings_module_ajax_form').serialize() + "&auto_update=" + next_page
- );
-
if(next_page === 1) {
page_load = true;
}
- $('#conversation_settings').modal('hide');
-
- if(timer) clearTimeout(timer);
- timer = setTimeout(updateInit,100);
+ $.post(
+ 'settings/conversation',
+ $('#settings_module_ajax_form').serialize() + "&auto_update=" + next_page
+ ).done(function() {
+ $('#conversation_settings').modal('hide');
+ toast('Conversation features updated', 'info');
+ updateInit();
+ });
return false;
}
@@ -486,7 +464,7 @@ function insertCommentURL(comment, id) {
if(reply && reply.length) {
reply = bin2hex(reply);
$('body').css('cursor', 'wait');
- $.get('linkinfo?f=&binurl=' + reply, function(data) {
+ $.get('linkinfo?binurl=' + reply, function(data) {
var tmpStr = $("#comment-edit-text-" + id).val();
if(tmpStr == comment) {
tmpStr = "";
@@ -515,16 +493,17 @@ function viewsrc(id) {
}
function showHideComments(id) {
- if( $('#collapsed-comments-' + id).is(':visible')) {
- $('#collapsed-comments-' + id + ' .autotime').timeago('dispose');
+ if($('#collapsed-comments-' + id).is(':visible')) {
$('#collapsed-comments-' + id).hide();
- $('#hide-comments-' + id).html(aStr.showmore);
+ $('#hide-comments-label-' + id).html(aStr.showmore);
$('#hide-comments-total-' + id).show();
+ $('#hide-comments-icon-' + id).toggleClass('bi-chevron-down bi-chevron-up');
+
} else {
- $('#collapsed-comments-' + id + ' .autotime').timeago();
$('#collapsed-comments-' + id).show();
- $('#hide-comments-' + id).html(aStr.showfewer);
+ $('#hide-comments-label-' + id).html(aStr.showfewer);
$('#hide-comments-total-' + id).hide();
+ $('#hide-comments-icon-' + id).toggleClass('bi-chevron-down bi-chevron-up');
}
}
@@ -566,7 +545,7 @@ function closeMenu(theID) {
}
function markRead(notifType) {
- $.get('notifications?f=&markRead='+notifType);
+ $.get('notifications?markRead='+notifType);
$('.' + notifType + '-button').fadeOut(function() {
$("." + notifType + "-update").html('0');
$('#nav-' + notifType + '-menu').html('');
@@ -579,7 +558,7 @@ function markRead(notifType) {
}
function markItemRead(itemId) {
- $.get('notifications?f=&markItemRead='+itemId);
+ $.get('notifications?markItemRead='+itemId);
$('.unseen-wall-indicator-'+itemId).remove();
}
@@ -648,201 +627,342 @@ function updatePageItems(mode, data) {
collapseHeight();
}
-
-function updateConvItems(mode,data) {
- let scroll_position = $(window).scrollTop();
+function updateConvItems(mode, data) {
+ let scroll_position = window.scrollY;
let b64mids = [];
- if(mode !== 'update')
- $(document).trigger('hz:updateConvItems');
+ // Parse the data string into a DOM object
+ let parser = new DOMParser();
+ let doc = parser.parseFromString(data, 'text/html');
- if(mode === 'update' || mode === 'replace') {
- prev = 'threads-begin';
+ if (mode !== 'update') {
+ document.dispatchEvent(new Event('hz:updateConvItems'));
}
- if(mode === 'append') {
- next = 'threads-end';
+
+ let prev, next;
+ if (mode === 'update' || mode === 'replace') {
+ prev = document.getElementById('threads-begin');
+ }
+ if (mode === 'append') {
+ next = document.getElementById('threads-end');
}
- $('.thread-wrapper', data).each(function() {
- if(this.classList.contains('toplevel_item')) {
- let ident = this.id;
- let convId = ident.replace('thread-wrapper-','');
- let commentWrap = $('#'+ident+' .collapsed-comments').attr('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;
// figure out the comment state
- if(typeof commentWrap !== 'undefined')
- itmId = commentWrap.replace('collapsed-comments-','');
+ if (commentWrap !== undefined) {
+ itmId = commentWrap.replace('collapsed-comments-', '');
+ }
- if($('#collapsed-comments-'+itmId).is(':visible'))
+ 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)
-
- if($('#' + ident).length == 0) {
- if((mode === 'update' || mode === 'replace') && profile_page == 1) {
- $('#' + prev).after($(this));
- prev = ident;
+ 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') {
- $('#' + next).before($(this));
+ if (mode === 'append') {
+ if (next) {
+ next.before(elem);
+ }
}
- }
- else {
- $('#' + ident).replaceWith($(this));
+ } else {
+ existingElem.replaceWith(elem);
}
- // set the comment state to the state we discovered earlier
+ // DOMParser will prevent scripts from execution for security reasons.
+ // We remove all scripts but possibly injected some from
+ // addons like for example gallery later.
+ // TODO: make the script run from the addon itself.
+ let scripts = elem.querySelectorAll('script');
+ scripts.forEach(script => {
+ let scriptContent = script.textContent || script.innerText;
+ eval(scriptContent); // Execute the script
+ });
- if(isVisible)
+ // set the comment state to the state we discovered earlier
+ if (isVisible) {
showHideComments(itmId);
+ }
let commentBody = localStorage.getItem("comment_body-" + convId);
-
- if(commentBody) {
- var commentElm = $('#comment-edit-text-' + convId);
- if(auto_save_draft) {
- if($(commentElm).val() === '') {
- $('#comment-edit-form-' + convId).show();
- $(commentElm).addClass("expanded");
+ 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).val(commentBody);
+ commentElm.value = commentBody;
}
} else {
localStorage.removeItem("comment_body-" + convId);
}
}
- // trigger the autotime function on all newly created content
- $("> .wall-item-outside-wrapper .autotime, > .thread-wrapper .autotime",this).timeago();
- $("> .shared_header .autotime",this).timeago();
-
- if((mode === 'append' || mode === 'replace') && (loadingPage)) {
+ 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.indexOf("mid=") != -1 || window.location.pathname.indexOf("display") != -1) {
- let title = $(".wall-item-title").text();
- title.replace(/^\s+/, '');
- title.replace(/\s+$/, '');
- 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;
+ }
}
}
}
}
- $(this).data('b64mids').forEach((b64mid) => {
- b64mids.push(b64mid);
+ b64mids.push(...JSON.parse(elem.dataset.b64mids));
+ });
+
+ document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids }));
+
+ 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 (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);
});
+ });
+
+ 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();
+ }
});
- $(document).trigger('hz:sse_setNotificationsStatus', [b64mids]);
+ // 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;
- $(window).scrollTop(scroll_position);
+ updateRelativeTime('.autotime');
+}
+
+function imagesLoaded(elements, callback) {
+ let loadedCount = 0;
+ let totalImages = 0;
+ let timeoutId;
+ const timeout = 10000;
+ const processed = new Set(); // Use a Set for efficient lookup
- if(followUpPageLoad) {
- $(document).trigger('hz:sse_bs_counts');
+ // Helper function to extract img elements from an HTML string
+ function extractImagesFromHtml(htmlString) {
+ const tempDiv = document.createElement('div');
+ tempDiv.innerHTML = htmlString;
+ return tempDiv.querySelectorAll('.wall-item-body img, .wall-photo-item img');
}
- else {
- $(document).trigger('hz:sse_bs_init');
+
+ function checkComplete(src) {
+ // Skip processing if image has already been processed
+ if (processed.has(src)) return;
+
+ processed.add(src);
+ loadedCount++;
+
+ // Update progress
+ const progress = Math.round((loadedCount * 100) / totalImages);
+ document.getElementById('image_counter').innerText = `${progress}%`;
+
+ // If all images are loaded, trigger the callback
+ if (loadedCount === totalImages) {
+ document.getElementById('image_counter').innerText = '';
+ clearTimeout(timeoutId);
+ callback();
+ }
}
- if(commentBusy) {
- commentBusy = false;
- $('body').css('cursor', 'auto');
+ // Convert HTML string to img elements if necessary
+ if (typeof elements === 'string') {
+ elements = extractImagesFromHtml(elements);
+ }
+
+ // Exit early if there are no images to load
+ if (!elements || elements.length === 0) {
+ callback();
+ return;
}
- // Setup to determine if the media player is playing. This affects
- // some content loading decisions.
+ // Filter valid image elements (only img with src attribute)
+ const images = Array.from(elements)
+ .filter((element) => element.tagName.toLowerCase() === 'img' && element.src)
+ .filter((element, index, self) =>
+ index === self.findIndex(e => e.src === element.src) // Avoid duplicates
+ );
- $('video').off('playing');
- $('video').off('pause');
- $('audio').off('playing');
- $('audio').off('pause');
+ // If no images are found, call the callback immediately
+ if (images.length === 0) {
+ callback();
+ return;
+ }
- $('video').on('playing', function() {
- mediaPlaying = true;
- });
- $('video').on('pause', function() {
- mediaPlaying = false;
- });
- $('audio').on('playing', function() {
- mediaPlaying = true;
+ totalImages = images.length;
+
+ // Set timeout for the loading process
+ timeoutId = setTimeout(() => {
+ console.warn(`Image loading timed out after ${timeout}ms`);
+ callback(false);
+ }, timeout);
+
+ // Iterate through images to add load and error event listeners
+ images.forEach((img) => {
+ img.loading = 'eager'; // Preload the image
+
+ if (img.complete && img.naturalHeight > 0) {
+ // Image is already loaded, handle immediately
+ checkComplete(img.src);
+ } else {
+ // Add event listeners for load and error events
+ img.addEventListener('load', () => checkComplete(img.src));
+ img.addEventListener('error', () => {
+ console.log(`Image failed to load: ${img.src}`);
+ checkComplete(img.src);
+ });
+ }
});
- $('audio').on('pause', function() {
- mediaPlaying = false;
+}
+
+function updateRelativeTime(selector) {
+ // Get all elements with the given selector
+ const timeElements = document.querySelectorAll(selector);
+ if (timeElements.length === 0) return;
+
+ // Default time style and map for supported options
+ const styleMap = ['narrow', 'short', 'long'];
+ const style = styleMap.find(s => selector.includes(s)) || 'long';
+
+ // Create an instance of RelativeTimeFormat
+ const rtf = new Intl.RelativeTimeFormat(lang, {
+ localeMatcher: 'best fit', // 'best fit' or 'lookup'
+ numeric: 'always', // 'always' or 'auto'
+ style: style // 'long', 'short', or 'narrow'
});
- if(! preloadImages) {
- $('.wall-item-body, .wall-photo-item').imagesLoaded()
- .always( function( instance ) {
- //console.log('all images loaded');
- collapseHeight();
+ const now = Date.now(); // Get the current time only once
- if(bParam_mid && mode === 'replace')
- scrollToItem();
-
- })
- .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 ) {
- //var result = image.isLoaded ? 'loaded' : 'broken';
- //console.log( 'image is ' + result + ' for ' + image.img.src );
- });
- }
- else {
- collapseHeight();
+ // Helper function to calculate the time difference in appropriate units
+ function getRelativeTime(diffInSeconds) {
+ const isFuture = diffInSeconds > 0;
+ const absDiffInSeconds = Math.abs(diffInSeconds);
- if(bParam_mid && mode === 'replace')
- scrollToItem();
+ if (absDiffInSeconds < 60) return { value: absDiffInSeconds, unit: 'second' };
+ if (absDiffInSeconds < 3600) return { value: Math.floor(absDiffInSeconds / 60), unit: 'minute' };
+ if (absDiffInSeconds < 86400) return { value: Math.floor(absDiffInSeconds / 3600), unit: 'hour' };
+ if (absDiffInSeconds < 2592000) return { value: Math.floor(absDiffInSeconds / 86400), unit: 'day' };
+ if (absDiffInSeconds < 31536000) return { value: Math.floor(absDiffInSeconds / 2592000), unit: 'month' };
+ return { value: Math.floor(absDiffInSeconds / 31536000), unit: 'year' };
}
- // reset rotators and cursors we may have set before reaching this place
+ // Process each element
+ timeElements.forEach(element => {
+ const timestamp = new Date(element.title).getTime();
+ if (isNaN(timestamp)) return; // Skip invalid timestamps
- $("#page-spinner").hide();
- $("#profile-jot-text-loading").hide();
+ const diffInSeconds = Math.floor((timestamp - now) / 1000); // Time difference in seconds
+ const { value, unit } = getRelativeTime(diffInSeconds);
- followUpPageLoad = true;
+ // Format the relative time and set it as the element's text
+ const formattedTime = rtf.format(diffInSeconds > 0 ? value : -value, unit);
+ element.textContent = formattedTime;
+ });
+ // Avoid duplicate timeout registrations for the same selector
+ if (!updateTimeout.includes(selector)) {
+ updateTimeout.push(selector);
+ setTimeout(() => updateRelativeTime(selector), 60000); // Re-run the update every 60 seconds
+ }
}
function scrollToItem() {
- // auto-scroll to a particular comment in a thread (designated by mid) when in single-thread mode
+ // auto-scroll to a particular comment in a thread (designated by mid) when in single-thread mode
- if(justifiedGalleryActive)
- return;
+ if (justifiedGalleryActive) return;
- let submid = ((bParam_mid.length) ? bParam_mid : 'abcdefg');
- //var encoded = ((submid.substr(0,4) == 'b64.') ? true : false);
- //var submid_encoded = ((encoded) ? submid : window.btoa(submid));
+ let submid = ((bParam_mid.length) ? bParam_mid : 'abcdefg');
- $('.thread-wrapper').filter(function() {
- if($(this).data('b64mids').indexOf(submid) > -1 && !$(this).hasClass('toplevel_item')) {
- if($('.collapsed-comments').length) {
- var scrolltoid = $('.collapsed-comments').attr('id').substring(19);
- $('#collapsed-comments-' + scrolltoid + ' .autotime').timeago();
- $('#collapsed-comments-' + scrolltoid).show();
- $('#hide-comments-' + scrolltoid).html(aStr.showfewer);
- $('#hide-comments-total-' + scrolltoid).hide();
- }
- $('html, body').animate({ scrollTop: $(this).offset().top - $('nav').outerHeight(true) }, 'slow');
- $(this).addClass('item-highlight');
- }
- });
+ // Select all thread wrappers
+ let threadWrappers = document.querySelectorAll('.thread-wrapper');
+
+ threadWrappers.forEach(thread => {
+ // Get the 'data-b64mids' attribute and check if it contains submid
+ let b64mids = thread.dataset.b64mids;
+
+ if (b64mids && b64mids.includes(submid) && !thread.classList.contains('toplevel_item')) {
+
+ // Handle collapsed comments if any
+ let collapsedComments = document.querySelectorAll('.collapsed-comments');
+ if (collapsedComments.length) {
+ let scrolltoid = collapsedComments[0].id.substring(19);
+ let collapsedComment = document.getElementById('collapsed-comments-' + scrolltoid);
+ let hideCommentsLabel = document.getElementById('hide-comments-label-' + scrolltoid);
+ let hideCommentsTotal = document.getElementById('hide-comments-total-' + scrolltoid);
+
+ if (collapsedComment) collapsedComment.style.display = 'block';
+ if (hideCommentsLabel) hideCommentsLabel.innerHTML = aStr.showfewer;
+ if (hideCommentsTotal) hideCommentsTotal.style.display = 'none';
+ }
+
+ // Scroll to the target element
+ let navHeight = document.querySelector('nav') ? document.querySelector('nav').offsetHeight : 0;
+ window.scrollTo({
+ top: thread.offsetTop - navHeight,
+ behavior: 'smooth'
+ });
+ // Add highlight class
+ thread.classList.add('item-highlight');
+ }
+ });
}
function collapseHeight() {
@@ -869,8 +989,8 @@ function collapseHeight() {
startOpen: open,
heightMargin: 50,
collapsedHeight: divmore_height,
- moreLink: '<a href="#" class="divgrow-showmore fakelink">' + aStr.divgrowmore + '</a>',
- lessLink: '<a href="#" class="divgrow-showmore fakelink">' + aStr.divgrowless + '</a>',
+ moreLink: '<a href="#" class="divgrow-showmore fakelink"><i class="bi bi-chevron-down align-middle divgrow-showmore-icon"></i>&nbsp;<span class="divgrow-showmore-label align-middle">' + aStr.divgrowmore + '</span></a>',
+ lessLink: '<a href="#" class="divgrow-showmore fakelink"><i class="bi bi-chevron-up align-middle divgrow-showmore-icon"></i>&nbsp;<span class="divgrow-showmore-label align-middle">' + aStr.divgrowless + '</span></a>',
beforeToggle: function(trigger, element, expanded) {
if(expanded) {
if((($(element).offset().top + divmore_height) - $(window).scrollTop()) < 65 ) {
@@ -906,7 +1026,7 @@ function updateInit() {
liveUpdate();
}
else {
- $(document).trigger('hz:sse_bs_init');
+ document.dispatchEvent(new Event('hz:sse_bs_init'));
}
if($('#live-photos').length || $('#live-cards').length || $('#live-articles').length ) {
@@ -1032,10 +1152,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.');
@@ -1044,23 +1161,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;
@@ -1102,9 +1203,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;
@@ -1112,19 +1212,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 );
});
-
});
}
@@ -1144,7 +1232,7 @@ function pageUpdate() {
bParam_page = 1;
}
- update_url = baseurl + '/' + decodeURIComponent(page_query) + '/?f=&aj=1&page=' + bParam_page + extra_args ;
+ update_url = baseurl + '/' + decodeURIComponent(page_query) + '?aj=1&page=' + bParam_page + extra_args ;
$("#page-spinner").show();
update_mode = 'append';
@@ -1154,7 +1242,7 @@ function pageUpdate() {
scroll_next = false;
updatePageItems(update_mode,data);
$("#page-spinner").hide();
- $(".autotime").timeago();
+ updateRelativeTime('.autotime');
in_progress = false;
});
}
@@ -1176,20 +1264,27 @@ function justifyPhotosAjax(id) {
}
function dolike(ident, verb) {
- $('#like-rotator-' + ident.toString()).show();
+ $('#like-rotator-' + ident).show();
- if(typeof conv_mode == typeof undefined)
+ if (typeof conv_mode == typeof undefined) {
conv_mode = '';
+ }
- if(typeof page_mode == typeof undefined)
+ if (typeof page_mode == typeof undefined) {
page_mode = '';
+ }
+
+ let reload = 0;
- var reload = '';
- if(module == 'photos')
+ if (module == 'photos') {
reload = 1;
+ }
+
+
+ $.get('like/' + ident + '?verb=' + verb + '&conv_mode=' + conv_mode + '&page_mode=' + page_mode + '&reload=' + reload, function (data) {
+ if (data.success) {
- $.get('like/' + ident.toString() + '?verb=' + verb + '&conv_mode=' + conv_mode + '&page_mode=' + page_mode + '&reload=' + reload, function (data) {
- if(data.success) {
+ close_modal();
// mod photos
if (data.reload) {
@@ -1207,11 +1302,13 @@ function dolike(ident, verb) {
else {
$('#thread-wrapper-' + data.orig_id).replaceWith(data.html);
}
- $('#wall-item-ago-' + data.id + ' .autotime').timeago();
+
+ updateRelativeTime('.autotime');
collapseHeight();
liking = 0;
}
});
+
liking = 1;
}
@@ -1225,7 +1322,7 @@ function doreply(parent, ident, owner, hint) {
form.find('input[name=parent]').val(ident);
var i = form.find('button[type=submit]');
var btn = i.html().replace(/<[^>]*>/g, '').trim();
- i.html('<i class="fa fa-reply" ></i> ' + btn);
+ i.html('<i class="bi bi-arrow-90deg-left"></i> ' + btn);
var sel = 'wall-item-body-' + ident.toString();
var quote = window.getSelection().toString().trim();
form.find('textarea').val("@{" + owner + "}" + ((($(window.getSelection().anchorNode).closest("#" + sel).attr("id") != sel) || (quote.length === 0))? " " : "\n[quote]" + quote + "[/quote]\n"));
@@ -1257,7 +1354,7 @@ function doscroll(parent, hidden) {
});
$('html, body').animate({scrollTop:(id.offset().top) - 50}, 'slow');
- $('<a href="javascript:doscrollback(' + pos + ');" id="back-to-reply" title="' + aStr['to_reply'] + '"><i class="fa fa-angle-double-down"></i></a>').insertAfter('#wall-item-ago-' + id.attr('id').replace(/\D/g,''));
+ $('<a href="javascript:doscrollback(' + pos + ');" id="back-to-reply" title="' + aStr['to_reply'] + '"><i class="bi bi-chevron-double-down"></i></a>').insertAfter('#wall-item-ago-' + id.attr('id').replace(/\D/g,''));
}
function doscrollback(pos) {
@@ -1282,7 +1379,7 @@ function dopin(id) {
$('.dropdown-item-pinnable').html($('.dropdown-item-pinnable').html().replace(aStr['unpin_item'],aStr['pin_item']));
$('.wall-item-pinned').remove()
if(i.length == 0) {
- $('<span class="wall-item-pinned" title="' + aStr['pinned'] + '" id="wall-item-pinned-' + id + '"><i class="fa fa-thumb-tack">&nbsp;</i></span>').insertAfter('#wall-item-ago-' + id);
+ $('<span class="wall-item-pinned" title="' + aStr['pinned'] + '" id="wall-item-pinned-' + id + '"><i class="bi bi-pin">&nbsp;</i></span>').insertAfter('#wall-item-ago-' + id);
me.html(me.html().replace(aStr['pin_item'],aStr['unpin_item']));
};
})
@@ -1305,7 +1402,7 @@ function dropItem(url, object, b64mid) {
$(object + ', #pinned-wrapper-' + id).remove();
$('body').css('cursor', 'auto');
- toast(aStr.itemdel, 'info')
+ toast(aStr.itemdel, 'info');
//$.jGrowl(aStr.itemdel, { sticky: false, theme: 'info', life: 3000 });
if (typeof b64mid !== typeof undefined) {
@@ -1327,26 +1424,28 @@ function dropItem(url, object, b64mid) {
}
function dosubthread(ident) {
- $('#like-rotator-' + ident.toString()).show();
- $.get('subthread/sub/' + ident.toString(), updateInit );
+ $('#like-rotator-' + ident).show();
+ $.get('subthread/sub/' + ident, updateInit );
liking = 1;
}
function dounsubthread(ident) {
- $('#like-rotator-' + ident.toString()).show();
- $.get('subthread/unsub/' + ident.toString(), updateInit );
+ $('#like-rotator-' + ident).show();
+ $.get('subthread/unsub/' + ident, updateInit );
liking = 1;
}
-function moderate_approve(ident) {
- $('#like-rotator-' + ident.toString()).show();
- $.get('moderate/' + ident.toString() + '/approve', updateInit );
+function moderate_approve(ident, verb) {
+ $('#like-rotator-' + ident).show();
+ close_modal();
+ $.get('moderate/' + ident + '/approve', updateInit );
liking = 1;
}
function moderate_drop(ident) {
- $('#like-rotator-' + ident.toString()).show();
- $.get('moderate/' + ident.toString() + '/drop', $('#thread-wrapper-' + ident.toString()).fadeOut(function() { this.remove(); }));
+ $('#like-rotator-' + ident).show();
+ close_modal();
+ $.get('moderate/' + ident + '/drop', $('#thread-wrapper-' + ident).fadeOut(function() { this.remove(); }));
liking = 1;
}
@@ -1357,18 +1456,18 @@ function dostar(ident) {
if(data.result == 1) {
$('#starred-' + ident).addClass('starred');
$('#starred-' + ident).removeClass('unstarred');
- $('#starred-' + ident).addClass('fa-star');
- $('#starred-' + ident).removeClass('fa-star-o');
+ $('#starred-' + ident).addClass('bi-star-fill');
+ $('#starred-' + ident).removeClass('bi-star');
$('#star-' + ident).addClass('hidden');
$('#unstar-' + ident).removeClass('hidden');
- var btn_tpl = '<div class="btn-group" id="star-button-' + ident + '"><button type="button" class="btn btn-outline-secondary border-0 btn-sm wall-item-star" onclick="dostar(' + ident + ');"><i class="fa fa-star"></i></button></div>'
- $('#wall-item-tools-left-' + ident).prepend(btn_tpl);
+ var btn_tpl = '<div class="" id="star-button-' + ident + '"><button type="button" class="btn btn-sm btn-link link-secondary wall-item-star" onclick="dostar(' + ident + ');"><i class="bi bi-star generic-icons"></i></button></div>'
+ $('#wall-item-tools-right-' + ident).prepend(btn_tpl);
}
else {
$('#starred-' + ident).addClass('unstarred');
$('#starred-' + ident).removeClass('starred');
- $('#starred-' + ident).addClass('fa-star-o');
- $('#starred-' + ident).removeClass('fa-star');
+ $('#starred-' + ident).addClass('bi-star');
+ $('#starred-' + ident).removeClass('bi-star-fill');
$('#star-' + ident).removeClass('hidden');
$('#unstar-' + ident).addClass('hidden');
$('#star-button-' + ident).remove();
@@ -1445,7 +1544,7 @@ function post_comment(id) {
$("#comment-edit-preview-" + id).hide();
$("#comment-edit-text-" + id).val('').blur().attr('placeholder', aStr.comment);
$('#wall-item-comment-wrapper-' + id).before(data.html);
- $('#wall-item-ago-' + data.id + ' .autotime').timeago();
+ updateRelativeTime('.autotime');
$('body').css('cursor', 'unset');
collapseHeight();
commentBusy = false;
@@ -1475,7 +1574,7 @@ function preview_comment(id) {
function(data) {
if(data.preview) {
$("#comment-edit-preview-" + id).html(data.preview);
- $("#comment-edit-preview-" + id + " .autotime").timeago();
+ updateRelativeTime('.autotime');
$("#comment-edit-preview-" + id + " a").click(function() { return false; });
}
},
@@ -1505,7 +1604,7 @@ function preview_post() {
function(data) {
if(data.preview) {
$("#jot-preview-content").html(data.preview);
- $("#jot-preview-content .autotime").timeago();
+ updateRelativeTime('.autotime');
$("#jot-preview-content" + " a").click(function() { return false; });
}
},
@@ -1553,7 +1652,7 @@ function contactgroupChangeMember(gid, cid) {
$('body').css('cursor', 'wait');
$.get('contactgroup/' + gid + '/' + cid, function(data) {
$('body').css('cursor', 'auto');
- $('#group-' + gid).toggleClass('fa-check-square-o fa-square-o');
+ $('#group-' + gid).toggleClass('bi-check-square bi-square');
});
}
@@ -1622,11 +1721,6 @@ $(window).scroll(function () {
}
});
-function addhtmltext(data) {
- data = h2b(data);
- addeditortext(data);
-}
-
function loadText(textRegion,data) {
var currentText = $(textRegion).val();
$(textRegion).val(currentText + data);
@@ -1639,123 +1733,6 @@ function addeditortext(data) {
}
}
-function h2b(s) {
- var y = s;
- function rep(re, str) {
- y = y.replace(re,str);
- }
-
- rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
- rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]");
- rep(/<span style=\"color:(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]");
- rep(/<font>(.*?)<\/font>/gi,"$1");
- rep(/<img.*?width=\"(.*?)\".*?height=\"(.*?)\".*?src=\"(.*?)\".*?\/>/gi,"[img=$1x$2]$3[/img]");
- rep(/<img.*?height=\"(.*?)\".*?width=\"(.*?)\".*?src=\"(.*?)\".*?\/>/gi,"[img=$2x$1]$3[/img]");
- rep(/<img.*?src=\"(.*?)\".*?height=\"(.*?)\".*?width=\"(.*?)\".*?\/>/gi,"[img=$3x$2]$1[/img]");
- rep(/<img.*?src=\"(.*?)\".*?width=\"(.*?)\".*?height=\"(.*?)\".*?\/>/gi,"[img=$2x$3]$1[/img]");
- rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");
-
- rep(/<ul class=\"listbullet\" style=\"list-style-type\: circle\;\">(.*?)<\/ul>/gi,"[list]$1[/list]");
- rep(/<ul class=\"listnone\" style=\"list-style-type\: none\;\">(.*?)<\/ul>/gi,"[list=]$1[/list]");
- rep(/<ul class=\"listdecimal\" style=\"list-style-type\: decimal\;\">(.*?)<\/ul>/gi,"[list=1]$1[/list]");
- rep(/<ul class=\"listlowerroman\" style=\"list-style-type\: lower-roman\;\">(.*?)<\/ul>/gi,"[list=i]$1[/list]");
- rep(/<ul class=\"listupperroman\" style=\"list-style-type\: upper-roman\;\">(.*?)<\/ul>/gi,"[list=I]$1[/list]");
- rep(/<ul class=\"listloweralpha\" style=\"list-style-type\: lower-alpha\;\">(.*?)<\/ul>/gi,"[list=a]$1[/list]");
- rep(/<ul class=\"listupperalpha\" style=\"list-style-type\: upper-alpha\;\">(.*?)<\/ul>/gi,"[list=A]$1[/list]");
- rep(/<li>(.*?)<\/li>/gi,"[li]$1[/li]");
-
- rep(/<code>(.*?)<\/code>/gi,"[code]$1[/code]");
- rep(/<\/(strong|b)>/gi,"[/b]");
- rep(/<(strong|b)>/gi,"[b]");
- rep(/<\/(em|i)>/gi,"[/i]");
- rep(/<(em|i)>/gi,"[i]");
- rep(/<\/u>/gi,"[/u]");
-
- rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]");
- rep(/<u>/gi,"[u]");
- rep(/<blockquote[^>]*>/gi,"[quote]");
- rep(/<\/blockquote>/gi,"[/quote]");
- rep(/<hr \/>/gi,"[hr]");
- rep(/<br (.*?)\/>/gi,"\n");
- rep(/<br\/>/gi,"\n");
- rep(/<br>/gi,"\n");
- rep(/<p>/gi,"");
- rep(/<\/p>/gi,"\n");
- rep(/&nbsp;/gi," ");
- rep(/&quot;/gi,"\"");
- rep(/&lt;/gi,"<");
- rep(/&gt;/gi,">");
- rep(/&amp;/gi,"&");
-
- return y;
-}
-
-function b2h(s) {
- var y = s;
- function rep(re, str) {
- y = y.replace(re,str);
- }
-
- rep(/\&/gi,"&amp;");
- rep(/\</gi,"&lt;");
- rep(/\>/gi,"&gt;");
- rep(/\"/gi,"&quot;");
-
- rep(/\n/gi,"<br />");
- rep(/\[b\]/gi,"<strong>");
- rep(/\[\/b\]/gi,"</strong>");
- rep(/\[i\]/gi,"<em>");
- rep(/\[\/i\]/gi,"</em>");
- rep(/\[u\]/gi,"<u>");
- rep(/\[\/u\]/gi,"</u>");
- rep(/\[hr\]/gi,"<hr />");
- rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>");
- rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>");
- rep(/\[img=(.*?)x(.*?)\](.*?)\[\/img\]/gi,"<img width=\"$1\" height=\"$2\" src=\"$3\" />");
- rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");
-
- rep(/\[zrl=([^\]]+)\](.*?)\[\/zrl\]/gi,"<a href=\"$1" + '?f=&zid=' + zid + "\">$2</a>");
- rep(/\[zrl\](.*?)\[\/zrl\]/gi,"<a href=\"$1" + '?f=&zid=' + zid + "\">$1</a>");
- rep(/\[zmg=(.*?)x(.*?)\](.*?)\[\/zmg\]/gi,"<img width=\"$1\" height=\"$2\" src=\"$3" + '?f=&zid=' + zid + "\" />");
- rep(/\[zmg\](.*?)\[\/zmg\]/gi,"<img src=\"$1" + '?f=&zid=' + zid + "\" />");
-
- rep(/\[list\](.*?)\[\/list\]/gi, '<ul class="listbullet" style="list-style-type: circle;">$1</ul>');
- rep(/\[list=\](.*?)\[\/list\]/gi, '<ul class="listnone" style="list-style-type: none;">$1</ul>');
- rep(/\[list=1\](.*?)\[\/list\]/gi, '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>');
- rep(/\[list=i\](.*?)\[\/list\]/gi,'<ul class="listlowerroman" style="list-style-type: lower-roman;">$1</ul>');
- rep(/\[list=I\](.*?)\[\/list\]/gi, '<ul class="listupperroman" style="list-style-type: upper-roman;">$1</ul>');
- rep(/\[list=a\](.*?)\[\/list\]/gi, '<ul class="listloweralpha" style="list-style-type: lower-alpha;">$1</ul>');
- rep(/\[list=A\](.*?)\[\/list\]/gi, '<ul class="listupperalpha" style="list-style-type: upper-alpha;">$1</ul>');
- rep(/\[li\](.*?)\[\/li\]/gi, '<li>$1</li>');
- rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<span style=\"color: $1;\">$2</span>");
- rep(/\[size=(.*?)\](.*?)\[\/size\]/gi,"<span style=\"font-size: $1;\">$2</span>");
- rep(/\[code\](.*?)\[\/code\]/gi,"<code>$1</code>");
- rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<blockquote>$1</blockquote>");
-
- rep(/\[video\](.*?)\[\/video\]/gi,"<a href=\"$1\">$1</a>");
- rep(/\[audio\](.*?)\[\/audio\]/gi,"<a href=\"$1\">$1</a>");
-
- rep(/\[\&amp\;([#a-z0-9]+)\;\]/gi,'&$1;');
-
- rep(/\<(.*?)(src|href)=\"[^hfm](.*?)\>/gi,'<$1$2="">');
-
- return y;
-}
-
-function zid(s) {
- if((! s.length) || (s.indexOf('zid=') != (-1)))
- return s;
-
- if(! zid.length)
- return s;
-
- var has_params = ((s.indexOf('?') == (-1)) ? false : true);
- var achar = ((has_params) ? '&' : '?');
- s = s + achar + 'f=&zid=' + zid;
-
- return s;
-}
-
function makeid(length) {
var result = '';
var characters = 'abcdef0123456789';
@@ -1801,7 +1778,7 @@ function push_notification(title, body, b64mid) {
function toggleAside() {
if ($('main.region_1-on').length) {
- $('#expand-aside-icon').addClass('fa-arrow-circle-right').removeClass('fa-arrow-circle-left');
+ $('#expand-aside-icon').addClass('bi-arrow-right-circle').removeClass('bi-arrow-left-circle');
$('html, body').css({ 'position': '', 'left': '' });
$('main').removeClass('region_1-on');
$('#region_1').addClass('d-none');
@@ -1809,7 +1786,7 @@ function toggleAside() {
$('#overlay').remove();
}
else {
- $('#expand-aside-icon').removeClass('fa-arrow-circle-right').addClass('fa-arrow-circle-left');
+ $('#expand-aside-icon').removeClass('bi-arrow-right-circle').addClass('bi-arrow-left-circle');
$('html, body').css({ 'position': 'sticky', 'left': '0px'});
$('main').addClass('region_1-on');
$('#region_1').removeClass('d-none');
@@ -1819,7 +1796,7 @@ function toggleAside() {
}
function toast(string, severity) {
- let id = btoa(string);
+ let id = bin2hex(string);
let container = document.getElementById('toast-container');
let toast = document.getElementById(id);
@@ -1840,3 +1817,11 @@ function toast(string, severity) {
toastInstance.show();
}
+
+function close_modal() {
+ let modal = bootstrap.Modal.getInstance(document.querySelector('.modal.show'));
+
+ if (modal) {
+ modal.hide();
+ }
+}