您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
adds quick quote and reply buttons https://cs.rin.ru/forum/viewtopic.php?f=14&t=134386
// ==UserScript== // @name cs.rin.ru quick quote & reply // @namespace none // @version 2 // @description adds quick quote and reply buttons https://cs.rin.ru/forum/viewtopic.php?f=14&t=134386 // @author odusi // @match https://cs.rin.ru/forum/viewtopic.php?* // @match https://cs.rin.ru/forum/posting.php?* // @icon none // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // ==/UserScript== const bbTags = [ {open: '[b]', close: '[/b]', label: 'B'}, {open: '[url=]', close: '[/url]', label: 'URL'}, {open: '[spoiler=]', close: '[/spoiler]', label: 'spoiler'}, ] const bbColors = [] if (location.href.includes('viewtopic.php') && !document.querySelector('a[href^="./posting.php?mode=reply"] img').alt.includes('locked')) { const url = new URL(location) const f = url.searchParams.get('f') const t = url.searchParams.get('t') GM_addStyle(` #quickreply-toggle { border: 1px solid #8d8dc9; border-radius: 5px; color: #c3d855; font-family: 'Lucida Grande', Verdana, Helvetica, sans-serif; padding: 0.2rem; background-color: #562e52; } .quickreply-btn { padding: 2px 10px; color: #AAAAAA; font-size: 0.7rem } .quickreply-bbcolor { width: 12px; height: 12px; padding: 2px; border: 1px solid black; margin-left: 2px } .quickreply-quickquote { border: none; padding: 0.1rem 0.3rem; font-family: inherit; margin-right: 10px; font-size: 0.6rem; border-radius: 2px; background-color: #b3d3d3; cursor: pointer; } `) function insertBBCode(tag, value) { let textArea = document.getElementById('quickreply-textarea'); let text = textArea.value; let start = textArea.selectionStart; let end = textArea.selectionEnd; let before = text.substring(0, start); let middle = text.substring(start, end); let after = text.substring(end, text.length); if (value) { textArea.value = before + `[color=${value}]` + middle + '[/color]' + after textArea.selectionStart = start + `[color=${value}]`.length; textArea.selectionEnd = end + `[color=${value}]`.length; } else { textArea.value = before + tag['open'] + middle + tag['close'] + after textArea.selectionStart = start + tag['open'].length; textArea.selectionEnd = end + tag['open'].length; } textArea.focus() } function rgbToHex(clr) { if (/^([a-z]+)$/i.test(clr)) return clr let a = clr.split("(")[1].split(")")[0]; a = a.split(","); let b = a.map(function (x) { x = parseInt(x).toString(16); return (x.length === 1) ? "0" + x : x; }); return "#" + b.join(""); } function quoteSpan(span, text, nodetext = null, multi = null) { let a = multi ? traverseNodes(span) : text || nodetext if (span.style.fontWeight === 'bold') text = `[b]${a}[/b]` if (span.style.textDecoration === 'underline') text = `[u]${a}[/u]` if (span.style.fontStyle === 'italic') text = `[i]${a}[/i]` if (span.style.fontSize) text = `[size=${span.style.fontSize.slice(0, -1)}]${a}[/size]` if (span.style.color) text = `[color=${rgbToHex(span.style.color)}]${a}[/color]` return text } function traverseNodes(nodes) { let text = ""; nodes.childNodes.forEach(function (child) { if (child.nodeType === Node.TEXT_NODE) text += child.nodeValue; else if (child.nodeType === Node.ELEMENT_NODE) { if (child.tagName === "IMG") text += child.alt; else if (child.tagName === "BR") text += "\n"; else if (child.tagName === "A") text += child.href === child.textContent ? traverseNodes(child) : `[url=${child.href}]${traverseNodes(child)}[/url]` else if (child.tagName === "SPAN") { text += quoteSpan(child, text, null, 1) } else text += traverseNodes(child); } }); return text; } function quickQuote(element) { let selectedText = '' let selection = window.getSelection() if (selection.rangeCount > 0) { let range = selection.getRangeAt(0); if (range.endContainer.nodeName === '#text' && range.startContainer === range.endContainer) { let parent = range.endContainer.parentElement while (parent.tagName === 'SPAN') { selectedText = quoteSpan(parent, selectedText, range.endContainer.textContent) parent = parent.parentElement } } else selectedText = traverseNodes(range.cloneContents()) } return selectedText ? selectedText : traverseNodes(element) } function insertQuote(element) { document.getElementById('quickreply-main-container').style.display = 'block' let table = element.closest('.tablebg') textArea.value += `[quote="${table.querySelector('.postauthor').textContent}"]${quickQuote(table.querySelector('.postbody'))}[/quote]` } const pagecontent = document.querySelector("#pagecontent") pagecontent.insertAdjacentHTML('afterbegin', ` <div id="quickreply-container" style="position: fixed; top: 70%"> <button type="button" id="quickreply-toggle"">Quick Post</button> <div id="quickreply-main-container" style="display: none; background-color: #201d1d; "> <div id="bb-tags-container" style="font-size: 0; float:left;" ></div> <div id="bb-colors-container" style="font-size: 0; clear:both;"></div> <textarea id="quickreply-textarea" cols="60" rows="7" style="margin: 2px 0; font-size: 0.6rem;"></textarea> <div style="display:flex; justify-content:space-between;"> <button type="button" class="btnmain quickreply-btn" id="quickreply-submit">Submit</button> <button type="button" class="btnlite quickreply-btn" id="open-full">Open in full editor</button> </div> </div> </div> <button type="button" class="quickreply-quickquote" id="quickreply-floatingquote" style="display:none; position:absolute;">Quick Quote</button> `) const submitButton = document.getElementById('quickreply-submit') const textArea = document.getElementById('quickreply-textarea') let floatingButton = document.querySelector('#quickreply-floatingquote'); bbTags.forEach(tag => { let button = document.createElement('button') button.type = 'button' button.className = 'btnbbcode quickreply-btn' button.textContent = tag.label; button.addEventListener('click', () => { insertBBCode(tag) }) document.getElementById('bb-tags-container').append(button) }) bbColors.forEach((color) => { let button = document.createElement('button') button.type = 'button' button.className = 'quickreply-bbcolor' button.style.backgroundColor = color button.addEventListener('click', () => { insertBBCode('', color) }) document.getElementById('bb-colors-container').append(button) }) function submit() { submitButton.textContent = 'Submitting...' fetch(`posting.php?mode=reply&f=${f}&t=${t}`) .then(r => r.text()) .then(h => { let doc = document.createElement('div') doc.style.display = 'none' doc.innerHTML = h document.body.append(doc) doc.querySelector('textarea[name=message]').value = textArea.value setTimeout(() => { doc.querySelector('form[name=postform]').requestSubmit(doc.querySelector('input[name=post]')) }, 1200) }) } submitButton.addEventListener('click', () => submit()) textArea.addEventListener('keydown', ev => { if (ev.ctrlKey && ev.key === 'Enter') submit() }) document.getElementById('open-full').addEventListener('click', () => { GM_setValue('p', 1) GM_setValue('text', textArea.value) window.location.href = `posting.php?mode=reply&f=${f}&t=${t}` }) document.getElementById('quickreply-toggle').addEventListener('click', () => { let d = document.getElementById('quickreply-main-container') if (d.style.display === 'none') { d.style.display = 'block' textArea.focus() } else d.style.display = 'none' }) pagecontent.addEventListener('mouseup', () => { setTimeout(() => { const selection = document.getSelection(); if (!selection.rangeCount || selection.isCollapsed) floatingButton.style.display = 'none'; if (!selection.isCollapsed) { const range = selection.getRangeAt(0); let node = range.commonAncestorContainer node.nodeType === Node.TEXT_NODE ? node = node.parentElement : null let postbody = node.closest('.postbody') if (postbody) { const newRange = document.createRange(); newRange.setStart(range.endContainer, range.endOffset - 1); // set range to last character newRange.setEnd(range.endContainer, range.endOffset); const rect = newRange.getBoundingClientRect(); floatingButton.replaceWith(floatingButton.cloneNode(true)) // remove existing event listener floatingButton = document.getElementById('quickreply-floatingquote') floatingButton.addEventListener('click', () => insertQuote(postbody)) floatingButton.style.top = `${rect.bottom + window.scrollY}px`; floatingButton.style.left = `${rect.right + window.scrollX}px`; floatingButton.style.display = 'block'; } } }, 0) }); document.querySelectorAll('a[href^="./posting.php?mode=quote"]').forEach(a => { let quickquotebutton = document.createElement('button') quickquotebutton.type = 'button' quickquotebutton.textContent = 'Quick Quote' quickquotebutton.className = 'quickreply-quickquote' quickquotebutton.addEventListener('click', () => insertQuote(a)) a.before(quickquotebutton) }) } if (location.href.includes('posting.php') && GM_getValue('p') === 1) { GM_setValue('p', 0) document.querySelector('textarea[name=message]').value = GM_getValue('text') }