2012-11-09 27 views
10

Tôi có một cấu trúc bảng lồng nhau nhưjQuery: find() con cho đến khi một yếu tố ngưỡng nhất định là gặp phải

<table> 

     <td id="first"> 

      <div class="wrapper"> 
       <input name=1> 
      </div> 

      <input name=2> 

      <table> 

       <td id="second"> 

        <input name=3> 

Tôi có jQuery lựa chọn $("#first"). Tôi muốn duyệt qua và find() tất cả trẻ em <input>s trong ngữ cảnh <td> này, nhưng không được đưa vào lồng nhau <table> s.

Vì vậy, tôi cần một thủ thuật jQuery mà

  • sẽ find() tất cả trẻ em các yếu tố của một yếu tố nào đó

  • sẽ Descent n mức giảm trong DOM cây

  • Nhưng sẽ ngừng giảm dần nếu nhất định một yếu tố (<table>) gặp phải, do đó bộ chọn không chọn đầu vào của một bảng lồng nhau (sẽ được xử lý riêng)

  • Có thể có bất kỳ số lượng <table> mức lồng nhau, vì vậy giải pháp nên làm việc dù có bao nhiêu cha mẹ <table> hoặc trẻ em <table> đang gặp phải trong phạm vi $ ("# đầu tiên") <td> hoặc bất kỳ khác <td>

Tôi đã kiểm tra jQuery khác cho đến khi có câu hỏi. Họ có câu trả lời, nhưng có vẻ như họ không điền vào tiêu chí cuối cùng

+0

Bạn có nghĩ rằng cấu trúc bảng của bạn là tốt ở đây? – freebird

+1

Cho dù cấu trúc được thực hiện bằng cách sử dụng '

' hoặc một số yếu tố khác là tự nhiên không thích hợp cho câu hỏi –

+0

Tôi đã hỏi vì thẻ 'input' của bạn không tốt hình thành cũng 'tr' bị thiếu. – freebird

Trả lời

5

Tôi đã có một vấn đề tương tự trong this other question. Cuối cùng tôi đã tự mình tìm ra một plugin sau khi đi qua lại với một số người đang cố gắng nghĩ về một bộ chọn tìm.

SỬ DỤNG: ExclusiveInputs = $('#first').findExclude('input','table');

// Find-like method which masks any descendant 
// branches matching the Mask argument. 
$.fn.findExclude = function(Selector, Mask, result){ 

    // Default result to an empty jQuery object if not provided 
    var result = typeof result !== 'undefined' ? 
       result : 
       new jQuery(); 

    // Iterate through all children, except those match Mask 
    this.children().each(function(){ 

     var thisObject = jQuery(this); 
     if(thisObject.is(Selector)) 
      result.push(this); 

     // Recursively seek children without Mask 
     if(!thisObject.is(Mask)) 
      thisObject.findExclude(Selector, Mask, result); 
    }); 

    return result; 
} 

(Version Condensed):

$.fn.findExclude = function(selector, mask, result) 
{ 
    var result = typeof result !== 'undefined' ? result : new jQuery(); 
    this.children().each(function(){ 
     var thisObject = jQuery(this); 
     if(thisObject.is(selector)) 
      result.push(this); 
     if(!thisObject.is(mask)) 
      thisObject.findExclude(selector, mask, result); 
    }); 
    return result; 
} 
2

eh, tôi có một ý tưởng tốt hơn ..

var badTable = "table.bad"; //the one you want to avoid 
var $goodInputs = $("#first").find('input').filter(function() { 
    return $(this).closest(badTable).length == 0; 
}); 

này có thể hoặc không có thể đủ nhanh cho bạn. nó phụ thuộc vào DOM của bạn mà bạn không muốn nói về;)

nếu nó chậm, chỉ cần viết mã cho thuật toán của bạn bằng tay. Không có phím tắt chọn.

+0

Như câu hỏi, bạn không thể xác định bảng nào là "xấu" từ ngữ cảnh, nhưng nó phải hoạt động với bất kỳ cấp độ làm tổ nào mà không có điểm đánh dấu lớp đặc biệt –

3

Cập nhật: Hãy tính đến điều này.

Về cơ bản, bạn muốn kết hợp tất cả các yếu tố <input> đó là hậu duệ của #first và đó không phải là con của <td> yếu tố lồng nhau nhiều hơn một mức độ sâu dưới #first.

(Tôi không chắc chắn về phần under #first cuối cùng này, nhưng việc triển khai nó cho phép chúng tôi hỗ trợ <td> các yếu tố trên #first trong chuỗi tổ tiên.)

Về mặt kỹ thuật, bộ chọn sau đây một mình nên đáp ứng yêu cầu của bạn:

var inputs = $("#first td:not(#first td td) > input"); 

Nếu điều này không làm việc trong trình duyệt của bạn (sizzle nên lên đến nhiệm vụ tôi nghĩ, nhưng selectors phức tạp như :not() luôn khéo léo), bạn có thể ủy xử lý với các phương pháp jQuery:

var inputs = $("#first td").not("#first td td").children("input"); 

gốc một swer sau:

Bạn có thể sử dụng để loại trừ not()<input> yếu tố mà có nhiều hơn một <td> tổ tiên:

var firstLevelCells = $("#first").find("input").not("td td input"); 
+1

Tôi không hiểu; sẽ không cần phải được '$ (" # đầu tiên "). tìm thấy (" đầu vào "). không (" td td đầu vào ")'? – lnrbob

+0

Bạn hoàn toàn đúng, tôi đã mất dấu phần tử thực tế để khớp trên đường đi. Trả lời cập nhật cho phù hợp, cảm ơn cho người đứng đầu lên :) –

1

Tôi đã có một vấn đề tương tự và vẫn còn thử thách để làm một cái gì đó mà không có một vòng lặp gia hạn hoặc có cấu trúc chính xác của DOM. Trong trường hợp của tôi, tôi đã có một tham chiếu đến phần tử '#first' mà nếu bạn không, chúng ta có thể lấy nó cho ví dụ với mỗi phần tử (ngay cả khi nó chỉ là một đối tượng). Bí quyết là để trở lại lên cây với cha mẹ và dừng lại ở yếu tố hàng đầu của bạn để xem nếu có bất kỳ yếu tố trung gian đáp ứng các điều kiện.

Sử dụng các ký hiệu viết tắt lambda cho các chức năng (như bạn có thể viết trong nguyên cảo) điều này sẽ dẫn đến điều này:

$('#first').each((idx, f) => $(f).find('input').filter((idx2, inp) => $(inp).parentsUntil(f, 'table').length == 0) 

Nó có thể không phải là cách hiệu quả nhất (như bạn đầu tiên chọn tất cả mọi thứ để sau đó ném các yếu tố đi bằng cách gắn lên cây DOM một lần nữa, nhưng nó là nhỏ gọn và khá chung chung

Các vấn đề liên quan