Prevent text selection in rt (furigan) tags

I use ruby ​​annotation to add furigans to Japanese text:

<ruby><rb>ζΌ’</rb><rt>かん</rt></ruby><ruby><rb>ε­—</rb><rt>じ</rt></ruby> 

When I try to select ζΌ’ε­— and copy it to Safari or Chrome, the clipboard looks like this:

 漒かん字 

I cannot search a word from the OS X dictionary.

Is there a way to prevent the selection of furigans? rt { -webkit-user-select: none; } rt { -webkit-user-select: none; } doesn't seem to work.

+8
javascript css ruby-characters
source share
3 answers

It looks like if you wrap them inside a single <ruby> element, for example:

 <ruby> <rb>ζΌ’</rb><rt>かん</rt> <rb>ε­—</rb><rt>じ</rt> </ruby> 

Then it will be possible to choose ζΌ’ε­— without the selected furigans.


UPDATE:

For kanji-kana mixed text, such as ι–“ に 合 わ せ γ‚‹, you can:

  • Use an empty <rt> element, for example:

     <ruby> <rb>ι–“</rb><rt>ま</rt> <rb>に</rb><rt></rt> <rb>合</rb><rt>あ</rt> <rb>わせる</rb><rβ€Œβ€‹t></rt> </ruby> 
  • Write javascript using clipboard events * & dagger; :

    • HTML:

       <ruby> <rb>ι–“</rb><rt>ま</rt> </ruby>に<ruby> <rb>合</rb><rt>あ</rt> </ruby>わせる 
    • JavaScript:

       $(document).on('copy', function (e) { e.preventDefault(); // the clipboard data will be set manually later // hide <rt> elements so that they won't be selected $('rt').css('visibility', 'hidden'); // copy text from selection e.originalEvent.clipboardData.setData('text', window.getSelection().toString()); // restore visibility $('rt').css('visibility', 'visible'); }); 

Here is a demo page & Dagger; : http://jsfiddle.net/vJK3e/1/

* Checked OK on Safari 6.0.3
<Sub> & X's; Newer browser version may be required.
<Sub> & Dagger; I am adding a line of code css rt::selection { display: none; } rt::selection { display: none; } to prevent the furigans font from being selected (visually)

+4
source share

Here's the vanilla javascript way to do this:

 // hide furigana before sending and reenable after document.addEventListener('copy', function (e) { e.preventDefault(); var furis = document.getElementsByTagName('rt'); for (var i = 0; i < furis.length; i++) { furis[i].style.display = 'none'; } e.clipboardData.setData('text', window.getSelection().toString()); for (var i = 0; i < furis.length; i++) { furis[i].style.removeProperty('display'); } }); 

As noted above, adding .replace(/\n/g, '') after window.getSelection().toString() will remove any new lines that still hang around. .replace(' ', '') can be useful if you do not want the user to have extra spaces as well. This may or may not be desirable for your use.

+3
source share

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; } } } }); 
0
source share

All Articles