Temukan string teks menggunakan jQuery?

241

Katakanlah halaman web memiliki string seperti "Saya adalah string sederhana" yang ingin saya temukan. Bagaimana cara saya menggunakan JQuery?

Keith Donegan
sumber

Jawaban:

327

jQuery memiliki metode berisi. Ini cuplikan untuk Anda:

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

Selektor di atas memilih elemen apa pun yang berisi string target. Foundin akan menjadi objek jQuery yang berisi elemen yang cocok. Lihat informasi API di: https://api.jquery.com/contains-selector/

Satu hal yang perlu diperhatikan dengan wildcard '*' adalah Anda akan mendapatkan semua elemen, termasuk elemen tubuh html Anda, yang mungkin tidak Anda inginkan. Itulah sebabnya sebagian besar contoh di jQuery dan tempat lain menggunakan $ ('div: berisi ("Saya adalah string sederhana")')

Tony Miller
sumber
12
@ Tony, bagaimana saya bisa memanipulasi hanya teks yang cocok dan bukan hanya seluruh parapgraph, div dll?
Keith Donegan
12
Harus menunjukkan bahwa ini peka huruf besar-kecil. Seorang pengguna bernama "saya" menulis ini di halaman dokumen jQuery: $ .expr [':']. Icontains = function (obj, index, meta, stack) {return (obj.textContent || obj.innerText || jQuery ( obj) .text () || '') .toLowerCase (). indexOf (meta [3] .toLowerCase ())> = 0; }; Contoh: $ ("div: icontains ('John')"). Css ("text-decoration", "underline");
Brandon Bloom
apakah ini bekerja untuk json? Bagaimana jika saya ingin memfilter beberapa teks dalam nilai json?
Chamilyan
5
Ini tidak akan berfungsi jika simpul teks memiliki jeda baris misalnya. "Saya adalah string \ n sederhana". Perhatikan bahwa jeda baris tidak akan diberikan sehingga pengguna bahkan tidak akan tahu di mana masalahnya. Semua solusi ini memiliki masalah ini. Lihat jsfiddle.net/qPeAx
jesper
9
-1, tidak bekerja. Ini mengembalikan semua node induk di pohon, Anda hanya ingin yang terendah.
TMS
51

Biasanya pemilih jQuery tidak mencari di dalam "node teks" di DOM. Namun jika Anda menggunakan fungsi .contents (), simpul teks akan disertakan, maka Anda bisa menggunakan properti nodeType untuk memfilter hanya simpul teks, dan properti nodeValue untuk mencari string teks.

    $ ('*', 'tubuh')
        .andSelf ()
        .isi()
        .filter (function () {
            kembalikan this.nodeType === 3;
        })
        .filter (function () {
            // Hanya cocok ketika berisi 'string sederhana' di mana saja dalam teks
            kembalikan this.nodeValue.indexOf ('string sederhana')! = -1;
        })
        .each (function () {
            // Lakukan sesuatu dengan this.nodeValue
        });
BarelyFitz
sumber
8
Untuk memperjelas, seperti yang disebutkan Tony, Anda dapat menggunakan pemilih ": berisi ()" untuk mencari di dalam simpul teks, tetapi jQuery tidak akan mengembalikan masing-masing simpul teks dalam hasil (hanya daftar elemen). Tetapi ketika Anda menggunakan .contents (), maka jQuery mengembalikan elemen dan simpul teks. Untuk info lebih lanjut: docs.jquery.com/Traversing/contents
BarelyFitz
5
Saya bingung mengapa Anda menggunakannya .andSelf(). Dari api.jquery.com/andSelf : "objek jQuery memelihara tumpukan internal yang melacak perubahan pada set elemen yang cocok. Ketika salah satu metode traversal DOM dipanggil, set elemen baru didorong ke stack. Jika set elemen sebelumnya juga diinginkan, .andSelf () dapat membantu. " Saya tidak melihat konteks sebelumnya, apa yang saya lewatkan?
Alan H.
1
Terpilih! Seharusnya jawaban yang diterima karena menyaring semua node induk yang saya pikir merupakan kebutuhan umum di sebagian besar skenario.
LucaM
29

