Post by Chris on Oct 25, 2024 17:34:29 GMT -8
This message has been moved to Geocities by Chris .
Updates so far:
Oct 26, 2024 9:26:37 GMT -8 Quote Highlighted Text (Latest Version) said:
/** 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 boundaryNew
- reinstate timeout of 2.5 seconds auto-close button if pointer not over button (:hover)New
- added empty and singleton sub-sections to special tagsNew
- added twitter and instagram to the list of tags that require special conversion treatmentNew
- added facebook to the list of tags that require special conversion treatmentNew
- added support for NOPARSE/NOUBBC tags (implied in HTML)New
- added spotify to the list of tags that require special conversion treatmentNew
- curtailed a Firefox issue regarding promiscuous clicksNew
New
Oct 25, 2024 21:54:10 GMT -8:- fixed constant being defined twice resulting in erro aborting the rest of the scriptNew
Oct 26, 2024 9:26:37 GMT -8:- switched dialog from modal to normal to allow copying selected text to clipboard
**/Newest Code:
Oct 26, 2024 9:26:37 GMT -8:
*Updated from revision 1729922050317 to revision 1729963597700 to fix copying text to clipboard. Change from showModal() to show()$(".quick-quote-div")[0].show();//showModal();
Oct 25, 2024 21:54:10 GMT -8:
*Updated from revision 1729904379760 to revision 1729922050317 because of a duplicate line defining a constant variable twice (resulting in an error and abort of the entire code)const container = $('<div></div>').html(htm), c0de = $('code', container);
c0de.length && c0de.html(c0de.html().replace(/\[\/?noparse\]/gi, ""));
//const container = $('<div></div>').html(htm);(second const container has been commented out)Oct 26, 2024 9:26:37 GMT -8 Quote Highlighted Text (Latest Version) said:<!-- Quick Quotes (UPDATED Oct 26, 2024 @ 1729963597700) -->
<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, attr_has_tagName, optional_tagName_when_not_in_attr, [{rename_this_attr:new_attr_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"}]],
['iframe[src*="spotify"]', '', 'spotify', {"src":"data-id"}]
],
"singletons":[ /* custom void tags that should not have a closing tag */
'twitter',
'instagram',
'facebook',
'spotify'
]
}
function cleanupHTML(htm){
if(htm==="")return htm;
htm = htm.replace(/(\[[^\]]+\])/gm,"[noparse]$1[/noparse]") //preserve uncoverted square brackets
const container = $('<div></div>').html(htm), c0de = $('code', container);
c0de.length && c0de.html(c0de.html().replace(/\[\/?noparse\]/gi, ""));
//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].show()//Modal();
$('.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).on("mouseup", '.message', 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
- 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
- added support for NOPARSE/NOUBBC tags (implied in HTML)
- added spotify to the list of tags that require special conversion treatment
- curtailed a Firefox issue regarding promiscuous clicks
- fixed duplication definition of a constant variable
**/
</script>