The Black Magic of HTML5 Data Attributes

Okay, so, rewind to about a year and a half ago, when I was lying on the sofa, having a whine about my retail job du jour, and remembered that I actually had some skills outside of smiling and accepting the blame for my store being out of arbitrarily-sized t-shirts. This train of thought ended up with a friend of mine sending me copies of a couple front-end ebooks to get me up to speed on HTML5 (which had just come out) and CSS3, since I was a little out of date with what was going on in the Great Big Hello World of Web Development.

So, I’m reading this HTML5 book, all like:

But, there was one thing that it either didn’t cover, or—more likely—I got bored and quit reading before I got that part, because it wasn’t like I couldn’t already HTML, and reading about HTML is not the most exciting thing on Earth. (Also, HTML is now a verb, I’ve decided.) The thing that I missed? Data attributes, or, as they are also known, black freakin’ magic. The first time I saw them being used, I was like:

…look, kids, back in the day, we had to come up with weird names for CSS classes and use JavaScript to parse them into something meaningful if we wanted data available in the DOM. Now, you just prefix with “data-*” on an element, and you can store whatever the heck kind of string you want in there (within reason). You can store JSON in it, for example, which is just—whaaaaaat, where has this been all my life? (Or maybe not—HTML5 is only two years old, so for the vast majority of my life it hasn’t existed… still, have I totally been living under a rock for two years?!)

So now, say I have an unordered list, and I want to grab a value (or several values) and display it when the user selects a list item, without making an Ajax call or querying a database or any of that nonsense. I’ll just stick my data in some data attributes—let’s call them “data-registration-number”, “data-color”, and “data-codename”:

  • <ul id="nonsenseList">
    
     <li data-registration-number="1701" data-color="yellow"
    
     data-codename="Enterprise">Nonsense</li> 
    
     <li data-registration-number="74656" data-color="blue"
    
     data-codename="Voyager">More Nonsense</li>
    
     <li data-registration-number="74205" data-color="red"
    
     data-codename="Defiant">Even More Nonsense</li>
    
     </ul>

So now, I can use JavaScript to grab one of those values from my list items, and use it however I want:

<script> 
//this first script uses the element.getAttribute() function to nab the value from our data attribute:
var nonsenseList = document.getElementById("nonsenseList"); 
var firstItem = nonsenseList.children[0]; 
firstItem.onmouseover = function(){ 
 var regNumber = firstItem.getAttribute("data-registration-number"); 
 window.alert("Registration Number: " + regNumber); 
}; 
</script>

Admittedly, this is a pretty lame example with little/no practical application. The point is, I was able to tell my script to get the value of the attribute named “data-number” off a particular element, and it did. You should note that in order to have to a valid data attribute, the attribute name must be prefixed with “data-”, have at least one character after the first hyphen, be XML-compatible, and contain no uppercase ASCII letters (as per w3 spec for HTML documents, read more here).

But wait! There’s more. There is actually an even better way to access what is stored in your data attributes, and it’s through the new HTML5 dataset API. This API exposes an element attribute named dataset, which returns a DOMStringMap object. The DOMStringMap keys are the names of the data attributes (without the “data-” prefix), and the corresponding values are the string values contained in the attributes themselves. If the data attribute name is made of multiple words (like our data-registration-number), it’s converted to camelCase (in this case, registrationNumber). The dataset API is dead simple to use, too—just call it using dot notation on a chosen element:

<script>
//let's try it again using the dataset API:
var nonsenseList = document.getElementById("nonsenseList"); 
var secondItem = nonsenseList.children[1]; 
secondItem.onmouseover = function(){
 var regNumber = secondItem.dataset.registrationNumber; 
 window.alert("Registration Number: " + regNumber); 
}; 
</script>

The dataset API is widely supported in modern desktop and mobile browsers (aside from in Internet Explorer, which only supports it in IE11, because it’s Internet Explorer). There is a shim out there for it (only a Google search away), but if you’re concerned about compatibility, you can always fall back on using more vanilla Javascript functions like getAttribute(). I’ve also read that using the dataset API is slower, but unless you’ve got a load of stuff stored in your attributes or need to read out of a whole bunch of them very quickly, performance shouldn’t be a concern—and, side note, if this is an issue, it’s my opinion that you’re probably weighing down the DOM with too much data, and need to rethink your architecture.

Another side note: data attributes should only be used when a suitable HTML5 element or attribute does not already exist. Additionally, unlike microformats, data attributes are meant to be private—that is, they are not intended to be read by outside software, and are meant only for custom data in the context of the site they are located on. Data attributes are meant to be used by the site’s own scripts, meaning that you shouldn’t be implementing them to store publicly-usable metadata. If you want to do that, use microformats, that’s what they’re for!

If you’d like to try it with some quick and dirty code, here’s the pointlessness that I threw together for this post–feel free to pop it into your editor of choice and use it as a starting point for playing around with data attributes:

<html> 
<head>
 <!--doing some quick/dirty styling so that things aren't as ugly-->
 <link href="https://fonts.googleapis.com/css?family=Homemade+Apple" rel="stylesheet"> 
 <style>
 .container { 
 width: 25%; 
 text-align: center;
 }
 li { 
 display: block; 
 margin: 10%; 
 padding: 10%;
 border: 5px solid black; 
 border-radius: 10px;
 font-family: 'Homemade Apple', cursive;
 }
 </style>
