diff options
Diffstat (limited to 'view/js')
-rw-r--r-- | view/js/autocomplete.js | 2 | ||||
-rw-r--r-- | view/js/main.js | 644 |
2 files changed, 577 insertions, 69 deletions
diff --git a/view/js/autocomplete.js b/view/js/autocomplete.js index 7d6ddb1c4..ad8e04050 100644 --- a/view/js/autocomplete.js +++ b/view/js/autocomplete.js @@ -38,7 +38,7 @@ function contact_format(item) { var desc = ((item.label) ? item.nick + ' ' + item.label : item.nick); if(typeof desc === 'undefined') desc = ''; if(desc) desc = ' ('+desc+')'; - return "<div class='dropdown-item dropdown-notification lh-sm text-truncate' title='{4}'><img class='menu-img-2' src='{1}' loading='lazy'><strong>{2}</strong><br><small class='opacity-75'>{4}</small></div>".format(item.taggable, item.photo, item.name, desc, typeof(item.link) !== 'undefined' ? item.link : desc.replace('(','').replace(')','')); + return "<div class='dropdown-item dropdown-notification lh-sm text-truncate' title='{4}'><img class='menu-img-2' src='{1}' loading='lazy'><strong>{2}</strong><br><small class='text-body-secondary'>{4}</small></div>".format(item.taggable, item.photo, item.name, desc, typeof(item.link) !== 'undefined' ? item.link : desc.replace('(','').replace(')','')); } else return ""; diff --git a/view/js/main.js b/view/js/main.js index 43f0333ed..5bf7234aa 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -26,6 +26,10 @@ var followUpPageLoad = false; var window_needs_alert = true; var expanded_items = []; var updateTimeout = []; +const singlethread_modules = ['display', 'hq']; +const redirect_modules = ['display', 'notify']; +let b64mids = []; + var page_cache = {}; @@ -85,6 +89,146 @@ $(document).ready(function() { } }); + document.addEventListener('click', function(event) { + // Only handle clicks on .wall-item-reaction or its children + const target = event.target.closest('.wall-item-reaction'); + if (!target) return; + + let doRequest = true; + const isUserClick = event.isTrusted; + + // Destructure relevant data attributes + const { itemId: id, itemMid: mid, itemParent: parentId, itemUuid: uuid, itemVerb: verb } = target.dataset; + const isCommentBtn = target.classList.contains('wall-item-comment'); + + if (isCommentBtn) { + if (id === parentId) { + // Handle blog mode + target.classList.add('disabled'); + document.getElementById(`load-more-progress-wrapper-${id}`).classList.remove('d-none'); + document.getElementById(`load-more-${id}`).classList.remove('d-none') + request(id, mid, 'load', parentId, uuid, isUserClick); + return; + } + + // Get relevant DOM elements + const threadWrapper = document.getElementById(`thread-wrapper-${id}`); + const parentWrapper = document.getElementById(`thread-wrapper-${parentId}`); + const subThreadWrapper = document.getElementById(`wall-item-sub-thread-wrapper-${id}`); + const parentSubThreadWrapper = document.getElementById(`wall-item-sub-thread-wrapper-${parentId}`); + + // Query related sub-thread and highlight elements + const parentIndentedThreads = document.querySelectorAll(`#wall-item-sub-thread-wrapper-${parentId} .wall-item-sub-thread-wrapper.item-indent`); + + let ancestorIds = []; + + doRequest = !subThreadWrapper.children.length; + + // Set visual styles using UUID + subThreadWrapper.style.setProperty('--hz-item-indent', stringToHslColor(uuid)); + threadWrapper.style.setProperty('--hz-item-highlight', stringToHslColor(uuid)); + threadWrapper.style.setProperty('--hz-wall-item-expanded-before-content', '"' + aStr.dblclick_to_exit_zoom + '"'); + + // Clear previous highlights + parentSubThreadWrapper.querySelectorAll('.thread-wrapper.item-highlight').forEach(el => el.classList.remove('item-highlight')); + + if (isUserClick && parentIndentedThreads.length === 0 && !subThreadWrapper.children.length) { + // Handle first-time expansion and highlighting but not for toplevels (blog mode) + threadWrapper.classList.add('item-highlight'); + } else { + // Handle indentation and zooming + let ancestor = subThreadWrapper.parentElement; + ancestorIds.push(ancestor.id.slice(15)); // thread-wrapper-1234 + + while (ancestor) { + if (ancestor.classList.contains('item-indent') && ancestor.classList.contains('wall-item-sub-thread-wrapper')) { + ancestorIds.push(ancestor.parentElement.id.slice(15)); + } + ancestor = ancestor.parentElement; + } + + ancestorIds.reverse(); + + if (ancestorIds.length > 3) { + // Handle zooming in + let firstWrapper = document.getElementById('thread-wrapper-' + ancestorIds[0]); + let firstSubWrapper = document.getElementById('wall-item-sub-thread-wrapper-' + ancestorIds[0]); + + firstWrapper.querySelector('.wall-item-comment').classList.remove('indented'); + firstWrapper.classList.remove('wall-item-expanded', 'shadow'); + firstSubWrapper.classList.remove('item-indent'); + + let newFirstWrapper = document.getElementById('thread-wrapper-' + ancestorIds[1]) + let newFirstSubWrapper = document.getElementById('wall-item-sub-thread-wrapper-' + ancestorIds[1]) + + newFirstWrapper.classList.add('wall-item-expanded', 'shadow'); + parentWrapper.classList.add('wall-item-backdrop'); + + // Exit zoom on double-click + newFirstWrapper.addEventListener('dblclick', function() { + parentWrapper.querySelectorAll('.wall-item-comment.indented').forEach(el => el.classList.remove('indented')); + parentWrapper.querySelectorAll('.wall-item-comment.collapsed').forEach(el => el.classList.remove('collapsed')); + parentWrapper.classList.remove('wall-item-backdrop'); + parentWrapper.querySelectorAll('.wall-item-sub-thread-wrapper.item-indent').forEach(el => el.classList.remove('item-indent')); + parentWrapper.querySelectorAll('.wall-item-sub-thread-wrapper.d-none').forEach(el => el.classList.remove('d-none')); + parentWrapper.querySelectorAll('.thread-wrapper.wall-item-expanded').forEach(el => el.classList.remove('wall-item-expanded', 'shadow')); + }, { once: true }); + } + + // Toggle sub-thread visibility if indented + if (isUserClick && target.classList.contains('indented')) { + doRequest = false; + subThreadWrapper.classList.toggle('d-none'); + target.classList.toggle('collapsed'); + } + + // Indenting of already expanded but flattened items + if (isUserClick && subThreadWrapper.classList.contains('item-expanded') && !subThreadWrapper.classList.contains('item-indent')) { + doRequest = false; + + threadWrapper.querySelectorAll('.wall-item-sub-thread-wrapper.item-expanded').forEach(function (el, i) { + el.classList.add('item-indent'); + + el.querySelectorAll('.wall-item-comment.expanded').forEach(function (el, i) { + el.classList.add('collapsed', 'indented'); + }); + + // Collapse everything below the first level + if (i > 0) { + el.classList.add('d-none'); + } + }); + } + + // Indent the subthread + subThreadWrapper.classList.add('item-indent', 'item-expanded'); + + // Mark as indented after visibility toggle + target.classList.add('indented'); + } + + // Mark as expanded + target.classList.add('expanded'); + } + + if (doRequest) { + request(id, mid, verb, parentId, uuid, isUserClick); + } + }); + + document.addEventListener('click', function(event) { + const targetElement = event.target.closest('.dropdown-item-expand'); + if (!targetElement) return; + + event.preventDefault(); + + const id = targetElement.dataset.itemId; + const subWrapper = document.getElementById(`wall-item-sub-thread-wrapper-${id}`); + + subWrapper.innerHTML = ''; + autoExpand(id); + }); + // @hilmar |-> if ( typeof(window.tao) == 'undefined' ) { window.tao = {}; @@ -149,8 +293,6 @@ $(document).ready(function() { let notify_id = this.dataset.notify_id; let path = $(this)[0].pathname.split('/')[1]; let stateObj = { b64mid: b64mid }; - let singlethread_modules = ['display', 'hq']; - let redirect_modules = ['display', 'notify']; if (!b64mid && !notify_id) { return; @@ -329,6 +471,13 @@ function handle_comment_form(e) { var commentSaveTimer = null; var emptyCommentElm = form.find('.comment-edit-text').attr('id'); var convId = emptyCommentElm.replace('comment-edit-text-',''); + + // in case parent input is set use it as convId + const parentInputVal = form.find(':input[name=parent]').val(); + if (parentInputVal) { + convId = parentInputVal; + } + $('#' + emptyCommentElm).on('focusout',function(e){ if(commentSaveTimer) clearTimeout(commentSaveTimer); @@ -502,8 +651,11 @@ function showHideComments(id) { let isCollapsed = collapsedComments.style.display === 'none'; collapsedComments.style.display = isCollapsed ? '' : 'none'; - hideCommentsLabel.textContent = isCollapsed ? aStr.showfewer : aStr.showmore; - hideCommentsTotal.style.display = isCollapsed ? 'none' : ''; + hideCommentsLabel.textContent = isCollapsed ? hideCommentsLabel.dataset.expanded : hideCommentsLabel.dataset.collapsed; + + if (hideCommentsTotal) { + hideCommentsTotal.style.display = isCollapsed ? 'none' : ''; + } let oldClass = isCollapsed ? 'bi-chevron-down' : 'bi-chevron-up'; let newClass = isCollapsed ? 'bi-chevron-up' : 'bi-chevron-down'; @@ -740,7 +892,27 @@ function updateConvItems(mode, data) { } } - b64mids.push(...JSON.parse(elem.dataset.b64mids)); + let data_json = JSON.parse(elem.dataset.b64mids); + + if (elem.parentNode.classList.contains('wall-item-sub-thread-wrapper') && elem.parentNode.children.length) { + // Set the highlight state + if (data_json.includes(bParam_mid) && !elem.parentNode.parentNode.classList.contains('toplevel_item')) { + elem.parentNode.parentNode.classList.add('item-highlight'); + document.documentElement.style.setProperty('--hz-item-highlight', stringToHslColor(JSON.parse(elem.parentNode.parentNode.dataset.b64mids)[0])); + } + + let elemSubThreadWrapper = elem.querySelector('.wall-item-sub-thread-wrapper'); + let elemCommentButton = elem.querySelector('.wall-item-comment'); + + // Set the button and sub-thread-wrapper state + if (elemCommentButton && elemSubThreadWrapper.children.length) { + elemCommentButton.classList.add('expanded'); + } + + elem.parentNode.classList.add('item-expanded'); + } + + b64mids.push(...data_json); }); document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids })); @@ -771,10 +943,12 @@ function updateConvItems(mode, data) { } imagesLoaded(document.querySelectorAll('.wall-item-body img, .wall-photo-item img'), function () { - collapseHeight(); if (bParam_mid && mode === 'replace') { scrollToItem(); } + else { + collapseHeight(); + } }); // reset rotators and cursors we may have set before reaching this place @@ -789,6 +963,7 @@ function updateConvItems(mode, data) { followUpPageLoad = true; + updateRelativeTime('.autotime'); } @@ -859,19 +1034,25 @@ function imagesLoaded(elements, callback) { // Iterate through images to add load and error event listeners images.forEach((img) => { - img.loading = 'eager'; // Preload the image + let new_img = new Image(); + new_img.src = img.src; - if (img.complete && img.naturalHeight > 0) { + if (new_img.complete && new_img.naturalHeight > 0) { // Image is already loaded, handle immediately - checkComplete(img.src); + // console.log(`Image cached: ${new_img.src}`); + checkComplete(new_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); + new_img.addEventListener('load', () => { + // console.log(`Image loaded: ${new_img.src}`); + checkComplete(new_img.src) + }); + new_img.addEventListener('error', () => { + console.log(`Image failed to load: ${new_img.src}`); + checkComplete(new_img.src); }); } + }); } @@ -927,45 +1108,52 @@ function updateRelativeTime(selector) { } 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'); + let submid = ((bParam_mid.length) ? bParam_mid : 'abcdefg'); - // Select all thread wrappers - let threadWrappers = document.querySelectorAll('.thread-wrapper'); + // 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; + 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')) { + if (b64mids && b64mids.includes(submid)) { + // Handle collapsed comments if any + let collapsedComments = document.querySelectorAll('.collapsed-comments'); + if (collapsedComments.length) { + let scrollToId = collapsedComments[0].id.substring(19); + showHideComments(scrollToId); + } - // 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); + collapseHeight(); - if (collapsedComment) collapsedComment.style.display = 'block'; - if (hideCommentsLabel) hideCommentsLabel.innerHTML = aStr.showfewer; - if (hideCommentsTotal) hideCommentsTotal.style.display = 'none'; - } + if (!thread.classList.contains('toplevel_item')) { + // Scroll to the target element + let navHeight = document.getElementById('navbar-top') ? document.getElementById('navbar-top').offsetHeight : 0; + window.scrollTo({ + top: getOffsetTopRelativeToBody(thread) - navHeight, + behavior: 'smooth' + }); + } - // Scroll to the target element - let navHeight = document.querySelector('nav') ? document.querySelector('nav').offsetHeight : 0; - window.scrollTo({ - top: thread.offsetTop - navHeight, - behavior: 'smooth' - }); + let id = thread.id.replace('thread-wrapper-', ''); + let content = document.getElementById('wall-item-content-wrapper-' + id); + content.classList.add('item-highlight-fade'); + } + }); +} - // Add highlight class - thread.classList.add('item-highlight'); - } - }); +function getOffsetTopRelativeToBody(element) { + let offsetTop = 0; + while (element) { + offsetTop += element.offsetTop; + element = element.offsetParent; + } + return offsetTop; } function collapseHeight() { @@ -1153,26 +1341,16 @@ function liveUpdate(notify_id) { var dready = new Date(); console.log('DATA ready in: ' + (dready - dstart)/1000 + ' seconds.'); - if(update_mode === 'update' || preloadImages) { - console.log('LOADING images...'); - imagesLoaded(data, function () { - var iready = new Date(); - console.log('IMAGES ready in: ' + (iready - dready)/1000 + ' seconds.'); - - page_load = false; - scroll_next = false; - updateConvItems(update_mode,data); + console.log('LOADING images...'); + imagesLoaded(data, function () { + var iready = new Date(); + console.log('IMAGES ready in: ' + (iready - dready)/1000 + ' seconds.'); - in_progress = false; - }); - } - else { page_load = false; scroll_next = false; updateConvItems(update_mode,data); in_progress = false; - } - + }); }); } @@ -1266,6 +1444,277 @@ function justifyPhotosAjax(id) { $('#' + id).justifiedGallery('norewind').on('jg.complete', function(e){ justifiedGalleryActive = false; }); } +function request(id, mid, verb, parent, uuid, userClick) { + + if (verb === 'load') { + const dots = document.getElementById('load-more-dots-' + parent); + dots.classList.add('jumping-dots'); + + const parent_sub = document.getElementById('wall-item-sub-thread-wrapper-' + parent); + const offset = parent_sub.children.length; + + fetch('/request?offset=' + offset + '&verb=' + verb + '&mid=' + mid + '&parent=' + parent + '&module=' + module) + .then(response => response.json()) + .then(obj => { + let parser = new DOMParser(); + let doc = parser.parseFromString(obj.html, 'text/html'); + let b64mids = []; + + doc.querySelectorAll('.thread-wrapper').forEach(function (e) { + let data = JSON.parse(e.dataset.b64mids); + b64mids.push(...data); + }); + + imagesLoaded(doc.querySelectorAll('.wall-item-body img'), function () { + injectWithAnimation('wall-item-sub-thread-wrapper-' + parent, doc); + dots.classList.remove('jumping-dots'); + + const loadmore_progress = document.getElementById('load-more-progress-' + parent); + loadmore_progress.style.width = Math.round(100 * parent_sub.children.length / loadmore_progress.dataset.commentsTotal) + '%'; + + if (Number(parent_sub.children.length) === Number(loadmore_progress.dataset.commentsTotal)) { + const loadmore = document.getElementById('load-more-' + parent); + loadmore.remove(); + } + + updateRelativeTime('.autotime'); + collapseHeight(); + + document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids })); + document.dispatchEvent(new Event('hz:sse_bs_counts')); + }); + + }) + .catch(error => { + console.error('Error fetching data:', error); + }); + + return; + } + + const loading = document.getElementById('like-rotator-' + id); + + if (userClick) { + loading.style.display = 'block'; + } + + if (verb === 'comment') { + if (userClick && singlethread_modules.indexOf(module) !== -1) { + let stateObj = { b64mid: uuid }; + history.pushState(stateObj, '', module + '/' + uuid); + } + + fetch('/request?verb=' + verb + '&mid=' + mid + '&parent=' + parent + '&module=' + module) + .then(response => response.json()) + .then(obj => { + let parser = new DOMParser(); + let doc = parser.parseFromString(obj.html, 'text/html'); + + doc.querySelectorAll('.thread-wrapper').forEach(function (e) { + let data = JSON.parse(e.dataset.b64mids); + b64mids.push(...data); + }); + + imagesLoaded(doc.querySelectorAll('.wall-item-body img'), function () { + injectWithAnimation('wall-item-sub-thread-wrapper-' + id, doc, true); + updateRelativeTime('.autotime'); + collapseHeight(); + + if (userClick) { + loading.style.display = 'none'; + document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids })); + document.dispatchEvent(new Event('hz:sse_bs_counts')); + } + }); + + }) + .catch(error => { + console.error('Error fetching data:', error); + }); + } + else { + fetch('/request?verb=' + verb + '&mid=' + mid + '&parent=' + parent) + .then(response => response.json()) + .then(obj => { + const modal = new bootstrap.Modal('#reactions'); + const modal_content = document.getElementById('reactions_body'); + const modal_title = document.getElementById('reactions_title'); + const modal_action = document.getElementById('reactions_action'); + modal_action.style.display = 'none'; + modal_title.innerHTML = obj.title; + modal_content.innerHTML = ''; + if (obj.action) { + modal_action.innerHTML = '<a href="#" onclick="' + obj.action + '(' + id + ',\'' + verb + '\'); return false;">' + obj.action_label + '</a>'; + modal_action.style.display = 'block'; + } + console.log(obj) + obj.result.forEach(e => { + let mod = ''; + if (e.item_blocked === 4) { + mod = '<span onclick="moderate_approve(' + e.id + '); return false;" class="text-success pe-4 d-inline-block"><i class="bi bi-check-lg" ></i></span><span onclick="moderate_drop(' + e.id + '); return false;" class="text-danger pe-4 d-inline-block"><i class="bi bi-trash" ></i></span>'; + } + modal_content.innerHTML += '<a href="' + e.url + '" class="list-group-item list-group-item-action border-0">' + mod + '<img src="' + e.photo + '" class="menu-img-1" loading="lazy"> ' + e.name + '</a>'; + + }); + + modal.show(); + loading.style.display = 'none'; + }) + .catch(error => { + console.error('Error fetching data:', error); + }); + } + +} + +function injectWithAnimation(containerId, parsedDoc, overwrite = false) { + const container = document.getElementById(containerId); + if (!container) return; + if (overwrite) container.innerHTML = ''; + + const newElements = Array.from(parsedDoc.body.children); + + for (let i = newElements.length - 1; i >= 0; i--) { + const el = newElements[i].cloneNode(true); + el.classList.add('item-fade-in'); + container.insertBefore(el, container.firstChild); + + // Remove classes after transition ends + const onTransitionEnd = (event) => { + el.classList.remove('item-fade-in', 'show'); + el.removeEventListener('transitionend', onTransitionEnd); + }; + el.addEventListener('transitionend', onTransitionEnd); + + setTimeout(() => { + el.classList.add('show'); + }, (newElements.length - 1 - i) * 30); + } +} + +const autoExpand = (function () { + const clickedElements = new Set(); // Stores clicked button references + + // We wait 10 seconds for images. Set the timeout here slightly higher. + function waitForElement(selector, timeout = 11000) { + return new Promise((resolve, reject) => { + // Check if the element already exists + const element = document.querySelector(selector); + + if (element) { + resolve(element); + return; + } + + // Set up a timeout to reject the promise if the element doesn't appear in time + const timer = setTimeout(() => { + observer.disconnect(); + reject(new Error(`Element "${selector}" not found within ${timeout}ms`)); + }, timeout); + + // Create a MutationObserver to watch for DOM changes + const observer = new MutationObserver(() => { + const el = document.querySelector(selector); + if (el) { + clearTimeout(timer); + observer.disconnect(); + resolve(el); + } + }); + + // Start observing the document for changes + observer.observe(document.documentElement, { + childList: true, + subtree: true + }); + }); + } + + async function autoExpand(id) { + const loading = document.getElementById('like-rotator-' + id); + let iteration = 0; + const maxIterations = 3; + clickedElements.clear(); + + try { + // Step 1: Ensure initial button is clicked + const initBtnSelector = '#wall-item-comment-' + id; + const initBtn = await waitForElement(initBtnSelector); + + if (!clickedElements.has(initBtn)) { + initBtn.click(); + clickedElements.add(initBtn); + iteration++; + } + + // Step 2: Loop until no new buttons are found + let newButtonsFound; + + const commentSelector = `#wall-item-sub-thread-wrapper-${id} .thread-wrapper`; + const commentBtnSelector = `#wall-item-sub-thread-wrapper-${id} .wall-item-comment`; + + do { + newButtonsFound = false; + + // Wait for any comment to appear + await waitForElement(commentSelector); + + const expandButtons = document.querySelectorAll(commentBtnSelector); + + for (const btn of expandButtons) { + if (!clickedElements.has(btn)) { + btn.click(); + clickedElements.add(btn); + newButtonsFound = true; + // Optional: await waitForElement(...) to wait for new content + } + } + + // Wait between iterations to allow UI to update + if (newButtonsFound) { + iteration++; + await new Promise(res => setTimeout(res, 700)); + } + + } while (newButtonsFound && iteration < maxIterations); + + console.log('Replies loaded!'); + + loading.style.display = 'none'; + + document.dispatchEvent(new CustomEvent('hz:sse_setNotificationsStatus', { detail: b64mids })); + document.dispatchEvent(new Event('hz:sse_bs_counts')); + + } catch (error) { + loading.style.display = 'none'; + console.error("autoExpand failed:", error.message); + } + } + + return autoExpand; +})(); + + +function stringToHexColor(str) { + let hash = 0; + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + let color = "#"; + for (let i = 0; i < 3; i++) { + const value = (hash >> (i * 8)) & 0xFF; + color += value.toString(16).padStart(2, '0'); + } + return color; +} + +function stringToHslColor(str) { + let stringUniqueHash = [...str].reduce((acc, char) => { + return char.charCodeAt(0) + ((acc << 5) - acc); + }, 0); + return `hsl(${stringUniqueHash % 360}, 65%, 65%)`; +} + function dolike(ident, verb) { $('#like-rotator-' + ident).show(); @@ -1321,17 +1770,73 @@ function doprofilelike(ident, verb) { function doreply(parent, ident, owner, hint) { - var form = $('#comment-edit-form-' + parent.toString()); - 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="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")); - $('#comment-edit-text-' + parent.toString()).focus(); + const modal = new bootstrap.Modal('#reactions'); + const modal_content = document.getElementById('reactions_body'); + const modal_title = document.getElementById('reactions_title'); + const modal_action = document.getElementById('reactions_action'); + + modal_action.style.display = 'none'; + modal_title.innerHTML = hint; + + const preview = document.getElementById('comment-edit-preview-' + parent.toString()); + preview.innerHTML = ''; + + // Get the form element by ID + const form = document.getElementById('comment-edit-wrapper-' + parent.toString()); + if (!form) return; + + modal_content.innerHTML = ''; + modal_content.append(form); + + // Set the value of the input named 'parent' + const parentInput = form.querySelector('input[name=parent]'); + if (parentInput) { + parentInput.value = ident; + } + + // Find the submit button and update its HTML + const submitBtn = form.querySelector('button[type=submit]'); + if (submitBtn) { + const btnText = submitBtn.innerHTML.replace(/<[^>]*>/g, '').trim(); + submitBtn.innerHTML = '<i class="bi bi-arrow-90deg-left"></i> ' + btnText; + } + + // Prepare the quote logic + const sel = 'wall-item-body-' + ident.toString(); + const quote = window.getSelection().toString().trim(); + + // Check if the selection is inside the correct element + let isInSel = false; + const anchorNode = window.getSelection().anchorNode; + if (anchorNode) { + let node = anchorNode.nodeType === 3 ? anchorNode.parentNode : anchorNode; + while (node) { + if (node.id === sel) { + isInSel = true; + break; + } + node = node.parentNode; + } + } + + modal.show(); + + // Set the textarea value + const textarea = form.querySelector('textarea'); + if (textarea) { + let commentBody = localStorage.getItem('comment_body-' + ident); + if (commentBody) { + textarea.value = commentBody; + } + else { + textarea.value = "@{" + owner + "}" + ((!isInSel || quote.length === 0) ? " " : "\n[quote]" + quote + "[/quote]\n"); + } + + textarea.focus(); + } } + function doscroll(parent, hidden) { var id; var x = '#hide-comments-outer-' + hidden.toString(); @@ -1345,6 +1850,7 @@ function doscroll(parent, hidden) { var c = '#collapsed-comments-' + x; if($(c).length !== 0 && (! $(c).is(':visible'))) { showHideComments(x); + collapseHeight(); pos += $(c).height(); } } @@ -1542,11 +2048,13 @@ function post_comment(id) { window.location.href = data.reload; } + close_modal(); localStorage.removeItem("comment_body-" + 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-sub-thread-wrapper-' + data.thr_parent_id).append(data.html); + updateRelativeTime('.autotime'); $('body').css('cursor', 'unset'); collapseHeight(); |