//

Thursday, July 4, 2019

Navigate the DOM with jQuery

Parent child relationships

Navigating the DOM with jQuery

CSS offers quite a bit of power when it comes to selecting items. However, there are a couple of limitations. First, CSS selectors aren't dynamic; if new items are added later those new items aren't part of the selection. Second, there are times when it's just easier to express the items you want programatically rather than using CSS. Fortunately, jQuery allows us to select items by using code as well.
jQuery offers two methods that allow you to locate children or descendents of the currently selected element.

The first is children, which will allow you to select, or search through, all direct descendents of the currently selected item. Keep in mind that children will only work with direct children of the current element; anything further down the hierarchy will not be considered when using children.
children also accepts an optional CSS selector. This allows you to filter children using the same syntax we covered earlier. Consider a navelement with multiple a elements as children. You may want to select all a elements that have an href attribute starting with http://, which would indicate the link refers to an external site. You could select just those a elements by using the following syntax:

currentElement.children('a[href^="http://"]');
As mentioned earlier, children only applies to direct descendents. If you need to look throughout the entire hierarchy below the currently selected element, you use the find method. find works just like children, with the only difference being that find will look beyond direct children of the current element. Just like childrenfind also accepts a selector for filtering.
Consider the following HTML.

<nav id="navigation">
    <ul>
        <li><a href="http://www.microsoft.com">Microsoft</a></li>
        <li><a href="http://www.adventure-works.com">AdventureWorks</a></li>
        <li><a href="register">Register</a></li>
    </ul>
</nav>
If we needed to select all a elements under the nav element we couldn't use children. This is where find comes into play. And, just like before, if we only wanted the a elements that had an href that started with http://, we could add in the CSS selector to filter.

// select the nav element by its ID
var navigation = $('#navigation');

// select all a elements with an href that starts with http://
navigation.find('a[href^="http://"]')

Siblings

Many sections of an HTML page have a consistent structure. For example, most forms will have a label, followed by an input element, followed by a placeholder for an error message.

<div>
    <label for="name">Name:</label>
    <input type="text" id="name" />
    <div id="name-error"></div>
</div>
Imagine a bit of jQuery code where you had a reference to the input element, and you were performing a bit of validation. You would want to display any error message in the div element immediately following the input tag. While you could explicitly get a reference to the div element by its ID, that code wouldn't be reusable.
If your site maintained that structure of labelinputdiv, you could create generic event handlers, and update the error message simply by using that consistent structure to your advantage.

prev and next

Image a bit of jQuery code to grab the input element.

var currentInput = $('name');
To move to the prior element, jQuery provides the prev method. You can use prev() to access the prior element in the hierarchy (the label in the example). If you wanted the div element to update the error message, which follows the input element, you would use next()

// text allows you to modify the text in an element
curentInput.next().text('error message');
As with most methods used to select items in jQuery, both prev and next support CSS selectors.

prevAll and nextAll

prev and next only look at the item immediately prior or after, respectively. prevAll and nextAll will select all siblings prior or after the element. Both methods also accept a CSS selector to limit the items.
Imagine a form with a checkbox, where upon selection you need to enable the two textboxes and labels immediately following it.

<label for="provide-address">Provide address?</label>
<input type="checkbox" id="provide-address" />

<label for="street">Street:</label>
<input type="text" id="street" disabled="true" />

<label for="country">Country:</label>
<input type="text" id="country" disabled="true" />
You could enable the textboxes by using the following jQuery:

// The attr method is used to set (or read) an attribute
// The first parameter is the name of the attribute, the second is the value to set

// Since we only need input elements, we'll use the name of the tag as the filter
$('#provide-address').nextAll('input').attr('disabled', 'true');
Disabled attribute One interesting note about the disabled attribute is that it's one of the attributes that, according to the HTML specification, does not require a key/value pair. As a result, simply using <input disabled type="text" /> would disable the textbox. However, this wouldn't be valid XML syntax. As a result, I personally prefer to use either disabled="true" or disabled="disabled" to ensure a key/value pair and well-formed XML.

prevUntil and nextUntil

Finally, prevUntil and nextUntil select all prior or following elements up to, but not including the element that matches the selector.
Selecting items by position

When creating a dynamic UI, you might not know anything else about an item other than its position. jQuery offers you the ability to both locate an item by its position in a collection, or to find out the index location of an item.

Finding the index of an item

If you have a reference to an object, but need to know where it sits in a collection of items, you can use the index method. The index method will return the zero based (ordinal) location of the item, or -1 if the item isn't found.

var currentElement = $('some selector');
var parent = $('some selector');
var index = parent.children().index(currentElement);

Finding an item by its position

If you know the zero based (ordinal) location of an item in a collection, you can obtain a reference to that item by using the get method.

var parent = $('some selector');
var element = parent.children().get(index);
get return type
One important note about get is it returns a JavaScript DOM object, not a jQuery object. This means the various jQuery methods, such as attrand text are not available. In order to call jQuery methods on the object, you must convert it to a jQuery object. Fortunately, this is just as easy as passing the object into the jQuery constructor. The above code would become:

var parent = $('some selector');
var element = parent.children().get(index);
var jQueryObject = $(element);
Or, you could distill it down to two lines

var parent = $('some selector');
var jQueryObject = $(parent.children().get(index));
Or, I suppose, down to one line.

var jQueryObject = $($('some selector').children().get(index));
It's all just a matter of personal preference.

Interactive Demo



See the Pen Interactive demo of jQuery tree traversal methods by Christopher Harrison (@GeekTrainer) on CodePen.

No comments:

Post a Comment

Effective Branching Strategies in Development Teams

Effective Branching Strategies in Development Teams Effective Branching Strategies in Developme...