How to find elements that are not deeper than a selector?
Asked Answered
C

2

7

I am building a jQuery plugin to manage form collections. The plugin aims to add add, remove, move up and move down buttons to alter that collection.

  • A collection's root node always contains a selector, such as .collection.

  • A button can be anything as soon as it has the .add class

I implemented min and max options, so add and remove buttons disappear accordingly. My problem comes up when I try to manage a collection of form collections: how to select only the add buttons that refers to the right collection?

To simplify the problem, look at the following HTML code:

<div class="collection">
  <div>something</div>
  <div>something</div>
  <div>
    <div class="add">+</div>
  </div>
  <div>something</div>
  <div class="collection">
    <div>something</div>
    <div>something</div>
    <div>
      <div class="add">+</div>
    </div>
    <div>something</div>
  </div>
</div>

Keep in mind that the button can be arbitrary deep: collection is built by an user and I don't know where can be the button in the dom. BTW, it is deeper than the .collection, that's all I know.

How to select all add buttons until the second .collection, but not further?

For those interested, this plugin is available (but in active dev) here.

Chatelaine answered 28/2, 2015 at 17:24 Comment(4)
Select all .add, select all .collection .collection .collection .add, remove intersectionMighell
"How to select all add buttons until the second .collection, but not further?" At html , would that be one .add element ?Triumvir
@PaulS. there can be an arbitrary number of collections that encapsulate collections (even if that would be very strange to create collection of collections of collections iMHO).Chatelaine
@guest271314, this is useful sometimes to put 2 add buttons (one at the left and one at the right side for example).Chatelaine
C
5

I will assume you have a reference to the .collection object that you want to find the add buttons for in a variable called target. If so, you can do it like this:

target.find(".add").filter(function(i, element) {
   return $(element).closest(".collection").get(0) === target.get(0);
});

This finds all the .add buttons that are in a given .collection and then removes any who are contained in a nested .collection instead of directly in the target .collection.

Carl answered 28/2, 2015 at 17:46 Comment(2)
I did not noticed that .closest() were using ancestors only. Very interesting. Thanks.Chatelaine
@AlainTiemblo - I made a change to the code because I think it has to compare DOM elements, not jQuery objects.Carl
T
3

Try

$(".add").not($(".collection:gt(0) .add"));

Note,

Utilizing jQuery .not()'s .not( selector ) , where selector is selctor string

.not( selector ) version added: 1.0

selector Type: Selector or Element or Array A string containing a selector expression, a DOM element, or an array of elements to match against the set.

$(".add").not(".collection:gt(0) .add") http://jsfiddle.net/47wc5L96/21/

did not appear to return same results as .not( selection ) , where selection is jQuery object

.not( selection ) version added: 1.4

selection Type: jQuery An existing jQuery object to match the current set of elements against.

$(".add").not($(".collection:gt(0) .add")); http://jsfiddle.net/47wc5L96/20/


console.log($(".add").not($(".collection:gt(0) .add")));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div class="collection">
  <div>something</div>
  <div>something</div>
  <div>
<div class="add">+</div>
  </div>
  <div>something</div>
  <div class="collection">
<div>something</div>
<div>something</div>
<div>
  <div class="add">+</div>
</div>
<div>something</div>
  </div>
</div>
Triumvir answered 28/2, 2015 at 17:49 Comment(3)
Hmm, looks working great for the top collection, but if I try to get add buttons from the 2nd one like this: jsfiddle.net/47wc5L96/25 --- Sorry :pChatelaine
@AlainTiemblo The top collection is perhaps interesting one to filter , as it contains nested collections having same class ; requiring removal of non-selected elements having parent container class. Nested , inner collections could be selected relatively directly jsfiddle.net/47wc5L96/26Triumvir
I know but that's not true, because I do not know how many nested collections I can have. Imagine I have a form that describe a REST response, letting user to choose between 3 fields: key, value and node, with a node that can contain an arbitrary number of nested key/value/node. We can imagine that the response will get deeper than 2 elements. BTW, don't worry, this is too complex to do that in jQuery (spent my day on it), I finally opted for distinct button's class prefixes for each collection. Thanks for ur time!Chatelaine

© 2022 - 2024 — McMap. All rights reserved.