другие решения не дали мне то, что мне было нужно.
Короткий ответ
мой ответ:
$('#output *:not(:has(*)):visible').text()
plunkr
TL; DR
Проблема с решением Маркга
Вы не должны задавать текст всего элемента под каким-либо корневым элементом.
почему? - будет повторять вывод и игнорировать скрытый флаг
Давайте рассмотрим простой пример
<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>
сейчас, если я сделаю $('#output').children(":visible").text()
Я получу .some-div
и .second
..
когда на самом деле .some-div
меня не касается ..
когда я запрашиваю text()
для этих элементов, .some-div
также возвращает скрытый текст ..
так что технически решение Маркга неверно ИМХО ...
Причина моего ответа
Теперь, чтобы правильно ответить на вопрос, мы должны сделать предположение. Тот, который для меня кажется достаточно разумным.
Предположение состоит в том, что текст появляется только в элементах листа.
Так что мы не увидим ничего подобного:
<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>
Почему это предположение кажется мне разумным? две причины:
- Потому что сложно поддерживать страницу, созданную таким образом, и со временем люди с опытом узнают об этом и избегают этого.
- Легко преобразовать ваш html в такую структуру. просто оберните текст родителей с пролетами. Таким образом, даже если это предположение не существует прямо сейчас, туда легко попасть.
Исходя из этого предположения, вы хотите запросить все конечные элементы (элементы без дочерних элементов), отфильтровать видимое и запросить их текст.
$('#output *:not(:has(*)):visible').text()
Это должно дать правильный результат.
У вас есть текст вне листа?
комментарии предполагают, что иногда вы просто должны иметь текст вне элемента листа
<div> This is some <strong style="display:none"> text </strong> </div>
Как видите, у вас есть <strong>
в качестве листа, и обычно текст вне него, как в этом примере.
Вы можете обойти это с обходным путем, который я предлагаю выше ... но что, если вы не можете?
Вы можете клонировать дом, а затем удалить все скрытые элементы.
Проблема здесь заключается в том, что для работы селекторов :visible
или :hidden
необходимо, чтобы в документе был элемент dom (то есть фактически видимый для пользователя).
Итак, этот метод имеет некоторые побочные эффекты, поэтому будьте осторожны.
Вот пример
для этого HTML
<div id="output" class="my-root">
<span>
some text <strong style="display:none">here.. </strong>
</span>
</div>
Этот JavaScript работает
$(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.
})
см. Плункер здесь
как уже упоминалось - побочные эффекты могут выглядеть как кратковременное мерцание или какой-то сценарий инициализации, который должен быть запущен ... некоторых можно избежать с некоторым оригинальным мышлением (div с размером 1px / 1px, чтобы содержать клон вместе с оригинальным контентом?) В зависимости от ваш сценарий