Cara menggunakan youngest common ancestor javascript

The requested URL was not found on this server.

Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.


Apache/2.4.41 (Ubuntu) Server at proveedores.yaguar.com.ar Port 443


With jQuery you can traverse up the DOM tree to find ancestors of an element.

An ancestor is a parent, grandparent, great-grandparent, and so on.


Traversing Up the DOM Tree

Three useful jQuery methods for traversing up the DOM tree are:

  • parent()
  • parents()
  • parentsUntil()

jQuery parent() Method

The parent() method returns the direct parent element of the selected element.

This method only traverse a single level up the DOM tree.

The following example returns the direct parent element of each <span> elements:



jQuery parents() Method

The parents() method returns all ancestor elements of the selected element, all the way up to the document's root element (<html>).

The following example returns all ancestors of all <span> elements:

You can also use an optional parameter to filter the search for ancestors.

The following example returns all ancestors of all <span> elements that are <ul> elements:


jQuery parentsUntil() Method

The parentsUntil() method returns all ancestor elements between two given arguments.

The following example returns all ancestor elements between a <span> and a <div> element:

Example

$(document).ready(function(){
  $("span").parentsUntil("div");
});

Try it Yourself »


jQuery Exercises

Test Yourself With Exercises

Exercise:

Use a jQuery method to get the direct parent of a <span> element.

Start the Exercise


jQuery Traversing Reference

For a complete overview of all jQuery Traversing methods, please go to our jQuery Traversing Reference.



Last year, I wrote about my preferred approach to event delegation. Specifically, I prefer to attach my delegated event handlers to the closest common ancestor of two or more elements. Although I don't use jQuery, the following snippet from the documentation for the on() method also applies to vanilla JS:

Attaching many delegated event handlers near the top of the document tree can degrade performance. Each time the event occurs, jQuery must compare all selectors of all attached events of that type to every element in the path from the event target up to the top of the document. For best performance, attach delegated events at a document location as close as possible to the target elements. Avoid excessive use of document or document.body for delegated events on large documents.

I normally just find the common ancestor manually, but I thought "hey, wouldn't it be cool if I could write a helper function to do this for me?"

Over the weekend, that's exactly what I did.

getCommonAncestor.js

If you just want the helper function, here it is:

/**
* Get the common ancestor of two or more elements
* {@link https://gist.github.com/kieranbarker/cd86310d0782b7c52ce90cd7f45bb3eb}
* @param {String} selector A valid CSS selector
* @returns {Element} The common ancestor
*/

function getCommonAncestor (selector) {
// Get the elements matching the selector
const elems = document.querySelectorAll(selector);

// If there are no elements, return null
if (elems.length < 1) return null;

// If there's only one element, return it
if (elems.length < 2) return elems[0];

// Otherwise, create a new Range
const range = document.createRange();

// Start at the beginning of the first element
range.setStart(elems[0], 0);

// Stop at the end of the last element
range.setEnd(
elems[elems.length - 1],
elems[elems.length - 1].childNodes.length
);

// Return the common ancestor
return range.commonAncestorContainer;
}

You can view a couple of demos on CodePen:

  • Demo 1
  • Demo 2

If you want to learn how it works, read on.

Getting the matching elements

The first thing we do is use the document.querySelectorAll() method to get a NodeList of all elements matching the CSS selector string.

If there are no matching elements, we just return null.

If there's only one matching element, then there's no point in using event delegation, so we just return it. That way, you can attach the event listener directly to the element and not bother with event delegation.

Getting the common ancestor

If there are at least two elements, then we want to get their common ancestor. To do that, we can use the Range API.

We create a Range using the document.createRange() method, then set its boundaries using the setStart() and setEnd() methods.

We want to start the range at the beginning of the first element, and stop the range at the end of the last element. The setStart() and setEnd() methods both accept two arguments:

  1. The Node to use; and
  2. An integer greater than or equal to zero representing the offset for the start/end of the Range from the start of the Node. If the Node is a Text, Comment, or CDataSection node, then it's a number of characters from the start of the Node. Otherwise, it's a number of child nodes from the start of the Node. The latter is applicable to this helper function.

For the first element, we pass the following to setStart():

  1. elems[0] — the first element
  2. 0 — the beginning of the first element

For the last element, we pass the following to setEnd():

  1. elems[elems.length - 1] — the last element
  2. elems[elems.length - 1].childNodes.length — the end of the last element

Finally, now that the Range is set, we return the common ancestor using the commonAncestorContainer property.