I have website that converts Japanese Kanji into Romaji (roman letters):
and the output shows and hides with CSS what the user needs to see depending on their input criteria. For example:
<div id="output"><span class="roman">watashi</span> <span class="english">I</span></div>
The interface allows the user to flip between and output of watashi
or I
depending on what they want to see. The CSS hides one or the other using jQuery and a toggle button. (the hiding mechanism involves simple adding a class to the body and letting CSS do its thing).
The problem is that when users copy/paste the text into Word it copies everything. So I decided to use a system to copy paste the text using JavaScript and jQuery, but the problem repeats itself:
$('#output').text()
outputs watashi I
even if I
is invisible on the page itself rather than watashi
. Is there any way to get just the visible text?
Get Content - text(), html(), and val() Three simple, but useful, jQuery methods for DOM manipulation are: text() - Sets or returns the text content of selected elements. html() - Sets or returns the content of selected elements (including HTML markup) val() - Sets or returns the value of form fields.
Use the textContent property to get the text of an html element, e.g. const text = box. textContent . The textContent property returns the text content of the element and its descendants. If the element is empty, an empty string is returned.
visibility = 'visible'; If you are using jQuery, you can do it even easier as long as you want to set the display property: $(elem). hide(); $(elem).
Answer: Use the jQuery :visible Selector You can use the jQuery :visible selector to check whether an element is visible in the layout or not. This selector will also select the elements with visibility: hidden; or opacity: 0; , because they preserve space in the layout even they are not visible to the eye.
the other solutions did not give me what I needed.
my answer is :
$('#output *:not(:has(*)):visible').text()
plunkr
You should not ask the text of all element under some root element..
why? - it will repeat output and ignore hidden flag
lets look at a simple example
<div id="output" class="my-root"> <div class="some-div"> <span class="first" style="display:none"> hidden text </span> <span class="second" > visible text </span> </div> <div>
now if I do $('#output').children(":visible").text()
I will get .some-div
and .second
.. when in fact .some-div
is of no concern to me..
when I ask for text()
on those elements, .some-div
will return the hidden text as well..
so technically marcgg's solution is wrong IMHO...
Now, in order to properly answer the question, we have to make an assumption. One that, for me, seems reasonable enough.
The assumption is that text only appears in leaf elements..
So we won't see something like this:
<div id="output" class="my-root"> <div class="some-div"> <span class="first" style="display:none"> hidden text </span> <span class="second" > visible text </span> </div> some text here.. <div>
Why does this assumption seem reasonable to me? two reasons:
With that assumption, what you want to do is request all leaf elements (elements without children) , filter out the visible, and ask for their text..
$('#output *:not(:has(*)):visible').text()
This should generate the correct result.
the comments suggest sometimes you just got to have text outside leaf element
<div> This is some <strong style="display:none"> text </strong> </div>
As you can see, you have <strong>
as a leaf and it is common to have text outside it like in this example.
You could go around it with the workaround I suggest above.. but what if you can't?
You can clone the dom and then remove all hidden elements. The problem here is that in order for :visible
selector or :hidden
selectors to work, I must have the dom element on the document (which means actually visible to the user). And so, this method comes with some side effects, so be careful.
Here is an example
for this html
<div id="output" class="my-root"> <span> some text <strong style="display:none">here.. </strong> </span> </div>
This javascript works
$(function(){ var outputClone = $('#output').clone(); $('#output :hidden').remove(); console.log($('#output').text()); // only visible text $('#output').replaceWith(outputClone); console.log($('#output').text()); // show original state achieved. })
see plunker here
as mentioned - side effects may appear like a momentary flicker, or some initialization script that should run.. some may be avoided with some original thinking (div with size 1px/1px to contain the clone alongside original content?) depending on your scenario.
Use the :visible selector of jQuery
In your case I think you want to do:
$('#output').children(":visible").text()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With