</head>
<body>
 <div class="container">
 <ul id="nonsenseList">
 <li data-registration-number="1701" data-color="yellow"
 data-codename="Enterprise">Nonsense</li> 
 <li data-registration-number="74656" data-color="blue"
 data-codename="Voyager">More Nonsense</li>
 <li data-registration-number="74205" data-color="red"
 data-codename="Defiant">Even More Nonsense</li>
 </ul>
 </div>
</body>
</html>

<script> 
//this first script uses the element.getAttribute() function to nab the value from our data attribute:
var nonsenseList = document.getElementById("nonsenseList"); 
var firstItem = nonsenseList.children[0]; 
firstItem.onmouseover = function(){ 
 var regNumber = firstItem.getAttribute("data-registration-number"); 
 window.alert("Registration Number: " + regNumber); 
}; 
</script>

<script>
//let's try it again using the dataset API:
var nonsenseList = document.getElementById("nonsenseList"); 
var secondItem = nonsenseList.children[1]; 
secondItem.onmouseover = function(){
 var regNumber = secondItem.dataset.registrationNumber; 
 window.alert("Registration Number: " + regNumber); 
}; 
</script>

Burnout & Broken Things

As 2016 wraps up, I’ve been waxing nostalgic about the past few years. I moved back to Cleveland from England on August 15, 2014; my divorce was finalized December 15 that same year, and I graduated from bootcamp on December 12, 2015—almost a year later. The disastrous culmination of my first tech interview process on December 30, 2015 taught me enough to fully recover for the next one, which resulted in a job offer from Hyland with start date of Februrary 22, 2016. I’ve been able to pull all of those dates right off the top of my head, somehow, even though I literally have to stop and think before telling people the date of my child’s birthday (March 3, May 5, same thing—right?).

The thing is, there’s a lot out there about how to live your best life—how to get a decent job, how to ditch your abusive partner, how to de-stress, eat right, exercise, meditate, how to dress for success, how to wing your eyeliner, how to clean dog puke out of upholstery. There’s all sorts of ways to get there–Google it, and you’ll find it. What no one seems to have is any advice for it what comes afterward… when you’re sure that you’re fierce and independent and capable, and suddenly, you’re sitting in front of an auditorium full of people with a microphone in your lap, and someone in the crowd raises their hand and say, “this is a question for Tori,” because they’ve decided that they want their best life, too, and they think you have the answers they’re looking for.

In a nutshell: 2016 has been both extremely rewarding, and utterly terrifying. I got a job—a full-time job, at a company that hired me for reasons other than that I’m capable of showing up on time and speaking in full sentences. After two years, I was finally able to pack up and move my kid, my dog, and myself out of my parents’ spare bedroom and into a house. I don’t worry about making my son’s school tuition payments, let alone worry that I’m not going to be able to afford medicine or food.

I’ve done this with the realization that if I hadn’t had my parents’ patience (and their spare bedroom), at least one good friend (hi, Dave), and someone to loan me $9,000 without even checking my beyond-terrible credit score (thanks, WCCI), this might not have played out so well. Even with the advantages, I still had to ask Hyland to move my start date up two weeks from their initial offer, because I had run out of money to keep putting gas in the car. Truth is, there are many, many people who had it far, far worse than I had it—which is exactly why I need to have answers when someone says, “this is a question for Tori”, because hard is hard, and I’m going to offer whatever slivers of hope and strength I can.

An apprentice at We Can Code IT contacted me recently and offered to take me out for coffee. If we do end up going for coffee, she’s not paying for it. She’s paying nine thousand dollars already; there’s no way she needs to spend an extra two bucks on buying her mentor a cup of coffee. I’ll buy my coffee, I’ll buy her coffee, I’ll buy pastries if she wants one. I’ve realized that you don’t just get out what you put in—once you climb the mountain, the good thing to do is to turn around and reach down to help the next person.

2016 has been humbling. I’ve also spent the last few months of the year fighting with a bout of anemia brought on by switching out one of my medications, which is its own special version of terrible. I’ve had to drop projects I was excited about, and push myself to finish others while exhausted. Good news, though—I’m a month into taking iron supplements, and I almost feel ready to try out some short hikes again. Strapping on a pack and putting down substantial miles is still a bit far off, but getting the boots on for a couple miles in the park is beginning to sound appealing again. Some of the things I had to drop off in 2016 should see new efforts in 2017, which I’m finally excited over (instead of exhausted just thinking about).

The title? Burnout, obviously, from the anemia—trying to do too much while my body wasn’t getting what it needed. I spent a couple months insisting that I was fine, and that my elevated heart-rate and constant fatigue were from stress and not having time to hike on weekends. In retrospect, that was ridiculous, because I had plenty of time to hike on weekends, I just wasn’t able to make it out of bed. I did force myself to Philadelpha for Ela Conf, which was very much worth it, and to attend a few events and start a couple of projects, but the physical cost was pretty great. Thankfully, I shouldn’t have to deal with it very much longer. Broken things, though—that’s a little more introspective. I’ve spent a long time identifying myself by what was wrong with my life—no money, no job/bad job/low-paying job, bad relationship, etc. There is still plenty wrong with my life (debt up my eyeballs, I live in a bad rom-com, my dog likes to eat things she shouldn’t), but I’ve quit defining myself by it. This has been the year that I finally started defining myself by the things I’ve accomplished and the things I enjoy, not the things that I don’t have or the things I’m not good at. That’s a lesson I want to share with people going forward.

There’s 2016 wrapped up neatly, let’s put on a bow on it and move on.