Expanding on the solution provided by Rox Dorentus and incorporating jpc-ae's Javascript conversion, a revised algorithm is presented here to enhance functionality without the need to manipulate the display
style of <rt>
elements, which could be considered delicate.
Instead of directly modifying styles, this approach involves constructing an array containing references to all nodes in the selection, filtering for those tagged as <rb>
, and extracting their textual content using innerText
. Additionally, an alternative method is outlined as a fallback when <rb>
tags are not utilized to envelop the kanji characters.
document.addEventListener('copy', function (e) {
var nodesInRange = getRangeSelectedNodes(window.getSelection().getRangeAt(0));
/* Retrieves all <rb> elements within the selected range e.g., for <ruby><rb>振</rb><rt>ふ</rt></ruby> */
var payload = nodesInRange.filter((node) => node.nodeName === "RB").map((rb) => rb.innerText).join("");
/* Alternative method if no <rb> tags are used: captures all textNodes within <ruby> elements e.g., 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();
/* Helper function for fetching an array of node references within 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;
}
}
}
});