Based on Rox Dorentus's accepted answer (and with reference to jpc-ae useful Javascript transformation), an algorithm is improved that does not involve breaking the display style of the <rt> elements, which seems fragile to me.
Instead, we create an array of links to all nodes in the selection, filter for any with the <rb> and return their innerText . I also provide a commented out alternative if <rb> tags are not used to wrap kanji.
document.addEventListener('copy', function (e) { var nodesInRange = getRangeSelectedNodes(window.getSelection().getRangeAt(0)); /* Takes all <rb> within the selected range, ie. for <ruby><rb>ζ―</rb><rt>γ΅</rt></ruby> */ var payload = nodesInRange.filter((node) => node.nodeName === "RB").map((rb) => rb.innerText).join(""); /* Alternative for when <rb> isn't used: take all textNodes within <ruby> elements, ie. for <ruby>ζ―<rt>γ΅</rt></ruby> */ // var payload = nodesInRange.filter((node) => node.parentNode.nodeName === "RUBY").map((textNode) => textNode.textContent ).join(""); e.clipboardData.setData('text/plain', payload); e.preventDefault(); /* Utility function for getting an array of references to all the nodes in the selection area, * from: http://stackoverflow.com/a/7784176/5951226 */ function getRangeSelectedNodes(range) { var node = range.startContainer; var endNode = range.endContainer; if (node == endNode) return [node]; var rangeNodes = []; while (node && node != endNode) rangeNodes.push(node = nextNode(node)); node = range.startContainer; while (node && node != range.commonAncestorContainer) { rangeNodes.unshift(node); node = node.parentNode; } return rangeNodes; function nextNode(node) { if (node.hasChildNodes()) return node.firstChild; else { while (node && !node.nextSibling) node = node.parentNode; if (!node) return null; return node.nextSibling; } } } });
Jamie birch
source share