Ini akan memilih hanya elemen daun yang mengandung "Saya string sederhana".

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

Rekatkan yang berikut ke bilah alamat untuk mengujinya.

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

Jika Anda ingin mengambil hanya "Saya adalah string sederhana" . Pertama bungkus teks dalam elemen seperti itu.

$('*: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>' 
               )  
           ) 
});

dan kemudian lakukan ini.

$('*[containsStringImLookingFor]').css("border","solid 2px red");
Ramping
sumber
3
fungsi .filter () akan lebih bermanfaat daripada .each () di sini. Bahkan, Anda bisa memasukkannya ke dalam satu pemilih: "*: berisi ('blah'): kosong"
nickf
2
#nickf -: kosong tidak akan memilih simpul teks yang berisi teks. Jadi, jika simpul teks berisi "Saya string sederhana" itu dikecualikan. docs.jquery.com/Selectors/empty
Slim
2
Saya tahu saya sedikit terlambat di sini, tetapi bukankah ini akan mengabaikan blok teks mana pun string berada di tingkat atas tetapi ada anak-anak di dalamnya? misalnya: <blockquote> Saya adalah string sederhana <span style = "font-weight: bold;"> LIVING ON THE EDGE </span> </blockquote>
Ken Bellows
Saya hanya ingin menyebutkan bahwa "berisiStringImLookingFor" bukan Atribut HTML yang valid. Silakan gunakan untuk HTML 5 "data-mengandungStringImLookingFor". Tidak ada cara untuk Versi HTML lebih awal dari 5 untuk menambahkan Atribut khusus ...
Snickbrack
17

Jika Anda hanya ingin simpul yang paling dekat dengan teks yang Anda cari, Anda bisa menggunakan ini:

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

Ini bahkan akan berfungsi jika HTML Anda terlihat seperti ini:

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

Menggunakan pemilih di atas akan menemukan <strong>tag, karena itu adalah tag terakhir yang berisi seluruh string.

nickf
sumber
1
Ini sepertinya tidak berhasil. Pada halaman ini, misalnya, *: berisi ("the"): terakhir hanya mengembalikan 1 elemen.
bzlm
4
@ bzlm: yah itu tidak selalu menentukan bahwa dia ingin menemukan beberapa kejadian.
nickf
2
Aha. Apakah ada cara untuk membuatnya berfungsi untuk banyak kejadian? Saya pikir itu solusi yang lebih elegan daripada yang melibatkan rekursif jenis node memeriksa dll
bzlm
1
satu-satunya cara saya bisa berpikir untuk mendapatkan semua node, tetapi tidak semua nenek moyang akan mengulangi hasilnya, menghapus semua orang tua, meskipun Anda dapat memiliki masalah, misalnya: <p>my text <b>my text</b></p>- menghapus leluhur <b>tag akan kalah pada pertandingan lainnya
nick
7

Hanya menambahkan jawaban Tony Miller karena ini membuat saya 90% menuju apa yang saya cari tetapi masih tidak berhasil. Menambahkan .length > 0;ke akhir kodenya membuat skrip saya berfungsi.

 $(function() {
    var foundin = $('*:contains("I am a simple string")').length > 0;
 });
Pixelomo
sumber
bagaimana cara menambahkan kata baru pada string yang ditemukan ?, saya ingin menambahkan asterik pada pekerjaan yang ditemukan itu.
userAZLogicApps
@SaMolPP foundin += '*';
Pixelomo
2

fungsi ini harus berfungsi. pada dasarnya melakukan pencarian rekursif sampai kita mendapatkan daftar node daun yang berbeda.

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;
}
danatcofo
sumber