2017-01-27 143 views
2

請建議更好的標題以使其他用戶更容易找到此問題。在不知道匹配元素的嵌套位置的情況下選擇匹配的元素,但不匹配那些匹配元素的子元素

我試圖選擇一個父元素的孩子,但孩子可能是一個孩子的孩子,沒有限制多少嵌套的孩子。我想選擇那個孩子,但是如果在許多嵌套的孩子中有一個孩子的孩子,我不希望這個孩子被選中。例如:

<div class="section"> 
<div> <!--First nested child (Take this and repeat as many times as you want within the parent 'section' class, structure of nested children changing each time.)--> 
    <div> <!--Second nested child (Can have potentially infinite sub-nests like first, second, etc.)--> 
     <div class="block"> <!--Select this --> 
     Select 
      <div> 
       <div class="block"> <!--DONT select this --> 
       Don't select 
        <div class="section"> 
         <div> <!--More unknown nestings to an assumed infinite degree--> 
          <div class="block"> <!--Select this--> 
          Select 
           <div> 
            <div class="block">Don't select</div> <!--DONT select this --> 
           </div> 
          </div> 
         </div> 
        </div> 
       </div> 
      </div> 
     </div> 
    </div> 
</div> 
<div> 
    <div> 
     <div class="block"> <!--Select this --> 
     Select 
      <div> 
       <div class="block"> <!--DONT select this --> 
       Don't select 
        <div class="section"> 
         <div> <!--More unknown nestings to an assumed infinite degree--> 
          <div class="block"> <!--Select this--> 
          Select 
           <div> 
            <div class="block">Don't select</div> <!--DONT select this --> 
           </div> 
          </div> 
         </div> 
        </div> 
       </div> 
      </div> 
     </div> 
    </div> 
</div> 
</div> 

這看起來非常可怕,但這個想法是,我們只希望在任何孩子選擇第一次出現,並在那之後沒了。

我明顯喜歡CSS來做這個選擇,但是如果需要我們可以使用jQuery選擇器。我不確定在CSS中是否可行。

小提琴你一起玩:https://jsfiddle.net/78b3c6xh/1/

有三種解決這個問題。我選擇了來自Arman P.的純粹的CSS作爲答案,因爲這是問題偏好的問題,也是最快和最簡單的解決方案。

第二好的來自Susanne Peng,由於jQuery的簡單性和最少的使用。不確定效率,但它工作。

第三個是ibrahim mahrir誰是第一個解決,並利用自定義JavaScript函數依賴於jQuery。

如果可能的話,在這種情況下推薦使用CSS解決方案。工作小提琴解決方案是在該答案的評論。

+0

試着用更好的例子更清楚你想要什麼。我無法得到你想要的東西。 –

+0

我已經回答了你的問題。但後來我回過頭來閱讀你提供的HTML代碼的評論,我開始懷疑這不是正確的答案。所以你只需要'.section'子樹的第一個'.block'元素。對? –

+0

@ibrahimmahrir這是正確的。看到我評論你的答案的小提琴。 – forrestmid

回答

2

我不相信這是可能的只是CSS。

使用jQuery A液:

$('.section').each(function() { 
    $(this).find('.block').first().css('color', 'blue'); 
}); 

小提琴這裏:https://jsfiddle.net/78b3c6xh/2/

如果有可能是下一個.section發現多個子.block是你可以採取的方法是這樣的:

$('.block').each(function() { 
    var $closest = $(this).parent().closest('.section, .block'); 
    if ($closest.hasClass('section')) $(this).css('color', 'blue'); 
}); 

小提琴在這裏:https://jsfiddle.net/78b3c6xh/5/

+0

不完全。檢查這個小提琴。 https://jsfiddle.net/78b3c6xh/4/它看起來像不在每個'.section'中選擇多個'.block' – forrestmid

1

這是工作:

$(function(){ 
    // get the depth 
    var count = $(".section").length; 
    // array of matched elements 
    var elements = []; 

    // generate a selector for the '.section' that has a depth of 'depth' 
    function getSelector(depth){ 
     var selector = ""; 
     for(var i = 0; i < depth; i++) 
      selector += ".section "; 
     return selector; 
    } 

    // for each depth select only the first '.block' level of that depth 
    for(var i = 0; i < count; i++){ 
     // selector for the '.section' on this depth 
     var selector = getSelector(i + 1); 
     // select the '.block' of this depth that aren't children of other '.block' of this depth too. 
     $(selector + ".block").not(selector + ".block .block").each(function(){ 
      // push all the matched element into the array 
      elements.push(this); 
     }); 
    } 

    console.log(elements); 
}); 

例:

你的CSS是錯誤的看到這個例子中它的工作原理:

