Selecting Elements by Data Attributes Using Jquery

css
Selecting elements by their data attributes is a handy feature of Jquery. But a word of caution: Using Jquery's **.data()** method to change the attribute value will only change the values in memory, and not on the actual DOM. If the attribute value changes somewhere else in your code, it can lead to some head scratching.

Let's look at an example.

This is our list of animals. Our dogs have grown flippers and acquired a voracious appetite for fleshy, fatty Omega-3, and we need to update them with a more descriptive title.

<ul>
  <li data-animal="dog">Dog</li>
  <li data-animal="dog">Dog</li>
  <li data-animal="raccoon">Raccoon</li>
  <li data-animal="cat">Cat</li>
  <li data-animal="cat">Cat</li>
</ul>

We can get the dogs by using a Jquery data attribute selector, like this:

var dogs = $("li[data-animal='dog']");

console.log(dogs.length);

//output: 2

From the output, we can see that the selector is working and returned the correct number of dogs. We should be able to just update the attributes using the .data() method, right?

dogs.data("animal","seal");

dogs.each(function(){
  $(this).text("seal");
});

console.log(dogs);

/*
Output:
Object {animal: "seal"}
Object {animal: "seal"}
Object {animal: "raccoon"}
Object {animal: "cat"}
Object {animal: "cat"}
*/

Technically, yes. But what happens if we need to change the text color to blue? You know, since seals live in water. So let's revise our selector to get the attributes by data-animal='seal'

var seals = $("li[data-animal='seal']");

console.log(seals.length);

//Output: 0

Jquery updated the data attributes in memory, but the DOM remains unchanged. If we look at our list element again, we can see that the 'data-animal' attributes are still set to dog.

<ul>
  <li data-animal="dog">seal</li>
  <li data-animal="dog">seal</li>
  <li data-animal="raccoon">Raccoon</li>
  <li data-animal="cat">Cat</li>
  <li data-animal="cat">Cat</li>
</ul>

In order for the attribute selector to work, we need to update the attributes in the DOM using Jquery's .attr() method. Depending on what your code does, you may only need to use the .attr() method or the data() method. (Or to refactor.)

var seals = $("li[data-animal='dog']")
            .data("animal","seal")
            .attr("data-animal",'seal');

console.log(seals.length);

//output: 2

And there was much rejoicing.

<ul>
  <li data-animal="seal">seal</li>
  <li data-animal="seal">seal</li>
  <li data-animal="raccoon">Raccoon</li>
  <li data-animal="cat">Cat</li>
  <li data-animal="cat">Cat</li>
</ul>

If you run into this issue with data-attribute selectors, avoid spending an anxiety-stricken, overcaffinated afternoon scouring Stackoverflow and remember that Jquery's .data() method only changes attribute values in memory, and not in the DOM.

View my example: http://codepen.io/toymaker/pen/ZQEJGJ/
For reference: http://stackoverflow.com/questions/2891452/jquery-data-selector