Знайти текстовий рядок за допомогою jQuery?


241

Скажімо, на веб-сторінці є такий рядок, як "Я проста строка", який я хочу знайти. Як би я пішов про це за допомогою JQuery?

Відповіді:


327

jQuery має метод містить. Ось фрагмент для вас:

<script type="text/javascript">
$(function() {
    var foundin = $('*:contains("I am a simple string")');
});
</script>

Селектор вище вибирає будь-який елемент, який містить цільовий рядок. Foundin буде об’єктом jQuery, який містить будь-який збіглий елемент. Інформацію про API див. На веб-сторінці : https://api.jquery.com/contains-selector/

Одне, що слід зауважити під символом '*', - це те, що ви отримаєте всі елементи, включаючи ваш html елементи тіла, які, напевно, не хочете. Ось чому більшість прикладів у jQuery та інших місцях використовують $ ('div: містить ("Я проста строка")')


12
@ Тоні, як би я почав маніпулювати лише відповідним текстом, а не лише усім параграфом, дівом тощо тощо?
Кіт Донеган

12
Слід зазначити, що це залежно від регістру. Користувач на ім’я "я" написав це на сторінці документів jQuery: $ .expr [':']. Icontains = функція (obj, індекс, мета, стек) {return (obj.textContent || obj.innerText || jQuery ( obj) .text () || '') .toLowerCase (). indexOf (meta [3] .toLowerCase ())> = 0; }; Приклад: $ ("div: icontains ('John") "). Css (" прикраса тексту "," підкреслити ");
Брендон Блум

це працює для json? Що робити, якщо я хочу відфільтрувати текст у значенні json?
Чамілян

5
Це не працюватиме, якщо у текстового вузла є розрив рядка, наприклад. "Я простий \ n рядок". Зауважте, що розрив рядка не буде наданий, тому користувач навіть не дізнається, де проблема. Усі ці рішення мають цю проблему. Див jsfiddle.net/qPeAx
Jesper

9
-1, не працює. Він повертає всі батьківські вузли на дереві, потрібно лише найнижчий.
TMS

51

Зазвичай селектори jQuery не здійснюють пошук у "текстових вузлах" у DOM. Однак якщо ви використовуєте функцію .contents (), текстові вузли будуть включені, то ви можете використовувати властивість nodeType для фільтрації лише текстових вузлів, а властивість nodeValue для пошуку текстового рядка.

    $ ('*', 'body')
        .andSelf ()
        .contents ()
        .filter (function () {
            повернути цей.nodeType === 3;
        })
        .filter (function () {
            // Збігається лише тоді, коли в тексті міститься "проста рядок"
            повернути this.nodeValue.indexOf ('проста рядок')! = -1;
        })
        .each (function () {
            // Зробіть щось із цим.nodeValue
        });

8
Для уточнення, як згадував Тоні, ви можете використовувати селектор ": містить ()" для пошуку в текстових вузлах, але jQuery не поверне окремі текстові вузли в результатах (лише список елементів). Але коли ви використовуєте .contents (), тоді jQuery повертає і елементи, і текстові вузли. Для отримання додаткової інформації: docs.jquery.com/Traversing/contents
BarelyFitz

5
Мене спантеличує, чому ви користуєтесь .andSelf(). З api.jquery.com/andSelf : "Об'єкти jQuery підтримують внутрішній стек, який відстежує зміни в зібраному наборі елементів. Коли викликається один із методів обходу DOM, новий набір елементів висувається на стек. Якщо попередній набір елементів також бажаний .andSelf () може допомогти. " Я не бачу попереднього контексту, чого я пропускаю?
Алан Х.

1
Оголошено! Це має бути прийнятою відповіддю, оскільки вона фільтрує всі батьківські вузли, які, на мою думку, є загальною потребою в більшості сценаріїв.
ЛукаМ

29

Тут виберуть лише елементи листя, які містять "Я проста строка".

$('*:contains("I am a simple string")').each(function(){
     if($(this).children().length < 1) 
          $(this).css("border","solid 2px red") });

Вставте наступне в адресний рядок, щоб перевірити його.

javascript: $('*:contains("I am a simple string")').each(function(){ if($(this).children().length < 1) $(this).css("border","solid 2px red") }); return false;

