title: Skip recursion in jQuery.find() for a selector?
body: <p>TL;DR: <strong>How do I get an action like find(), but block traversal (not full stop, just skip) for a certain selector?</strong> </p>
  
  <p><strong>ANSWERS: <code>$(Any).find(Selector).not( $(Any).find(Mask).find(Selector) )</code></strong></p>
  
  <blockquote>
    <p>There were many truly great answers, I wish I could some how distribute the bounty points more, maybe I should make some 50 pt bounties in response to some of these ;p I choose <a href="https://stackoverflow.com/a/24314604/578023">Karl-André Gagnon's</a> because this answer managed to make findExclude unrequired in one, slightly long, line. While this uses three find calls and a heavy not filter, in most situations jQuery can use very fast implementation that skips traversal for most find()s.</p>
    
    <p>Especially good answers are listed below:</p>
    
    <p><a href="https://stackoverflow.com/a/24312203/578023">falsarella</a>: Good improvement on <a href="https://stackoverflow.com/q/24159478/578023">my solution</a>, findExclude(), best in many situatoins</p>
    
    <p><a href="https://stackoverflow.com/a/24295558/578023">Zbyszek</a>: A filter-based solution similar to falsarella's, also good on efficiency</p>
    
    <p><a href="https://stackoverflow.com/a/24298600/578023">Justin</a>: A completely different, but manageable and functional solution to the underlaying issues</p>
    
    <p>Each of these have their own unique merits and and are deserving of some mention.</p>
  </blockquote>
  
  <p>I need to descend into an element fully and compare selectors, returning all matched selectors as an array, but skip descending into the tree when another selector is encountered.</p>
  
  <p><img src="https://i.stack.imgur.com/FAyrM.png" alt="Selection Path Illustration">
  <strong>Edit: replacing original code sample with some from my site</strong></p>
  
  <p>This is for a message forum which may have reply message-groups nested inside any message. <br>
  Notice, however, we cannot use the message or content classes because the script is also used for other components outside of the forum. Only <code>InterfaceGroup</code>, <code>Interface</code> and <code>controls</code> classes are potentially useful - and preferably just Interface and controls.</p>
  
  <p><a href="http://jsfiddle.net/LymyS/6/" rel="nofollow noreferrer">Interact with the code and see it in JS Fiddle, thanks Dave A, here</a> Click on the buttons while viewing a JavaScript console to see that the controls class is being bound to one extra time per level of .Interface nesting.</p>
  
  <p>Visual A, Forum Layout Struture:</p>
  
  <pre><code>    &lt;li class="InterfaceGroup"&gt;
          &lt;ul class="Interface Message" data-role="MessagePost" &gt;
              &lt;li class="instance"&gt; ... condensed ... &lt;/li&gt;
              &lt;li class="InterfaceGroup"&gt; ... condensed ...&lt;/li&gt;
          &lt;/ul&gt;
          &lt;ul class="Interface Message" data-role="MessagePost" &gt;
              &lt;li class="instance"&gt; ... condensed ... &lt;/li&gt;
          &lt;/ul&gt;
          &lt;ul class="Interface Message" data-role="MessagePost" &gt;
              &lt;li class="instance"&gt; ... condensed ... &lt;/li&gt;
              &lt;li class="InterfaceGroup"&gt; ... condensed ...&lt;/li&gt;
          &lt;/ul&gt;
  
      &lt;/li&gt;
  </code></pre>
  
  <p>Inside of each <code>&lt;li class="InterfaceGroup"&gt;</code> there could be any number of repetitions of the same structure (each group is a thread of messages) and/or deeper nesting such as..</p>
  
  <pre><code>    &lt;li class="InterfaceGroup"&gt;
  
          &lt;ul class="Interface Message" data-role="MessagePost" &gt;
              &lt;li class="instance"&gt; ... condensed ... &lt;/li&gt;
              &lt;li class="InterfaceGroup"&gt;
  
                  &lt;ul class="Interface Message" data-role="MessagePost" &gt;
                      &lt;li class="instance"&gt; ... condensed ... &lt;/li&gt;
                      &lt;li class="InterfaceGroup"&gt; ... condensed ...&lt;/li&gt;
                  &lt;/ul&gt;
              &lt;/li&gt;
          &lt;/ul&gt;
      &lt;/li&gt;
  </code></pre>
  
  <p>Inside of each <code>&lt;li class="instance"&gt; ... &lt;/li&gt;</code> there are arbitrary places decided by another team where <code>class="controls"</code> may appear and an event listener should be bound. Though these contain messages, other components structure their markup arbitrarily but will always have <code>.controls</code> inside of <code>.Interface</code>, which are collected into an <code>.InterfaceGroup</code>.A reduced-complexity version of the inner-content (for forum posts) is below for reference.</p>
  
  <p>Visual B, Message Contents with controls class:</p>
  
  <pre><code>&lt;ul class="Interface Message" data-role="MessagePost" &gt;
      &lt;li class="instance"&gt;
        &lt;ul class="profile"&gt; ...condensed, nothing clickable...&lt;/ul&gt;
        &lt;ul class="contents"&gt;
          &lt;li class="heading"&gt;&lt;h3&gt;Hi there!&lt;/h3&gt;&lt;/li&gt;
          &lt;li class="body"&gt;&lt;article&gt;TEST Message here&lt;/article&gt;&lt;/li&gt;
          &lt;li class="vote controls"&gt;
            &lt;button class="up" data-role="VoteUp" &gt;&lt;i class="fa fa-caret-up"&gt; &lt;/i&gt;&lt;br/&gt;1&lt;/button&gt;
            &lt;button class="down" data-role="VoteDown" &gt;0&lt;br/&gt;&lt;i class="fa fa-caret-down"&gt; &lt;/i&gt;&lt;/button&gt;
          &lt;/li&gt;
          &lt;li class="social controls"&gt;
            &lt;button class="reply-btn" data-role="ReplyButton" &gt;Reply&lt;/button&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li class="InterfaceGroup" &gt;    &lt;!-- NESTING OCCURRED --&gt;
        &lt;ul class="Interface Message" data-role="MessagePost" &gt;
            &lt;li class="instance"&gt;... condensed ... &lt;/li&gt;
            &lt;li class="InterfaceGroup" &gt;... condensed ... &lt;/li&gt;
        &lt;/ul&gt;
     &lt;/li&gt;
  &lt;/ul&gt;
  </code></pre>
  
  <p>We can only bind to controls that are <em>within an Interface class</em>, <code>instance</code> may or may not exist but Interface will. <strong>Events bubble to <code>.controls</code> elements and have a reference to the <code>.Interface</code> which holds them.</strong>.</p>
  
  <p>So I am trying to <code>$('.Interface').each( bind to any .controls not inside a deeper .Interface )</code></p>
  
  <p>That's the tricky part, because </p>
  
  <ul>
  <li><code>.Interface .controls</code> will select the same <code>.control</code> multiple times in the .each()</li>
  <li>.not('.Interface .Interface .controls') cancels out controls in any deeper nesting</li>
  </ul>
  
  <p>How can I do this using jQuery.find() or a similar jQuery method for this? </p>
  
  <p>I have been considering that, perhaps, using children with a not selector <em>could</em> work and <em>could</em> be doing the same thing as find under the hood, but I'm not so sure that it actually is or wont cause horrible performance. Still, an answer recursing .children effectively is acceptable.</p>
  
  <p><strong>UPDATE: Originally I tried to use a psuedo-example for brevity, but hopefully seeing a forum structure will help clarify the issue since they're naturally nested structures. Below I'm also posting partial javascript for reference, line two of the init function is most important.</strong></p>
  
  <p>Reduced JavaScript partial:</p>
  
  <pre><code>var Interface=function()
  {
      $elf=this;
  
      $elf.call=
      {
          init:function(Markup)
          {
              $elf.Interface = Markup;
              $elf.Controls = $(Markup).find('.controls').not('.Interface .controls');
              $elf.Controls.on('click mouseenter mouseleave', function(event){ $elf.call.events(event); });
              return $elf;
          },
          events:function(e)
          {
              var classlist = e.target.className.split(/\s+/), c=0, L=0;
              var role = $(e.target).data('role');
  
              if(e.type == 'click')
              {
                  CurrentControl=$(e.target).closest('[data-role]')[0];
                  role = $(CurrentControl).data('role');
  
                  switch(role)
                  {
                      case 'ReplyButton':console.log('Reply clicked'); break;
                      case 'VoteUp':console.log('Up vote clicked'); break;
                      case 'VoteDown':console.log('Down vote clicked'); break;
                      default: break;
                  }
              }
          }
      }
  };
  
  $(document).ready( function()
  {
      $('.Interface').each(function(instance, Markup)
      {
          Markup.Interface=new Interface().call.init(Markup);
      });
  } );
  </code></pre>