Нужна функция jQuery text (), чтобы игнорировать скрытые элементы - PullRequest
2 голосов
/ 12 сентября 2011

У меня есть div, настроенный примерно так:

<div id="test"> <p>Hello</p> <p style="display: none">Goodbye</p> </div>

РЕДАКТИРОВАТЬ: Для пояснения, это самый простой пример.У div может быть любое произвольное число n глубоко вложенных дочерних элементов.

$('#test').getText() возвращает «Hello Goodbye».Вот один вкладыш для тестирования в Firebug: jQuery('<div id="test"> <p>Hello</p> <p style="display: none">Goodbye</p> </div>').text()

Похоже, это связано с тем, что внутреннее использование jQuery, textContent (для не IE), возвращает скрытые элементы как часть текста.Хрмф.

Есть ли способ вернуть текстовое содержимое, игнорируя отображение: none'd элементы?По сути, я пытаюсь имитировать текст, который вы получите, выделив div мышкой и скопировав его в системный буфер обмена.Это игнорирует скрытый текст.

Интересно, что если вы создаете диапазон выделения и получаете из него текст, это также возвращает текст внутри дисплея: ни одного элемента.

var range = document.body.createTextRange();
range.moveToElementText($('#test')[0]);
range.select();

console.log(range.toString()); // Also logs Hello Goodbye!

Таким образом, создание диапазона выбора документа, по-видимому, не то же самое, что выделение мышью с точки зрения отображения: ни один элемент.Как мне обойти эту грязную загадку?

Редактировать: было предложено использовать .filter(':visible').text, но в этом сценарии это не сработает.Мне нужно, чтобы возвращаемый текст был ТОЧНО тем, что получился бы при выделении мышью.Так, например:

$('<div>test1 <p>test2</p>\r\n <b>test3</b> <span style="display:none">none</span></div>').appendTo(document.body).children().filter(':visible').text()

возвращает

"test2test3"

Когда на самом деле я хочу получить вывод

test1 test2
 test3

разрывы строк, пробелы и все, что происходит из \г \ п

Ответы [ 6 ]

4 голосов
/ 12 сентября 2011

Отфильтруйте элементы, используя .filter(":visible").

Или используйте это:

$("#test :visible").text();

Но документация jQuery советует нам использовать .filter() вместо:

Поскольку :visible является расширением jQuery и не является частью спецификации CSS, запросы, использующие :visible, не могут воспользоваться преимуществами повышения производительности, обеспечиваемыми собственным методом DOM querySelectorAll().Для достижения максимальной производительности при использовании: visible для выбора элементов, сначала выберите элементы с помощью чистого селектора CSS, затем используйте .filter(":visible").

2 голосов
/ 12 сентября 2011

Используйте :visible в вашем селекторе как:

$("#test > p:visible").text()

A Пример функции:

- Редактировать:

http://jsfiddle.net/8H5ka/ (Работаетв Chrome в результате отображается «Hello»)

Если вышеописанное не работает:

http://jsfiddle.net/userdude/8H5ka/1/

1 голос
/ 12 сентября 2011

Если пробел не важен, вы можете скопировать разметку, удалить скрытые элементы и вывести этот текст.

var x = $('#test').clone();
x.filter(':not(:visible)').remove();
return x.text();
0 голосов
/ 16 марта 2019

Я ищу это и нашел этот вопрос, но без решения.Решение для меня просто выйти из jquery, чтобы использовать DOM:

var $test = $('#test').get(0).innerText

или, если больше, чем на элемент в массиве селектора, вам нужен цикл for и слияние, но я думаю, что в большинстве случаев этопервая версия, которая вам нужна.

var $test = $('#test').get().map(a => a.innerText).join(' ');
0 голосов
/ 01 августа 2012

Вот как я это сделал с MooTools:

$extend(Selectors.Pseudo, {
    invisible: function() {
        if(this.getStyle('visibility') == 'hidden' || this.getStyle('display') == 'none') {
            return this;
        }
    }
});

Element.implement({
    getTextLikeTheBrowserWould = function() {
        var temp = this.clone();
        temp.getElements(':invisible').destroy();
        return temp.get('text').replace(/ |&amp;/g, ' ');
    }
})
0 голосов
/ 01 августа 2012

У меня была эта проблема, и я нашел этот вопрос, и похоже, что реальное решение основано на предоставленных ответах, но не написано.Итак, вот полное решение, которое сработало для моей ситуации, аналогично OP с дополнительным условием, что элементы могут быть невидимыми из-за внешних стилей, основанных на позиции DOM.Пример:

<style>.invisible-children span { display: none; }</style>
<div class="invisible-children">
  <div id="test">Hello <span>Goodbye</span></div>
</div>

Решение заключается в следующем:

  1. Сделать клон всего объекта.
  2. Удалить невидимые объекты на месте;если мы удалим #test из DOM до того, как удалим невидимые объекты, jQuery может не знать, что они невидимы, потому что они больше не будут соответствовать правилам CSS.
  3. Получить текст объекта.
  4. Замените исходный объект созданным нами клоном.

Код:

var $test = $('#test');
// 1:
var $testclone = $test.clone();
// 2: We assume that $test is :visible and only remove children that are not.
$test.find('*').not(':visible').remove();
// 3:
var text = $test.text();
// 4:
$test.replaceWith($testclone);
// Now return the text...
return text;
// ...or if you're going to keep going and using the $test variable, make sure
// to replace it so whatever you do with it affects the object now in DOM and
// not the original from which we got the text after removing stuff.
$test = $testclone;
$test.css('background', 'grey'); // For example.
...