inherit
6871
0
Jun 10, 2024 2:25:35 GMT -8
bigballofyarn
"If you wish to make an apple pie from scratch, you must first invent the universe." -Carl Sagan
7,886
January 2003
bigballofyarn
|
Post by bigballofyarn on Oct 23, 2024 11:09:43 GMT -8
dustys , Chris' plugin doesn't operate the same way as the other one. Does this picture help you understand how the plugin operates? No, don't save the global footer code if you don't intend to use it.
|
|
inherit
Official Code Helper
65613
0
1
Oct 22, 2024 1:56:19 GMT -8
Chris
"'Oops' is the sound we make when we improve"
9,017
December 2005
horace
RedBassett's Mini-Profile
|
Post by Chris on Oct 23, 2024 12:25:48 GMT -8
This message has been moved to Geocities by Chris . Update:Chris , The only issue noted in 10 minutes of testing is that if a person is inclined to double/triple click to highlight a sentence rather than scroll with their mouse, it will break the quote. There are also the menus that browsers show on their own when you highlight text, which can appear under or over the quote button, sometimes making it appear like the quote button is there twice. bigballofyarn.proboards.com/thread/70502/quote-highlighted-test?page=1&scrollTo=1336112 You're seeing the quote button twice because both the plugin and the global header code are running. The header code is meant to replace and supersede the plugin because the plugin is not editable. Double-click was working fine, and it could simply be the two buttons competing. Disable the plugin and see if that is the issue (you'll need to recopy the header code since there was an errant semicolon error that was corrected when scrollIntoView was added). Edit:
The above images from my original post * show both the plugin and the header code enabled, running, and conflicting with each other (see console for errors). I just checked again and I still see the original plugin enabled. presumably
|
|
inherit
6871
0
Jun 10, 2024 2:25:35 GMT -8
bigballofyarn
"If you wish to make an apple pie from scratch, you must first invent the universe." -Carl Sagan
7,886
January 2003
bigballofyarn
|
Post by bigballofyarn on Oct 23, 2024 13:52:10 GMT -8
The plugin is not enabled. Neither is yours. Perhaps you happened to look in the ten minutes I was back and forth between the two. I am not home and did not make any changes to update 2. Even with the plugin disabled, people cannot click to select and quote. Edit: You are free to test in the guest thread. bigballofyarn.proboards.com/thread/17680/guest-chat?page=28
|
|
inherit
Official Code Helper
65613
0
1
Oct 22, 2024 1:56:19 GMT -8
Chris
"'Oops' is the sound we make when we improve"
9,017
December 2005
horace
RedBassett's Mini-Profile
|
Post by Chris on Oct 23, 2024 15:42:09 GMT -8
This message has been moved to Geocities by Chris . I'm seeing the code in the footer instead of the header and missing quite a few updates as you've mentioned, especially the update geared toward the double and triple-clickers. Also, notice that the <dialog> now precedes the script on newer releases to ensure proper reference when multiple dialogs bearing the same class are on the page (e.g. when plugin and script are both enabled). <dialog class="quick-quote-div" style="/*display: none;*/margin:0; border: grey solid 1px; border-radius: 5px; opacity: 0.8; padding: 5px; background-color: white;"> <form method="dialog"> <input name="quote" value="Quick Quote" type="submit" class="ui-button quick-quote-button" autofocus > </form> </dialog> <!-- Quick Quotes (UPDATED Oct 23, 2024 @ 1729681002992) --> <script> (() => { var isIE = document.all; var mouseX = 0; var mouseY = 0;
function getMouseXY(e) { if (!e) e = window.event; if (e) { mouseX = isIE ? (e.clientX + document.body.scrollLeft) : e.pageX; mouseY = isIE ? (e.clientY + document.body.scrollTop) : e.pageY; } }
document.addEventListener('mousemove', getMouseXY, true); htm_specials_tags = { "remove": [ '.quote_clear', '.quote_header', '.quote_avatar_container', '.spoiler_header' ], "unwrap": [ '.quote_body' ], "replace":[ ['div.quote','className'], ['div.spoiler[id]', 'data-tag'], ['iframe[src*="youtube.com"]','','video'] ] } function cleanupHTML(htm){ const container = $('<div></div>').html(htm); $('' + htm_specials_tags['remove'], container).remove() $('' + htm_specials_tags['unwrap'], container).each((i,e)=>{$(e).contents().unwrap()}); for(let j =0, tag = htm_specials_tags['replace'][0]; j < htm_specials_tags['replace'].length; tag = htm_specials_tags['replace'][++j]){ $(tag[0],container).each((i,e)=>{ let n = e[tag[1]]? $(`<${e[tag[1]]}>${e.innerHTML}</${e[tag[1]]}>`) : (tag[2]? $(`<${tag[2]}>${e.innerHTML}</${tag[2]}>`):$()); if(n.length){ for(const t of e.attributes)n.attr(t.name,t.value); $(e).replaceWith(n); } }); } return container.html() }
function getSelectionHtml() { var html = ""; if (typeof window.getSelection != "undefined") { var sel = window.getSelection(); if ($(sel.anchorNode).parents('.message').is($(sel.focusNode).parents('.message')) && sel.rangeCount) { if($(sel.anchorNode).parents('.quote').is($(sel.focusNode).parents('.quote'))){ quotequote=$(sel.focusNode).parents('.quote'); }else{ quotequote=null;} var container = document.createElement("div"); for (var i = 0, len = sel.rangeCount; i < len; ++i) { container.appendChild(sel.getRangeAt(i).cloneContents()); } html = container.innerHTML; } } else if (typeof document.selection != "undefined") { if (document.selection.type == "Text") { html = document.selection.createRange().htmlText; } } return cleanupHTML(html); }
var messageIDnum, messageIDsliced, messageAuthor, messageTimestamp, messageNew, quoteText, quotequote;
getSelectionHtml.mouseup = function (event) { var htmlSelection = getSelectionHtml(); getSelectionHtml.mouseup.timeout && clearTimeout(getSelectionHtml.mouseup.timeout) quoteText = htmlSelection.replace(/>/g, "]"); quoteText = quoteText.replace(/</g, "["); if ($('.unblocked .message:hover').length != 0) {
if (htmlSelection != '') { getSelectionHtml.mouseup.timeout = setTimeout(function () { $(".quick-quote-div").css({ position: "absolute", top: mouseY, left: mouseX }); $(".quick-quote-div")[0].showModal(); setTimeout(function () { if ($('.quick-quote-div:hover').length == 0) { $('.quick-quote-div')[0].close() htmlSelection = '' quoteText = '' } }, 2500)
}, 600); if(quotequote){ messageNew = `[quote author="${$(quotequote).attr('author')}" source="${$(quotequote).attr('source')}" timestamp="${$(quotequote).attr('timestamp')}"]${quoteText}[/quote]` }else{ messageIDnum = $('.post:hover').attr('id'); messageIDsliced = messageIDnum.substr(messageIDnum.lastIndexOf("-") + 1); messageAuthor = $('.post:hover .mini-profile').find('.user-link').attr('title') || $('.post:hover .mini-profile').find('[itemtype$="/Person"] span[itemprop="name"]').text(); messageTimestamp = $('.post:hover .info').find('abbr:first').attr('data-timestamp'); messageTimestamp = messageTimestamp.substring(0, messageTimestamp.length - 3); messageNew = '[quote author="' + messageAuthor + '" source="/post/' + messageIDsliced + '/thread" timestamp="' + messageTimestamp + '"]' + quoteText + '[/quote]' }
} } }
$('.quick-quote-button').click(function () { if (quoteText != '') { pb.data('quick_reply') ? $('.quick-reply textarea').replaceSelection(messageNew + "\n")[0].scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'smooth' }) : $('<form></form>', { method: 'POST', action: proboards.route('new_post', { thread_id: pb.item('thread', pb.item('post', +messageIDsliced)['thread_id']).id }) }) .append($('<input>', { name: 'quick_message' }).val(messageNew)) .append($('<input>', { name: 'csrf_token' }).val(proboards.data("csrf_token") || "null")) .appendTo('body').attr('id', 'quick_form'), setTimeout(function () { pb.data('quick_reply') && $('.quick-reply textarea')[0].focus(); $('#quick_form').submit() }, 500); htmlSelection = quoteText = ''; $('.quick-quote-div')[0].close(); } });
$(document).ready(function () {
$(document).bind("mouseup", getSelectionHtml.mouseup); $('.quick-quote-div').on('click', (event) => { event.target.tagName == 'DIALOG' && event.target.close(); })
});
})(); /** UPDATES: - encapsulate to avoid global variables getting overwritten - switched to <dialog> for top-layer treatment - used jQuery.fn.replaceSelection to insert at caret position in quick reply - look for timestamp only in .content > .info - search mini-profile only for author - support quoting guest posts - scroll quick reply into view and set focus on typing area - redirect to full reply if no quick reply is available - ignore selections that are outbounds of the post content - moved button click handler out of selection handler to avoid duplicate or multiple quotes on a single click - properly cite nested quotes and add logic to convert them back to BBCode - delayed button popup to allow for triple-click selections - made BBCode convertor expandable and added spoilers to the list of tags that require special treatment - added youtube to specials converter **/ </script>
/** UPDATES: - encapsulate to avoid global variables getting overwritten - switched to <dialog> for top-layer treatment - used jQuery.fn.replaceSelection to insert at caret position in quick reply - look for timestamp only in .content > .info - search mini-profile only for author - support quoting guest posts - scroll quick reply into view and set focus on typing area - redirect to full reply if no quick reply is available - ignore selections that are out of bounds of the post content - moved button click handler out of selection handler to avoid duplicate or multiple quotes on a single click - properly cite nested quotes and add logic to convert them back to BBCode - delayed button popup to allow for triple-click selections - made BBCode convertor expandable and added spoilers to the list of tags that require special treatment - added youtube to specials converter **/ Also, I'm building a list of HTML elements that need special treatment to return to their BBCode counterparts. It still won't be perfect, but it will be an improvement. htm_specials_tags = { "remove": [ '.quote_clear', '.quote_header', '.quote_avatar_container', '.spoiler_header' ], "unwrap": [ '.quote_body' ], "replace":[ /* [selector, attribute containing bbcode tagname, or static tagname] ['div.quote','className'], ['div.spoiler[id]', 'data-tag'], ['iframe[src*="youtube.com"]','','video'] ] } And thanks for getting me some much-needed feedback so this could move forward bigballofyarn 😁👍 (I am still trying to get in contact with David to see if this plugin can be given an open-source license or at least a designated caretaker so modernizations can actually be merged into the plugin itself)
|
|
inherit
6871
0
Jun 10, 2024 2:25:35 GMT -8
bigballofyarn
"If you wish to make an apple pie from scratch, you must first invent the universe." -Carl Sagan
7,886
January 2003
bigballofyarn
|
Post by bigballofyarn on Oct 23, 2024 15:58:15 GMT -8
Chris , I'm happy to be a helpful annoyance. Haha. I approved your guest post. Let me know if I'm missing an update. I thought I added everything. I moved the code to the global headers. People are still having weird issues when they try to click to select. bigballofyarn.proboards.com/thread/70502/quote-highlighted-test?page=2&scrollTo=1336362It's conceivable I put something in the incorrect place. I'm not as masterful a coder at all. This is what I have in my header: <!-- Quick Quotes (UPDATED Oct 23, 2024) --> <script> (()=>{ var isIE = document.all; var mouseX = 0; var mouseY = 0;
function getMouseXY(e) { if (!e) e = window.event; if (e) { mouseX = isIE ? (e.clientX + document.body.scrollLeft) : e.pageX; mouseY = isIE ? (e.clientY + document.body.scrollTop) : e.pageY; } }
//document.onmousemove = getMouseXY; document.addEventListener('mousemove', getMouseXY, true)
function getSelectionHtml() { var html = ""; if (typeof window.getSelection != "undefined") { var sel = window.getSelection(); if (sel.rangeCount) { var container = document.createElement("div"); for (var i = 0, len = sel.rangeCount; i < len; ++i) { container.appendChild(sel.getRangeAt(i).cloneContents()); } html = container.innerHTML; } } else if (typeof document.selection != "undefined") { if (document.selection.type == "Text") { html = document.selection.createRange().htmlText; } } return html; }
getSelectionHtml.mouseup = function () { var htmlSelection = getSelectionHtml();
var quoteText = htmlSelection.replace(/>/g, "]"); var quoteText = quoteText.replace(/</g, "["); if ($('.unblocked .message:hover').length != 0) {
if (htmlSelection != '') {
$(".quick-quote-div").css({ position: "absolute", top: mouseY, left: mouseX }); $(".quick-quote-div")[0].showModal() //.css("display", "inline"); var messageIDnum = $('.post:hover').attr('id'); var messageIDsliced = messageIDnum.substr(messageIDnum.lastIndexOf("-") + 1); var messageAuthor = $('.post:hover .mini-profile').find('.user-link').attr('title') || $('.post:hover .mini-profile').find('[itemtype$="/Person"] span[itemprop="name"]').text(); var messageTimestamp = $('.post:hover .info').find('abbr:first').attr('data-timestamp'); messageTimestamp = messageTimestamp.substring(0, messageTimestamp.length - 3); var messageNew = '[quote author="' + messageAuthor + '" source="/post/' + messageIDsliced + '/thread" timestamp="' + messageTimestamp + '"]' + quoteText + '[/quote]'
setTimeout(function () { if ($('.quick-quote-div:hover').length == 0) { $('.quick-quote-div')[0].close() //.css({"display":"none"}); htmlSelection = '' quoteText = '' } }, 2500)
$('.quick-quote-button').click(function () { if (quoteText != '') { pb.data('quick_reply') ? $('.quick-reply textarea').replaceSelection(messageNew + "\n")[0].scrollIntoView({block:'start',inline:'nearest',behavior:'smooth'}) : $('<form></form>',{method:'POST',action:proboards.route('new_post',{thread_id:pb.item('thread', pb.item('post', +messageIDsliced)['thread_id']).id})}) .append($('<input>',{name:'quick_message'}).val(messageNew)) .append('<input>',{name:'csrf_token', value: proboards.data("csrf_token") || "null"}) .appendTo('body').attr('id','quick_form'), setTimeout(function(){$('.quick-reply textarea')[0].focus();$('#quick_form').submit()},500); htmlSelection = '' quoteText = ''; $('.quick-quote-div')[0].close() } });
} } }
$(document).ready(function () {
$(document).bind("mouseup", getSelectionHtml.mouseup); $('.quick-quote-div').on('click', (event) => { event.target.tagName == 'DIALOG' && event.target.close(); })
});
htm_specials_tags = { "remove": [ '.quote_clear', '.spoiler_header' ], "unwrap": [ '.quote_body' ], "replace":[ ['div.quote','className'], ['div.spoiler[id]', 'data-tag'] ] } function cleanupHTML(htm){ const container = $('<div></div>').html(htm); $('' + htm_specials_tags['remove'], container).remove() $('' + htm_specials_tags['unwrap'], container).each((i,e)=>{$(e).contents().unwrap()}); for(let j =0, tag = htm_specials_tags['replace'][0]; j < htm_specials_tags['replace'].length; tag = htm_specials_tags['replace'][++j]){ $(tag[0],container).each((i,e)=>{ let n = $(`<${e[tag[1]]}>${e.innerHTML}</${e[tag[1]]}>`); for(const t of e.attributes)n.attr(t.name,t.value); $(e).replaceWith(n); }); } return container.html() }
})(); /** UPDATES: - encapsulate to avoid global variables getting overwritten - switched to <dialog> element for the top-layer treatment - used jQuery.fn.replaceSelection to insert at caret position in quick reply - look for timestamp only in post .info not entire post - search only mini-profile for author data not entire post - support correctly citing guest posts by also looking for [itemprop="name"] - added test for quick reply and redirect to full reply if not present **/ </script> <dialog class="quick-quote-div" style="/*display: none;*/margin:0; border: grey solid 1px; border-radius: 5px; opacity: 0.8; padding: 5px; background-color: white;"> <form method="dialog"> <input name="quote" value="Quick Quote" type="submit" class="ui-button quick-quote-button" autofocus > </form> </dialog>
|
|
inherit
Official Code Helper
65613
0
1
Oct 22, 2024 1:56:19 GMT -8
Chris
"'Oops' is the sound we make when we improve"
9,017
December 2005
horace
RedBassett's Mini-Profile
|
Post by Chris on Oct 23, 2024 16:32:59 GMT -8
This message has been moved to Geocities by Chris . bigballofyarn that is an "outdated" code relatively speaking given that the last update to that code you currently added had to do with " - added test for quick reply and redirect to full reply if not present". If you look at the spoiler in my last post you'll see there have been at least seven updates since then (most of which were addressing concerns that were brought up by testers on your forum) <dialog class="quick-quote-div" style="/*display: none;*/margin:0; border: grey solid 1px; border-radius: 5px; opacity: 0.8; padding: 5px; background-color: white;"> <form method="dialog"> <input name="quote" value="Quick Quote" type="submit" class="ui-button quick-quote-button" autofocus > </form> </dialog> <!-- Quick Quotes (UPDATED Oct 23, 2024 @ 1729681002992) --> <script> (() => { var isIE = document.all; var mouseX = 0; var mouseY = 0;
function getMouseXY(e) { if (!e) e = window.event; if (e) { mouseX = isIE ? (e.clientX + document.body.scrollLeft) : e.pageX; mouseY = isIE ? (e.clientY + document.body.scrollTop) : e.pageY; } }
document.addEventListener('mousemove', getMouseXY, true); htm_specials_tags = { "remove": [ '.quote_clear', '.quote_header', '.quote_avatar_container', '.spoiler_header' ], "unwrap": [ '.quote_body' ], "replace":[ ['div.quote','className'], ['div.spoiler[id]', 'data-tag'], ['iframe[src*="youtube.com"]','','video'] ] } function cleanupHTML(htm){ const container = $('<div></div>').html(htm); $('' + htm_specials_tags['remove'], container).remove() $('' + htm_specials_tags['unwrap'], container).each((i,e)=>{$(e).contents().unwrap()}); for(let j =0, tag = htm_specials_tags['replace'][0]; j < htm_specials_tags['replace'].length; tag = htm_specials_tags['replace'][++j]){ $(tag[0],container).each((i,e)=>{ let n = e[tag[1]]? $(`<${e[tag[1]]}>${e.innerHTML}</${e[tag[1]]}>`) : (tag[2]? $(`<${tag[2]}>${e.innerHTML}</${tag[2]}>`):$()); if(n.length){ for(const t of e.attributes)n.attr(t.name,t.value); $(e).replaceWith(n); } }); } return container.html() }
function getSelectionHtml() { var html = ""; if (typeof window.getSelection != "undefined") { var sel = window.getSelection(); if ($(sel.anchorNode).parents('.message').is($(sel.focusNode).parents('.message')) && sel.rangeCount) { if($(sel.anchorNode).parents('.quote').is($(sel.focusNode).parents('.quote'))){ quotequote=$(sel.focusNode).parents('.quote'); }else{ quotequote=null;} var container = document.createElement("div"); for (var i = 0, len = sel.rangeCount; i < len; ++i) { container.appendChild(sel.getRangeAt(i).cloneContents()); } html = container.innerHTML; } } else if (typeof document.selection != "undefined") { if (document.selection.type == "Text") { html = document.selection.createRange().htmlText; } } return cleanupHTML(html); }
var messageIDnum, messageIDsliced, messageAuthor, messageTimestamp, messageNew, quoteText, quotequote;
getSelectionHtml.mouseup = function (event) { var htmlSelection = getSelectionHtml(); getSelectionHtml.mouseup.timeout && clearTimeout(getSelectionHtml.mouseup.timeout) quoteText = htmlSelection.replace(/>/g, "]"); quoteText = quoteText.replace(/</g, "["); if ($('.unblocked .message:hover').length != 0) {
if (htmlSelection != '') { getSelectionHtml.mouseup.timeout = setTimeout(function () { $(".quick-quote-div").css({ position: "absolute", top: mouseY, left: mouseX }); $(".quick-quote-div")[0].showModal(); setTimeout(function () { if ($('.quick-quote-div:hover').length == 0) { $('.quick-quote-div')[0].close() htmlSelection = '' quoteText = '' } }, 2500)
}, 600); if(quotequote){ messageNew = `[quote author="${$(quotequote).attr('author')}" source="${$(quotequote).attr('source')}" timestamp="${$(quotequote).attr('timestamp')}"]${quoteText}[/quote]` }else{ messageIDnum = $('.post:hover').attr('id'); messageIDsliced = messageIDnum.substr(messageIDnum.lastIndexOf("-") + 1); messageAuthor = $('.post:hover .mini-profile').find('.user-link').attr('title') || $('.post:hover .mini-profile').find('[itemtype$="/Person"] span[itemprop="name"]').text(); messageTimestamp = $('.post:hover .info').find('abbr:first').attr('data-timestamp'); messageTimestamp = messageTimestamp.substring(0, messageTimestamp.length - 3); messageNew = '[quote author="' + messageAuthor + '" source="/post/' + messageIDsliced + '/thread" timestamp="' + messageTimestamp + '"]' + quoteText + '[/quote]' }
} } }
$('.quick-quote-button').click(function () { if (quoteText != '') { pb.data('quick_reply') ? $('.quick-reply textarea').replaceSelection(messageNew + "\n")[0].scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'smooth' }) : $('<form></form>', { method: 'POST', action: proboards.route('new_post', { thread_id: pb.item('thread', pb.item('post', +messageIDsliced)['thread_id']).id }) }) .append($('<input>', { name: 'quick_message' }).val(messageNew)) .append($('<input>', { name: 'csrf_token' }).val(proboards.data("csrf_token") || "null")) .appendTo('body').attr('id', 'quick_form'), setTimeout(function () { pb.data('quick_reply') && $('.quick-reply textarea')[0].focus(); $('#quick_form').submit() }, 500); htmlSelection = quoteText = ''; $('.quick-quote-div')[0].close(); } });
$(document).ready(function () {
$(document).bind("mouseup", getSelectionHtml.mouseup); $('.quick-quote-div').on('click', (event) => { event.target.tagName == 'DIALOG' && event.target.close(); })
});
})(); /** UPDATES: - encapsulate to avoid global variables getting overwritten - switched to <dialog> for top-layer treatment - used jQuery.fn.replaceSelection to insert at caret position in quick reply - look for timestamp only in .content > .info - search mini-profile only for author - support quoting guest posts - scroll quick reply into view and set focus on typing area - redirect to full reply if no quick reply is available - ignore selections that are outbounds of the post content - moved button click handler out of selection handler to avoid duplicate or multiple quotes on a single click - properly cite nested quotes and add logic to convert them back to BBCode - delayed button popup to allow for triple-click selections - made BBCode convertor expandable and added spoilers to the list of tags that require special treatment - added youtube to specials converter **/ </script>
/** UPDATES: - encapsulate to avoid global variables getting overwritten - switched to <dialog> for top-layer treatment - used jQuery.fn.replaceSelection to insert at caret position in quick reply - look for timestamp only in .content > .info - search mini-profile only for author - support quoting guest posts - scroll quick reply into view and set focus on typing area - redirect to full reply if no quick reply is available - ignore selections that are out of bounds of the post content - moved button click handler out of selection handler to avoid duplicate or multiple quotes on a single click - properly cite nested quotes and add logic to convert them back to BBCode - delayed button popup to allow for triple-click selections - made BBCode convertor expandable and added spoilers to the list of tags that require special treatment - added youtube to specials converter **/
|
|
inherit
6871
0
Jun 10, 2024 2:25:35 GMT -8
bigballofyarn
"If you wish to make an apple pie from scratch, you must first invent the universe." -Carl Sagan
7,886
January 2003
bigballofyarn
|
Post by bigballofyarn on Oct 23, 2024 16:43:32 GMT -8
Chris , I seem to miss spoilers in posts for some reason. My eyes gloss over them. I've added the code in the spoiler from 13 hours ago in place of the one I was using. What I have now is text that can be selected, but no "quote" button appearing. If I select text by dragging, the quote button appears. If I double/triple click to select a sentence, the button does not appear.
|
|
inherit
Official Code Helper
65613
0
1
Oct 22, 2024 1:56:19 GMT -8
Chris
"'Oops' is the sound we make when we improve"
9,017
December 2005
horace
RedBassett's Mini-Profile
|
Post by Chris on Oct 23, 2024 16:53:29 GMT -8
This message has been moved to Geocities by Chris . I confirm triple and double not working although working on two other forums...investigating further...
Edit: OK, I still could not determine why the selections on that particular forum would be so broad (e.g., selection on a textNode has the anchorNode as the textNode (as expected) but the focusNode is for whatever reason trying to go beyond the bounds of the post. On other forums both anchorNode and focusNode would be the same textNode since that is the only node of any relevance. I suspect either the dice or eightball plugins since they both have selection manipulation algorithms and have already ruled out the BBCode Buttons plugin. In any event, switching the algorithm that checks post boundaries from using parents to using closest should partially address the issue, and instead of trying to find the needle in the haystack, I've decided to adjust the selection to fit within the confines of the post should it try to extend beyond the boundaries of the post. This applies to the tail end of the selection (focusNode). If the start of the selection (anchorNode) begins outside the bounds of the post, then that is a try-again situation. There are also THREE copies of the <dialog> accompanying this code now living in your header. I'd suggest thoroughly cleaning it out and then putting the latest code listed below in there <!-- Quick Quotes (UPDATED Oct 24, 2024 @ 1729754075134) -->
<dialog class="quick-quote-div" style="margin:0; border: grey solid 1px; border-radius: 5px; opacity: 0.8; padding: 5px; background-color: white;"> <form method="dialog"> <input name="quote" value="Quick Quote" type="submit" class="ui-button quick-quote-button" autofocus > </form> </dialog>
<script> (() => { var isIE = document.all; var mouseX = 0; var mouseY = 0;
function getMouseXY(e) { if (!e) e = window.event; if (e) { mouseX = isIE ? (e.clientX + document.body.scrollLeft) : e.pageX; mouseY = isIE ? (e.clientY + document.body.scrollTop) : e.pageY; } }
document.addEventListener('mousemove', getMouseXY, false); htm_specials_tags = { "remove": [ '.quote_clear', '.quote_header', '.quote_avatar_container', '.spoiler_header' ], "unwrap": [ '.quote_body' ], "replace":[ ['div.quote','className'], ['div.spoiler[id]', 'data-tag'], ['iframe[src*="youtube.com"]','','video'] ] } function cleanupHTML(htm){ const container = $('<div></div>').html(htm); $('' + htm_specials_tags['remove'], container).remove() $('' + htm_specials_tags['unwrap'], container).each((i,e)=>{$(e).contents().unwrap()}); for(let j =0, tag = htm_specials_tags['replace'][0]; j < htm_specials_tags['replace'].length; tag = htm_specials_tags['replace'][++j]){ $(tag[0],container).each((i,e)=>{ let n = e[tag[1]]? $(`<${e[tag[1]]}>${e.innerHTML}</${e[tag[1]]}>`) : (tag[2]? $(`<${tag[2]}>${e.innerHTML}</${tag[2]}>`):$()); if(n.length){ for(const t of e.attributes)n.attr(t.name,t.value); $(e).replaceWith(n); } }); } return container.html() }
function getSelectionHtml() { var html = ""; if (typeof window.getSelection != "undefined") { var sel = window.getSelection(); if ($(sel.anchorNode).closest('.message').length && sel.rangeCount) { if($(sel.anchorNode).closest('.quote').is($(sel.focusNode).closest('.quote'))){ quotequote=$(sel.focusNode).parents('.quote'); }else{ quotequote=null; if($(sel.focusNode).closest('.message').length == 0){ sel.extend($(sel.anchorNode).closest('.quote')[0],$(sel.anchorNode).closest('.quote').contents().length) } } var container = document.createElement("div"); for (var i = 0, len = sel.rangeCount; i < len; ++i) { container.appendChild(sel.getRangeAt(i).cloneContents()); } html = container.innerHTML; } } else if (typeof document.selection != "undefined") { if (document.selection.type == "Text") { html = document.selection.createRange().htmlText; } } return cleanupHTML(html); }
var messageIDnum, messageIDsliced, messageAuthor, messageTimestamp, messageNew, quoteText, quotequote;
getSelectionHtml.mouseup = function (event) { var htmlSelection = getSelectionHtml(); getSelectionHtml.mouseup.timeout && clearTimeout(getSelectionHtml.mouseup.timeout) quoteText = htmlSelection.replace(/>/g, "]"); quoteText = quoteText.replace(/</g, "["); if ($('.unblocked .message:hover').length != 0) {
if (htmlSelection != '') { getSelectionHtml.mouseup.timeout = setTimeout(function () { $(".quick-quote-div").css({ position: "absolute", top: mouseY, left: mouseX }); $(".quick-quote-div")[0].showModal(); setTimeout(function () { if ($('.quick-quote-div:hover').length == 0) { $('.quick-quote-div')[0].close() htmlSelection = '' quoteText = '' } }, 2500)
}, 600); if(quotequote){ messageNew = `[quote author="${$(quotequote).attr('author')}" source="${$(quotequote).attr('source')}" timestamp="${$(quotequote).attr('timestamp')}"]${quoteText}[/quote]` }else{ messageIDnum = $('.post:hover').attr('id'); messageIDsliced = messageIDnum.substr(messageIDnum.lastIndexOf("-") + 1); messageAuthor = $('.post:hover .mini-profile').find('.user-link').attr('title') || $('.post:hover .mini-profile').find('[itemtype$="/Person"] span[itemprop="name"]').text(); messageTimestamp = $('.post:hover .info').find('abbr:first').attr('data-timestamp'); messageTimestamp = messageTimestamp.substring(0, messageTimestamp.length - 3); messageNew = '[quote author="' + messageAuthor + '" source="/post/' + messageIDsliced + '/thread" timestamp="' + messageTimestamp + '"]' + quoteText + '[/quote]' }
} } }
$('.quick-quote-button').click(function () { if (quoteText != '') { pb.data('quick_reply') ? $('.quick-reply textarea').replaceSelection(messageNew + "\n")[0].scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'smooth' }) : $('<form></form>', { method: 'POST', action: proboards.route('new_post', { thread_id: pb.item('thread', pb.item('post', +messageIDsliced)['thread_id']).id }) }) .append($('<input>', { name: 'quick_message' }).val(messageNew)) .append($('<input>', { name: 'csrf_token' }).val(proboards.data("csrf_token") || "null")) .appendTo('body').attr('id', 'quick_form'), setTimeout(function () { pb.data('quick_reply') && $('.quick-reply textarea')[0].focus(); $('#quick_form').submit() }, 500); htmlSelection = quoteText = ''; $('.quick-quote-div')[0].close(); } });
$(document).ready(function () {
$(document).bind("mouseup", getSelectionHtml.mouseup); $('.quick-quote-div').on('click', (event) => { event.target.tagName == 'DIALOG' && event.target.close(); })
});
})(); /** UPDATES: - encapsulate to avoid global variables getting overwritten - switched to <dialog> for top-layer treatment - used jQuery.fn.replaceSelection to insert at caret position in quick reply - look for timestamp only in .content > .info - search mini-profile only for author - support quoting guest posts - scroll quick reply into view and set focus on typing area - redirect to full reply if no quick reply is available - ignore selections that are outbounds of the post content - moved button click handler out of selection handler to avoid duplicate or multiple quotes on a single click - properly cite nested quotes and add logic to convert them back to BBCode - delayed button popup to allow for triple-click selections - made BBCode convertor expandable and added spoilers to the list of tags that require special treatment - added youtube to specials converter - switched from parents to closest in boundaries test and moved focusNode if necessary **/ </script>
|
|
inherit
6871
0
Jun 10, 2024 2:25:35 GMT -8
bigballofyarn
"If you wish to make an apple pie from scratch, you must first invent the universe." -Carl Sagan
7,886
January 2003
bigballofyarn
|
Post by bigballofyarn on Oct 24, 2024 1:32:44 GMT -8
Chris , That's interesting. The 8 Ball game is something my boyfriend and I created just for my forum. The dice game came from the plugin library, but both are only visible in the "Forum Games" board. I guess I wouldn't have expected those plugins to affect anything outside of that board. Granted, they are probably still "running" in every board on some level, even if they are invisible. I have updated my headers and I will have some people do some testing. All your guest posts were also approved if you need to see them. Edit: People are doing their testing in the announcement thread: bigballofyarn.proboards.com/thread/70502/quote-highlighted-test?page=3The first "clickers" to test were successful. The rest are claiming that an entire block of text is being selected by clicking, that they are then clicking the "quote" button, but only one word is showing up in the final quote. However, no code is showing up in their replies. People have so far tested in Chrome, Opera, UR, and Brave. Edit 2: Now they claim that it's only bringing blank quotes to the quick reply. The change I made in between edit 1 and edit 2 was removing the extra <dialog> instances from the headers. Edit 3: Quotes seem to be working fine if people quote my original post, but it's not working properly for any of the replies. Edit 4: If needed, I can temporarily make "Forum Games" viewable to guests, but you won't be able to post in there.
|
|
inherit
Official Code Helper
65613
0
1
Oct 22, 2024 1:56:19 GMT -8
Chris
"'Oops' is the sound we make when we improve"
9,017
December 2005
horace
RedBassett's Mini-Profile
|
Post by Chris on Oct 24, 2024 18:12:48 GMT -8
This message has been moved to Geocities by Chris . bigballofyarn I made a mistake in the last edit, this line if($(sel.focusNode).closest('.message').length == 0){ sel.extend($(sel.anchorNode).closest('.quote')[0], $(sel.anchorNode).closest('.quote').contents().length) } should be targeting div.message not div.quote (which might not exist) so try changing it to if($(sel.focusNode).closest('.message').length == 0){ sel.extend($(sel.anchorNode).closest('.message')[0], $(sel.anchorNode).closest('.message').contents().length) } I suspect the reason why it's stopping at the second click and ignoring the third is because there's an error in the third mouseup event: "Failed to execute 'extend' on 'Selection': parameter 1 is not of type 'Node'." when it tries to resize a selection that goes beyond the bounds of a post.
In other news... - Added Google Drive embeds as a BBCode that can now be converted back from HTML hell
- Added support for headless quote conversions
- Now removes table wrapper prior to conversion
htm_specials_tags = { "remove": [ /* removes an element and its contents */ '.quote_clear', '.quote_header', '.quote_avatar_container', '.no_avatar_placeholder', '.spoiler_header' ], "unwrap": [ /* removes an element but keep its contents */ '.quote_body', '.o-table__display-wrapper', '.o-gdoc-embed__inner-wrapper', '.o-gdoc-embed' ], "replace":[ /* changes the tagName of an element but keeps its contents */ /*[CSSselector, attribute_containing_tagName, tagName_if_not_in_an_attribute]*/ ['div.quote','className'], ['div.spoiler[id]', 'data-tag'], ['iframe[src*="youtube.com"]','','video'], ['.o-gdoc-embed__iframe', '', 'gdoc'] ] } function cleanupHTML(htm){ if(htm==="")return htm; const container = $('<div></div>').html(htm); $('' + htm_specials_tags['remove'], container).remove() $('' + htm_specials_tags['unwrap'], container).each((i,e)=>{$(e).contents().unwrap()}); for(let j =0, tag = htm_specials_tags['replace'][0]; j < htm_specials_tags['replace'].length; tag = htm_specials_tags['replace'][++j]){ $(tag[0],container).each((i,e)=>{ let n = e[tag[1]]? $(`<${e[tag[1]]}>${e.innerHTML}</${e[tag[1]]}>`) : (tag[2]? $(`<${tag[2]}>${e.innerHTML}</${tag[2]}>`):$()); if(n.length){ for(const t of e.attributes)n.attr(t.name,t.value); $(e).replaceWith(n); } }); } return container.html() }
|
|
inherit
6871
0
Jun 10, 2024 2:25:35 GMT -8
bigballofyarn
"If you wish to make an apple pie from scratch, you must first invent the universe." -Carl Sagan
7,886
January 2003
bigballofyarn
|
Post by bigballofyarn on Oct 25, 2024 2:01:12 GMT -8
Chris , I've made your update. The triple clickers are reporting great results and full functionality. What's interesting is that I saw this thread by chance when someone else bumped it, thought the feature seemed interesting to test, and this is what became of it. Hopefully you aren't dreaming in code or anything because of all this testing. Your work is greatly appreciated. I'm almost surprised you didn't want to recreate the plugin rather than "fix" someone else's code in a sense. Whichever is easier for you is fine with me. Edit: I also moved all replies out of the guest thread and to the test thread should you need them. bigballofyarn.proboards.com/thread/20800/test-thread?page=24
|
|
inherit
Official Code Helper
65613
0
1
Oct 22, 2024 1:56:19 GMT -8
Chris
"'Oops' is the sound we make when we improve"
9,017
December 2005
horace
RedBassett's Mini-Profile
|
Post by Chris on Oct 25, 2024 2:46:57 GMT -8
This message has been moved to Geocities by Chris . <!-- Quick Quotes (UPDATED Oct 25, 2024 @ 1729857164545) -->
<dialog class="quick-quote-div" style="margin:0; border: grey solid 1px; border-radius: 5px; opacity: 0.8; padding: 5px; background-color: white;"> <form method="dialog"> <input name="quote" value="Quick Quote" type="submit" class="ui-button quick-quote-button" autofocus > </form> </dialog>
<script> (() => { var isIE = document.all; var mouseX = 0; var mouseY = 0;
function getMouseXY(e) { if (!e) e = window.event; if (e) { mouseX = isIE ? (e.clientX + document.body.scrollLeft) : e.pageX; mouseY = isIE ? (e.clientY + document.body.scrollTop) : e.pageY; } }
document.addEventListener('mousemove', getMouseXY, false); htm_specials_tags = { "remove": [ /* removes an element and its contents */ '.quote_clear', '.quote_header', '.quote_avatar_container', '.no_avatar_placeholder', '.spoiler_header' ], "unwrap": [ /* removes an element but keep its contents */ '.quote_body', '.o-table__display-wrapper', '.o-gdoc-embed__inner-wrapper', '.o-gdoc-embed' ], "empty": [ /* keeps an element but remove its contents */ '.pb-twitter-wrapper', '.fb_iframe_widget' ], "replace":[ /* changes the tagName of an element but keeps its contents */ /*[CSSselector, attribute_containing_tagName, tagName_if_not_in_an_attribute, [{rename_this_attribute:new_attribute_name}] ]*/ ['div.quote','className'], ['div.spoiler[id]', 'data-tag'], ['iframe[title^="YouTube video"]','','video'], ['iframe.o-gdoc-embed__iframe', '', 'gdoc'], ['iframe.pb-instagram', '', 'instagram'], ['.pb-twitter-wrapper', '', 'twitter'], ['.fb_iframe_widget', '', 'facebook', [{"data-href":"url"}]] ], "singletons":[ /* custom void tags that should not have a closing tag */ 'twitter', 'instagram', 'facebook' ] } function cleanupHTML(htm){ const container = $('<div></div>').html(htm); $('' + htm_specials_tags['remove'], container).remove(); $('' + htm_specials_tags['empty'], container).empty(); $('' + htm_specials_tags['unwrap'], container).each((i,e)=>{$(e).contents().unwrap()}); for(let j =0, tag = htm_specials_tags['replace'][0]; j < htm_specials_tags['replace'].length; tag = htm_specials_tags['replace'][++j]){ $(tag[0],container).each((i,e)=>{ let n = e[tag[1]]? $(`<${e[tag[1]]}>${e.innerHTML}</${e[tag[1]]}>`) : (tag[2]? $(`<${tag[2]}>${e.innerHTML}</${tag[2]}>`):$()); if(n.length){ const renames = Object.assign.apply(this,[{}].concat(tag[3]||[{}])) for(const t of e.attributes){ n.attr(renames[t.name]||t.name,t.value); } $(e).replaceWith(n); } }); } return container.html() }
function getSelectionHtml() { var html = ""; if (typeof window.getSelection != "undefined") { var sel = window.getSelection(); if ($(sel.anchorNode).closest('.message').length && sel.rangeCount) { if($(sel.anchorNode).closest('.quote').is($(sel.focusNode).closest('.quote'))){ quotequote=$(sel.focusNode).parents('.quote'); }else{ quotequote=null; if($(sel.focusNode).closest('.message').length == 0){ sel.extend($(sel.anchorNode).closest('.message')[0],$(sel.anchorNode).closest('.message').contents().length) } } var container = document.createElement("div"); for (var i = 0, len = sel.rangeCount; i < len; ++i) { container.appendChild(sel.getRangeAt(i).cloneContents()); } html = container.innerHTML; } } else if (typeof document.selection != "undefined") { if (document.selection.type == "Text") { html = document.selection.createRange().htmlText; } } return cleanupHTML(html); }
var messageIDnum, messageIDsliced, messageAuthor, messageTimestamp, messageNew, quoteText, quotequote;
getSelectionHtml.mouseup = function (event) { var htmlSelection = getSelectionHtml(); getSelectionHtml.mouseup.timeout && clearTimeout(getSelectionHtml.mouseup.timeout) quoteText = htmlSelection.replace(/>/g, "]"); quoteText = quoteText.replace(/</g, "["); if ($('.unblocked .message:hover').length != 0) {
if (htmlSelection != '') { getSelectionHtml.mouseup.timeout = setTimeout(function () { $(".quick-quote-div").css({ position: "absolute", top: mouseY, left: mouseX }); $(".quick-quote-div")[0].showModal(); $('.quick-quote-button').data('button_timeout', setTimeout(function () { if ($('.quick-quote-button:hover').length == 0) { $('.quick-quote-div')[0].close() htmlSelection = '' quoteText = '' } }, 2500))
}, 600); if(quotequote){ messageNew = `[quote author="${$(quotequote).attr('author')}" source="${$(quotequote).attr('source')}" timestamp="${$(quotequote).attr('timestamp')}"]${quoteText}[/quote]` }else{ messageIDnum = $('.post:hover').attr('id'); messageIDsliced = messageIDnum.substr(messageIDnum.lastIndexOf("-") + 1); messageAuthor = $('.post:hover .mini-profile').find('.user-link').attr('title') || $('.post:hover .mini-profile').find('[itemtype$="/Person"] span[itemprop="name"]').text(); messageTimestamp = $('.post:hover .info').find('abbr:first').attr('data-timestamp'); messageTimestamp = messageTimestamp.substring(0, messageTimestamp.length - 3); messageNew = '[quote author="' + messageAuthor + '" source="/post/' + messageIDsliced + '/thread" timestamp="' + messageTimestamp + '"]' + quoteText + '[/quote]' }
} } }
$('.quick-quote-button').click(function () { if (quoteText != '') { messageNew = messageNew.replace(new RegExp("\\[\\/("+htm_specials_tags.singletons.join('|')+")\\]","gi"),""); pb.data('quick_reply') ? $('.quick-reply textarea').replaceSelection(messageNew + "\n")[0].scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'smooth' }) : $('<form></form>', { method: 'POST', action: proboards.route('new_post', { thread_id: pb.item('thread', pb.item('post', +messageIDsliced)['thread_id']).id }) }) .append($('<input>', { name: 'quick_message' }).val(messageNew)) .append($('<input>', { name: 'csrf_token' }).val(proboards.data("csrf_token") || "null")) .appendTo('body').attr('id', 'quick_form'), setTimeout(function () { pb.data('quick_reply') && $('.quick-reply textarea')[0].focus(); $('#quick_form').submit() }, 500); htmlSelection = quoteText = ''; $('.quick-quote-div')[0].close(); } });
$(document).ready(function () {
$(document).bind("mouseup", getSelectionHtml.mouseup); $('.quick-quote-div').on('click', (event) => { event.target.tagName == 'DIALOG' && event.target.close(); })
});
})(); /** UPDATES: - encapsulate to avoid global variables getting overwritten - switched to <dialog> for top-layer treatment - used jQuery.fn.replaceSelection to insert at caret position in quick reply - look for timestamp only in .content > .info - search mini-profile only for author - support quoting guest posts - scroll quick reply into view and set focus on typing area - redirect to full reply if no quick reply is available - ignore selections that are outbounds of the post content - moved button click handler out of selection handler to avoid duplicate or multiple quotes on a single click - properly cite nested quotes and add logic to convert them back to BBCode - delayed button popup to allow for triple-click selections - made BBCode convertor expandable and added spoilers to the list of tags that require special treatment - added youtube to specials converter - switched from parents to closest in boundaries test - resize tailend of selection if it goes beyond post boundary - reinstate timeout of 2.5 seconds auto-close button if pointer not over button (:hover) - added empty and singleton sub-sections to special tags to empty and remove ending tags on void/singleton elements respectively. - added twitter and instagram to the list of tags that require special conversion treatment - added facebook to the list of tags that require special conversion treatment **/ </script>
|
|
inherit
6871
0
Jun 10, 2024 2:25:35 GMT -8
bigballofyarn
"If you wish to make an apple pie from scratch, you must first invent the universe." -Carl Sagan
7,886
January 2003
bigballofyarn
|
Post by bigballofyarn on Oct 25, 2024 4:38:14 GMT -8
Just in case you didn't see my above edit, I moved all posts out of the guest thread and to the testing thread because it seemed more appropriate. If you need any of the replies or posts, that's where they are.
|
|
dustys
Junior Member
Posts: 443
inherit
258526
0
Nov 21, 2024 18:43:22 GMT -8
dustys
443
May 2019
dustys
|
Post by dustys on Oct 25, 2024 11:54:07 GMT -8
It works now?
|
|
inherit
6871
0
Jun 10, 2024 2:25:35 GMT -8
bigballofyarn
"If you wish to make an apple pie from scratch, you must first invent the universe." -Carl Sagan
7,886
January 2003
bigballofyarn
|
Post by bigballofyarn on Oct 25, 2024 11:54:57 GMT -8
dustys, I don't want to give a definitive answer on that. My testers may or may not have found an issue in Firefox. Further research and testing will be conducted.
|
|