Vae Vae - 3 months ago 6
Javascript Question

How to detect which element contains all other X elements

(Hope this question hasn't been asked yet : I didn't find it via a keyword search)

I'd like to detect, using jQuery, which element (div, span, anything) contains all the other XKindOfElement.

Meaning, for example, if I have multiple checkboxes in my screen, I want to know which div contains all those checkboxes.

<div id="block1">
<div id="underblock1">
<input type="checkbox" name="thing[]" value="1" />
<div id="underunderblock1">
<input type="checkbox" name="thing[]" value="2" />
</div>
</div>
<div id="underblock2">
<input type="checkbox" name="thing[]" value="3" />
</div>
</div>


In this example, it will return the
div#block1
because only it contains all the
input[type="checkbox"]
of the page.

Hope you'll understand and could help me !

UPDATE

Thinking of something... What do you think about this process :


  1. Check if our element exists in the page

  2. If so, count how many of this element exists and save it (let's say
    count
    )

  3. Check if the parent of the first element find contains all the
    count
    elements

  4. If not, check if the parent of the parent contains all the
    count
    elements,

  5. etc

  6. When the checked parent does contain all the
    count
    elements: it is our "smallest global parent" !



Would it be ok or too slow, too "expansive"... ?

Answer

I'm not very familiar with all the jQuery helper methods, but this approach might work for you:

  • Collect all the elements you want to be included
  • Collect their parents arrays and reverse them: all these arrays now start with: html > body and continue all the way to the actual element
  • loop through a parent array and check if the other parent arrays have the same element at the current index
  • the first element that doesn't match marks the index of the last shared parent

Note: you might want to refactor the code a bit to make sure you don't run into any errors for edge cases.

var required = $("input[type=checkbox]");

var getClosestParent = function(elements) {
  var maxLength = 0;
  var allParents = [];

  elements.each(function(i, el) {
    var parents = $(el).parents().toArray().reverse();
    maxLength = Math.max(maxLength, parents.length);
    allParents.push(parents);
  });

  var ref = allParents[0];
  var others = allParents.slice(1);

  for (var i = 0; i < maxLength; i += 1) {
    for (var j = 0; j < others.length; j += 1) {
      if (ref[i] !== others[j][i]) {
        return ref[i - 1];
      }
    }
  }

  return null;
}

console.log(getClosestParent(required).id);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="block1">
  <div id="underblock1">
    <input type="checkbox" name="thing[]" value="1" />
    <div id="underunderblock1">
      <input type="checkbox" name="thing[]" value="2" />
    </div>
  </div>
  <div id="underblock2">
    <input type="checkbox" name="thing[]" value="3" />
  </div>
</div>

Comments