Tìm chuỗi văn bản bằng jQuery?


241

Giả sử một trang web có một chuỗi như "Tôi là một chuỗi đơn giản" mà tôi muốn tìm. Làm thế nào tôi sẽ đi về điều này bằng cách sử dụng JQuery?

Câu trả lời:


327

jQuery có phương thức chứa. Đây là một đoạn dành cho bạn:

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

Bộ chọn ở trên chọn bất kỳ phần tử nào chứa chuỗi đích. Foundin sẽ là một đối tượng jQuery chứa bất kỳ phần tử phù hợp nào. Xem thông tin API tại: https://api.jquery.com/contains-selector/

Một điều cần lưu ý với ký tự đại diện '*' là bạn sẽ nhận được tất cả các yếu tố, bao gồm cả các yếu tố cơ thể html mà bạn có thể không muốn. Đó là lý do tại sao hầu hết các ví dụ tại jQuery và các nơi khác sử dụng $ ('div: chứa ("Tôi là một chuỗi đơn giản")')


12
@Tony, làm thế nào tôi có thể thao tác chỉ văn bản phù hợp và không chỉ toàn bộ parapgraph, div, v.v.?
Keith Donegan

12
Nên chỉ ra rằng đây là trường hợp nhạy cảm. Một người dùng có tên "tôi" đã viết điều này trên trang tài liệu jQuery: $ .expr [':']. Icontains = function (obj, index, meta, stack) {return (obj.textContent || obj.innerText || jQuery ( obj) .text () || '') .toLowerCase (). indexOf (meta [3] .toLowerCase ())> = 0; }; Ví dụ: $ ("div: icontains ('John')"). Css ("trang trí văn bản", "gạch chân");
Brandon Bloom

cái này có hiệu quả với json không? Nếu tôi muốn lọc một số văn bản trong giá trị json thì sao?
Ch Familyan

5
Điều này sẽ không hoạt động nếu nút văn bản có ngắt dòng, ví dụ. "Tôi là một chuỗi \ n đơn giản". Lưu ý rằng ngắt dòng sẽ không được hiển thị để người dùng thậm chí không biết vấn đề ở đâu. Tất cả các giải pháp có vấn đề này. Xem jsfiddle.net/qPeAx
jesper

9
-1, không hoạt động. Nó trả về tất cả các nút cha trong cây, bạn chỉ muốn nút thấp nhất.
TMS

51

Thông thường các bộ chọn jQuery không tìm kiếm trong "các nút văn bản" trong DOM. Tuy nhiên, nếu bạn sử dụng hàm .contents (), các nút văn bản sẽ được bao gồm, thì bạn có thể sử dụng thuộc tính nodeType để chỉ lọc các nút văn bản và thuộc tính nodeValue để tìm kiếm chuỗi văn bản.

    $ ('*', 'cơ thể')
        .và bản thân()
        .contents ()
        .filter (hàm () {
            trả lại cái này.nodeType === 3;
        })
        .filter (hàm () {
            // Chỉ khớp khi chứa 'chuỗi đơn giản' ở bất kỳ đâu trong văn bản
            return this.nodeValue.indexOf ('chuỗi đơn giản')! = -1;
        })
        .each (hàm () {
            // Làm gì đó với cái này.nodeValue
        });

8
Để làm rõ, như Tony đã đề cập, bạn có thể sử dụng bộ chọn ": chứa ()" để tìm kiếm trong các nút văn bản, nhưng jQuery sẽ không trả về các nút văn bản riêng lẻ trong kết quả (chỉ là danh sách các phần tử). Nhưng khi bạn sử dụng .contents (), thì jQuery trả về cả hai phần tử và nút văn bản. Để biết thêm thông tin: docs.jquery.com/Traversing/contents
BarelyFitz

5
Tôi bối rối tại sao bạn đang sử dụng .andSelf(). Từ api.jquery.com/andSelf : "Các đối tượng jQuery duy trì một ngăn xếp bên trong theo dõi các thay đổi đối với tập hợp các phần tử phù hợp. Khi một trong các phương thức truyền tải DOM được gọi, tập hợp các phần tử mới sẽ được đẩy lên ngăn xếp. bộ phần tử trước đó cũng được mong muốn, .andSelf () có thể giúp đỡ. " Tôi thấy không có bối cảnh trước đó, tôi đang thiếu gì?
Alan H.