Якщо ви хочете схопити просто "Я проста струна" . Спочатку загортайте текст у такий елемент.

$('*:contains("I am a simple string")').each(function(){
     if($(this).children().length < 1) 
          $(this).html( 
               $(this).text().replace(
                    /"I am a simple string"/
                    ,'<span containsStringImLookingFor="true">"I am a simple string"</span>' 
               )  
           ) 
});

а потім зробіть це.

$('*[containsStringImLookingFor]').css("border","solid 2px red");

3
тут функція .filter () була б кориснішою, ніж .each (). Насправді ви насправді можете вкласти його в один селектор: "*: містить (" бла "): порожній"
nickf

2
# nickf -: порожній звичай не вибирає текстовий вузол, який містить текст. Отже, якщо текстовий вузол містить "Я - простий рядок", він виключається. docs.jquery.com/Selectors/empty
Тонкий

2
Я знаю, що я трохи запізнююся тут, але чи не буде це ігноровано жодних текстових блоків, де рядок існує на верхньому рівні, але в ньому є діти? наприклад: <blockquote> Я проста рядок <span style = "font-weight: bold;"> ЖИТТЯ НА РОЗІ </span> </blockquote>
Кен Беллоуз

Я просто хочу зазначити, що "міститьStringImLookingFor" не є дійсним HTML-атрибутом. Будь ласка, використовуйте для HTML 5 "data-containsStringImLookingFor". Немає можливості для версії HTML раніше, ніж 5, додати спеціальні атрибути ...
Snickbrack,

17

Якщо ви просто хочете, щоб вузол був найближчим до тексту, який ви шукаєте, ви можете скористатися цим:

$('*:contains("my text"):last');

Це навіть спрацює, якщо ваш HTML виглядає так:

<p> blah blah <strong>my <em>text</em></strong></p>

Використовуючи вищевказаний селектор, ви знайдете <strong>тег, оскільки це останній тег, який містить всю цю рядок.


1
Це, здається, не працює. Наприклад, на цій сторінці *: містить ("the"): останній повертає лише 1 елемент.
bzlm

4
@bzlm: добре, це не обов'язково вказувало, що він хотів знайти кілька випадків.
nickf

2
Ага. Чи є спосіб змусити його працювати для кількох випадків? Я думаю, що це більш елегантне рішення, ніж ті, що стосуються рекурсивної перевірки типу вузлів тощо.
bzlm

1
єдиний спосіб я міг би подумати, щоб отримати всі вузли, але не всі предки піднімаються в рядку - це провести цикл через результат, видаливши всіх батьків, хоча у вас можуть виникнути проблеми, наприклад: <p>my text <b>my text</b></p>- видалення предків <b>тегу програють інший матч
nickf


7

Просто додавши відповідь Тоні Міллера, оскільки це наділило мене на 90% до того, що я шукав, але все одно не працював. Додавши .length > 0;до кінця свого коду, мій сценарій запрацював.

 $(function() {
    var foundin = $('*:contains("I am a simple string")').length > 0;
 });

як додати нове слово до знайденого рядка ?, я хочу додати зірочку до знайденої роботи.
користувачAZLogicApps

@SaMolPP foundin += '*';
Pixelomo

2

ця функція повинна працювати. в основному відбувається рекурсивний пошук, поки ми не отримаємо чіткого списку вузлів листя.

function distinctNodes(search, element) {
    var d, e, ef;
    e = [];
    ef = [];

    if (element) {
        d = $(":contains(\""+ search + "\"):not(script)", element);
    }
    else {
            d = $(":contains(\""+ search + "\"):not(script)");
    }

    if (d.length == 1) {
            e.push(d[0]);
    }
    else {
        d.each(function () {
            var i, r = distinctNodes(search, this);
            if (r.length === 0) {
                e.push(this);
            }
            else {
                for (i = 0; i < r.length; ++i) {
                    e.push(r[i]);
                }
            }
        });
    }
    $.each(e, function () {
        for (var i = 0; i < ef.length; ++i) {
            if (this === ef[i]) return;
        }
        ef.push(this);
    });
    return ef;
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.