$(function() { 
 
    // get the depth 
 
    var count = $(".section").length; 
 
    // array of matched elements 
 
    var elements = []; 
 

 
    // generate a selector for the '.section' that has a depth of 'depth' 
 
    function getSelector(depth) { 
 
    var selector = ""; 
 
    for (var i = 0; i < depth; i++) 
 
     selector += ".section "; 
 
    return selector; 
 
    } 
 

 
    // for each depth select only the first '.block' level of that depth 
 
    for (var i = 0; i < count; i++) { 
 
    // selector for the '.section' on this depth 
 
    var selector = getSelector(i + 1); 
 
    // select the '.block' of this depth that aren't children of other '.block' of this depth too. 
 
    $(selector + ".block").not(selector + ".block .block").each(function() { 
 
     // push all the matched element into the array 
 
     $(this).addClass('selected'); 
 
    }); 
 
    } 
 
});
.block { 
 
    color: red; 
 
} 
 
.block.selected { 
 
    color: blue; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div class="section"> 
 
    <div> 
 
    <!--First nested child (Take this and repeat as many times as you want within the parent 'section' class, structure of nested children changing each time.)--> 
 
    <div> 
 
     <!--Second nested child (Can have potentially infinite sub-nests like first, second, etc.)--> 
 
     <div class="block"> 
 
     <!--Select this --> 
 
     Select 
 
     <div> 
 
      <div class="block"> 
 
      <!--DONT select this --> 
 
      Don't select 
 
      <div class="section"> 
 
       <div> 
 
       <!--More unknown nestings to an assumed infinite degree--> 
 
       <div class="block"> 
 
        <!--Select this--> 
 
        Select 
 
        <div> 
 
        <div class="block">Don't select</div> 
 
        <!--DONT select this --> 
 
        </div> 
 
       </div> 
 
       </div> 
 
      </div> 
 
      </div> 
 
     </div> 
 
     </div> 
 
    </div> 
 
    </div> 
 
    <div> 
 
    <div> 
 
     <div class="block"> 
 
     <!--Select this --> 
 
     Select 
 
     <div> 
 
      <div class="block"> 
 
      <!--DONT select this --> 
 
      Don't select 
 
      <div class="section"> 
 
       <div> 
 
       <!--More unknown nestings to an assumed infinite degree--> 
 
       <div class="block"> 
 
        <!--Select this--> 
 
        Select 
 
        <div> 
 
        <div class="block">Don't select</div> 
 
        <!--DONT select this --> 
 
        </div> 
 
       </div> 
 
       </div> 
 
       <div> 
 
       <!--More unknown nestings to an assumed infinite degree--> 
 
       <div class="block"> 
 
        <!--Select this--> 
 
        Select 
 
        <div> 
 
        <div class="block">Don't select</div> 
 
        <!--DONT select this --> 
 
        </div> 
 
       </div> 
 
       </div> 
 
      </div> 
 
      </div> 
 
     </div> 
 
     </div> 
 
    </div> 
 
    </div> 
 
</div>

+0

我不相信這會起作用。 https://jsfiddle.net/78b3c6xh/ – forrestmid

+0

我也拒絕了標題建議,因爲我不認爲它準確地代表了問題。 – forrestmid

+0

@forrestmid檢查新的答案,它給出你想要的結果。 –

0

除非我錯過了什麼,爲什麼不會querySelector工作?它搜索與選擇器查詢匹配的第一個元素。 這確實只是一個知道如何編寫正確CSS selectors的問題。

另請注意,當您有節點引用時,您將始終通過該引用訪問後代節點。這就是DOM的本質。

document.querySelector("button").addEventListener("click", function(){ 
 
    var selector = document.getElementById("query").value; 
 
    var node = document.querySelector(selector); 
 
    var childNodes = node.querySelector("*"); 
 
    console.log("Found node: " + node); 
 
    console.log("Node contents: " + node.innerHTML); 
 

 
    node.setAttribute("class", "special"); 
 
    childNodes.setAttribute("class", "normal"); 
 

 
});
code.q { font-weight:bold; color:#f00; } 
 

 
.special { color:#0f0; } 
 
.normal { color:#000; }
<div class="section"> 
 
<div> <!--First nested child (Take this and repeat as many times as you want within the parent 'section' class, structure of nested children changing each time.)--> 
 
    <div> <!--Second nested child (Can have potentially infinite sub-nests like first, second, etc.)--> 
 
     <div class="block"> Select this 
 
      <div> 
 
       <div class="block"> DONT select this 
 
        <div class="section"> 
 
         <div> <!--More unknown nestings to an assumed infinite degree--> 
 
          <div class="block"> Select this 
 
           <div> 
 
            <div class="block"></div> DONT select this 
 
           </div> 
 
          </div> 
 
         </div> 
 
        </div> 
 
       </div> 
 
      </div> 
 
     </div> 
 
    </div> 
 
</div> 
 
</div> 
 
<p>You can get whatever node you want, regardless of the DOM structure, you just have to know how to write your CSS selectors properly.</p> 
 
<ul> 
 
    <li>To get the first <code class="q">.block</code>, the selector would be: <code class="q">.block</code></li> 
 
    <li>To get the third nested <code class="q">.block</code>, the selector would be: <code class="q">.block .block .block</code></li> 
 
</ul> 
 
<input type="text" id="query" value=".block"> 
 
<button>Search!</button>

+0

這是可能的工作,但我只有.section和.block選擇器,期間。我不知道這個街區有多少嵌套的孩子。另外,如果'querySelector'只選擇第一次迭代,它將不起作用。我需要它來選擇所有迭代,它們是第一個找到的子節點,不管是嵌套,還是.section中的.block。那有意義嗎? – forrestmid

+0

因此,該搜索函數返回發生的第一個'.section .block',但不是'.section .block .block .section .block',而不是我在編輯中添加的第二個'.section .block'。 – forrestmid

+0

看起來這只是選擇第一個可見的「選擇此」而不是第二個,它嵌套在第二個部分中。它需要搜索每個部分,並找到每個部分中的所有第一個塊,但不能激活那些類爲'.block'的塊的子項。 – forrestmid

0

以下CSS選擇按照當前提供的HTML工作,但不確定它是否可能會在其他情況下失敗,這取決於嵌套的樣子。

.section .block{ 
    color: red; 
} 

.section > * > .block, .section > * > * > .block{ 
    color: blue; 
} 

https://jsfiddle.net/3owtetfb/1/

它也可以「反向選擇」,我相信會更準確地工作,如果嵌套是不規則的,請參閱: https://jsfiddle.net/xqf0u40r/

+0

就像我所說的,嵌套是完全未知的。這隻有在已知嵌套時纔有效,但在涉及多個「.section」時嵌套可能會更改。 – forrestmid

0

你就需要這個CSS選擇,我瞭解: 查看下面的工作示例

.section .block { 
 
    color: red; 
 
} 
 

 
*:not(.block) > *:not(.block) > .block, 
 
.section > .block { 
 
    color: blue; 
 
}
<div class="section"> 
 
<div> <!--First nested child (Take this and repeat as many times as you want within the parent 'section' class, structure of nested children changing each time.)--> 
 
    <div> <!--Second nested child (Can have potentially infinite sub-nests like first, second, etc.)--> 
 
     <div class="block"> <!--Select this --> 
 
     Select 
 
      <div> 
 
       <div class="block"> <!--DONT select this --> 
 
       Don't select 
 
        <div class="section"> 
 
         <div class="block"> <!--Select this--> 
 
         Select 
 
         <div> 
 
          <div class="block">Don't select</div> <!--DONT select this --> 
 
         </div> 
 
         </div> 
 
        </div> 
 
       </div> 
 
      </div> 
 
     </div> 
 
    </div> 
 
</div> 
 
<div> 
 
    <div> 
 
     <div class="block"> <!--Select this --> 
 
     Select 
 
      <div> 
 
       <div class="block"> <!--DONT select this --> 
 
       Don't select 
 
        <div class="section"> 
 
         <div> <!--More unknown nestings to an assumed infinite degree--> 
 
          <div> 
 
          <div class="block"> <!--Select this--> 
 
          Select 
 
           <div> 
 
            <div class="block">Don't select</div> <!--DONT select this --> 
 
           </div> 
 
          </div> 
 
          </div> 
 
         </div> 
 
         <div> <!--More unknown nestings to an assumed infinite degree--> 
 
          <div> 
 
          <div class="block"> <!--Select this--> 
 
          Select 
 
           <div> 
 
            <div class="block">Don't select</div> <!--DONT select this --> 
 
           </div> 
 
          </div> 
 
          </div> 
 
         </div> 
 
        </div> 
 
       </div> 
 
      </div> 
 
     </div> 
 
    </div> 
 
</div> 
 
</div>

+0

'divs'無所謂,我已經更新了我的答案以忽略標籤。但我在你的小提琴中看到你想要選擇'.block'的孩子,你確定嗎? –

+0

是的,你知道了。使用CSS工作小提琴https://jsfiddle.net/78b3c6xh/10/抱歉回合! – forrestmid

+0

如果你有一個標題的建議,請製作它。這對於其他用戶來說很難找到這樣一個怪物頭銜。 – forrestmid