1
Nâng cao! Nên là câu trả lời được chấp nhận vì nó lọc ra tất cả các nút cha mà tôi nghĩ là nhu cầu chung trong hầu hết các kịch bản.
LucaM

29

Điều này sẽ chỉ chọn các phần tử lá có chứa "Tôi là một chuỗi đơn giản".

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

Dán sau đây vào thanh địa chỉ để kiểm tra nó.

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

Nếu bạn muốn lấy chỉ "Tôi là một chuỗi đơn giản" . Đầu tiên bọc văn bản trong một yếu tố như vậy.

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

và sau đó làm điều này.

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

3
hàm .filter () sẽ hữu ích hơn .each () ở đây. Trên thực tế, bạn thực sự có thể đặt nó trong một bộ chọn: "*: chứa ('blah'): trống"
nickf

2
#nickf -: trống sẽ không chọn nút văn bản có chứa văn bản. Vì vậy, nếu nút văn bản chứa "Tôi là một chuỗi đơn giản" thì nó bị loại trừ. docs.jquery.com/Selector/empty
Slim

2
Tôi biết tôi đến hơi muộn ở đây, nhưng sẽ không bỏ qua bất kỳ khối văn bản nào mà chuỗi tồn tại ở cấp cao nhất nhưng có con trong đó không? ví dụ: <blockquote> Tôi là một chuỗi đơn giản <span style = "font-weight: bold;"> SỐNG TRÊN EDGE </ span> </ blockquote>
Ken Bellows

Tôi chỉ muốn đề cập rằng "chứaStringImLookingFor" không phải là thuộc tính HTML hợp lệ. Vui lòng sử dụng cho HTML 5 "data-chứaStringImLookingFor". Không có cách nào cho Phiên bản HTML sớm hơn 5 để thêm Thuộc tính tùy chỉnh ...
Snickbrack

17

Nếu bạn chỉ muốn nút gần nhất với văn bản bạn đang tìm kiếm, bạn có thể sử dụng nút này:

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

Điều này thậm chí sẽ hoạt động nếu HTML của bạn trông như thế này:

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

Sử dụng bộ chọn ở trên sẽ tìm thấy <strong>thẻ, vì đó là thẻ cuối cùng chứa toàn bộ chuỗi đó.


1
Điều này dường như không hoạt động. Trên trang này, ví dụ: *: chứa ("the"): cuối cùng chỉ trả về 1 phần tử.
bzlm

4
@bzlm: cũng không nhất thiết phải xác định rằng anh ấy muốn tìm nhiều lần xuất hiện.
nickf

2
Aha. Có cách nào để làm cho nó hoạt động cho nhiều lần? Tôi nghĩ rằng đó là một giải pháp tao nhã hơn các giải pháp liên quan đến kiểm tra loại nút đệ quy, v.v.
bzlm

1
cách duy nhất tôi có thể nghĩ để có được tất cả các nút, nhưng không phải tất cả các tổ tiên trên dòng sẽ lặp lại kết quả, loại bỏ tất cả cha mẹ, mặc dù bạn có thể gặp vấn đề, ví dụ: <p>my text <b>my text</b></p>- xóa tổ tiên của <b>thẻ sẽ thua trận đấu khác
nickf


7

Chỉ cần thêm vào câu trả lời của Tony Miller là điều này giúp tôi đạt 90% cho những gì tôi đang tìm kiếm nhưng vẫn không hiệu quả. Thêm .length > 0;vào cuối mã của anh ấy đã làm cho kịch bản của tôi hoạt động.

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

Làm thế nào để nối một từ mới trên chuỗi tìm thấy?, tôi muốn thêm một dấu sao vào công việc tìm thấy đó.
userAZLogicApps

@SaMolPP foundin += '*';
Pixelomo

2

chức năng này sẽ hoạt động. về cơ bản thực hiện tra cứu đệ quy cho đến khi chúng ta có được một danh sách riêng biệt của các nút lá.

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.