5 Tips for Better jQuery Code

I’ve been coding using jQuery since shortly after it came out, and well — I’ve been using it almost every work day. Here is a few tips that have saved me time.

#1: Use data method instead of storing data inside the DOM.

The mistake I see people making all the time is this:

$('selector').attr('attribute', 'this is the data that I am storing');
// then later getting that data with
$('selector').attr('attribute');

Why is this a bad thing? Because “attribute” has absolutely no meaning whatsoever.

Instead use the data method in jQuery. It allows you to associated data with an element on the page.

$('selector').data('meaningfullname', 'this is the data I am storing');
// then later getting the data with
$('selector').data('meaningfullname');

This allows you to store data with meaningful names and as much data as you want on any element on the page. It is a really amazing utility and something I’ve come to rely on.

#2: Take advantage of jQuery’s built-in custom selectors.

jQuery has a plentiful amount of selectors that are beyond basic CSS selectors, so use them. Some that I use are:

  • :input example: get all the inputs on the page regardless if they are checkbox, textarea or select list – use :input
  • [attribute=value] example: find an input with the name,“container”- use input[name='container']
  • :eq(index) example: get the fourth table on the page – use table:eq(3)

#3: If you are Manipulating the DOM a lot, use the new on syntax.

When you add elements to the page a lot, attaching events with delegation. This way you can do things like:

$(document).on('click', 'div.edit', function(){ ... });

Then whenever you add a div to the page with class “edit” it will attach that click event.

#4: Use jQuery form plugin to submit files via Ajax.

If you use Mike Alsup’s jQuery form plugin you can use it to submit files via Ajax. It uses a trick with an iframe to submit the data. Just put in an input type file, then use $(form).ajaxSubmit(); and you are good to go.

#5: Use classes as flags.

If you aren’t storing data, but need to set a flag on an element use a class. What do I mean by a flag? Well, for instance if you are in“edit mode” of a form you might use the class,“editing”. With jQuery you can add a class with the addClass method¬†and then check later if an element has the class with the hasClass method.

Update: Todd Motto has written a great article on using data attributes for state changes instead of classes. Back when I wrote this article data attributes weren’t standard in HTML5…now they are!

Comments

  1. says

    I’ve been using jQuery for a year and a half, and I have to admit I’ve never heard of the data() method; I wish I had. This is going to change things for me.

    :eq(index) has definitely come in handy many times, but I remember it took a little while for me to find it.

    I can’t even begin to count the number of times I’ve been asked, “Why don’t my event bindings work on newly added DOM elements?” I usually point people to the jQuery FAQ entry explaining it (which also suggests livequery()).

  2. says

    Mike: Everyone I’ve worked with doesn’t use the data method, so you are definitely not alone on that one. That was why I wrote these tips – I understand people know what they are doing, but some parts of the jQuery API are undiscovered by most.

  3. says

    I’ve been using jQuery for a few years now, but always viewed storing data in DOM as a bad thing, or rather some sort of a hack. I don’t see the benefits of this over storing data as plain javascript variables and in objects. Why would it be better or useful?

    The tip with using classes as flags is something I need to reconsider, thanks! Keeping flags as javascript variables is easier on the eye for me as you don’t need to refer to DOM to do anything, but perhaps the added benefit of trying do bigger things with “conditional” CSS might be worth giving it a shot.

  4. says

    Marc, good tips. I tend to rely on rel attributes for data markers.
    Did you use $.data() in the Google Maps mashup you demoed at jQuery Camp?

  5. says

    Matt Wood: I think performance is a non-issue. The real reason behind using CSS flags is that you can grab all the elements on the page that are flagged easily with a normal CSS query. Or you can also use the built-in hasClass method in jQuery to check for the flag.

    Tom Sieron: Normal JavaScript objects and variables are great for storing things! The only reason you would ever want to use the data method is if you want to associate a piece of data with a specific element on the page.

    Sean O: no I didn’t use data the method. That was just a simple demo, but you reminded me I really need to finish that tutorial!

  6. says

    Thanks for the tip, didn’t knew about data method. It’s great, but sometimes you need to pass a value from the backend to that element, so a class or rel attribute is needed as data storage. Let’s say the item ID. What do you think is the best solution for that?
    Imagine you need to pass many divs per records in a DB, and do operations with each div. How you say from backend to jQuery/javascript which ID is related to current div?

    I’ll give livequery a try, looks very useful.
    Thanks

  7. Tian says

    Hi Marc,
    Many thanks for the .data() method – it looks very useful and, like the rest here, it has eluded my attention until now.
    A question about its performance: where is the data actually stored? Are we bloating the DOM by adding large data elements to it, or is the data being stored in js variable space as say an associative array and cross-referenced by the element ID?

    I have some reservations about using classes as flags. While I do use this technique a lot, it has always bothered me that my HTML markup will not pass a lint test what with all those missing classes. E.g. in Visual Studio the elements that are so adorned with these undefined classes don’t fall easy on the eye, yet I’ve never bothered to define dummy CSS classes to get rid of the warnings. I’ve always assumed that there would be a more standards-compliant way of achieving this … but I’m not so sure anymore now that one of my jQuery heroes is advocating this technique!

  8. gregf says

    Like everyone else thanks for letting us know about the data method. Something else I had no idea about is that jquery.form had a built in way of dealing with file uploads. That’s a really neat trick.

  9. says

    Tian: the data is stored in the jQuery reference to the object. Performance is a not an issue, that is what jQuery uses internally in the core.

    Visual Studio barks if you don’t have any styles associated with the flag class. Just try adding a few flag classes to the style sheet and the errors will go away. As far as standards, if it helps you and makes sense to developers than who cares? To me classes are meant to be CSS flags, why not use them for JS flags as well – it makes perfect sense to me.

  10. says

    Great tip on the .data() function, I haven’t seen that before. Going to be really useful.

    One thing I’ve been doing that (to me) might be a good thing to tell people about is not to reference the same deep selector call multiple times. Calling $(this).parents(‘.parent’).find(‘span’) more than once in your function is probably not the best way of going about it as you’re relying on jQuery to query the DOM each time to find the handle to what you’re looking for. What I like to do is set a long selector query like that to a JS variable, and then work off that variable so it doesn’t have to be calculated all the time. Same thing as setting a counter variable before your for loop so you only have to do it once.

  11. says

    Nice I have to agree with Mike Rundle and here’s an example:

    var el = $('p.secondary');
    el.css('color','#cecece');
    el.text('hello world!');
    el.append('<p>Another paragraph</p>');

    Instead of constantly referencing the element, $(‘p.secondary’), set it to a variable which “caches” it locally for quick reuse. Immensely efficient!

  12. olivvv says

    Most people do not understand what livequery implies, i.e, the dom to be periodically scanned.
    They only understand it when they face performance problems on large dom operations.

    I think it is much much more productive to teach people event delegation, rather than orientating them toward a pseudo-miraculous solution that will badly leak when thing get serious.

    Event Delegation rules !

  13. says

    @olivvv

    It is true that Event Delegation is a powerful technique, but it also needs to be approached with care. In most cases, it can be used for relatively infrequent events (such as clicks) with impunity, but more frequent events (such as mousemove, mouseover) can see very poor performance. Event Delegation requires inspecting the target of each and every event (of a particular type) that is fired. If that event is a mousemove, you can be performing a ridiculous amount of target inspections.

    Bottom line is to understand the implications of all these techniques so that you can pick the best one for your current needs. Factors such as the frequency of DOM modification and the type of events you’re reacting to can make a world of a difference.

  14. says

    Jeremy Martin: Well said. It is not a simple answer to use one or the other. You have to understand them both to really get a grasp what to use in what situation. In general, livequery performs well enough until you get into intense DOM manipulation. That is why I suggested it, but still pointed people towards learning event delegation.

  15. says

    I never heard of data() either until I found this page. :)

    Can the 2nd parameter for data() be any type of variable, or does it have to be a string?

  16. says

    @Vik: You can store a function or an object as well, for instance.

    set function in data with

    $(selector).data('foo', function(){ alert('bar'); });
    $(selector).data('foo') ... returns function()
    $(selector).data('foo')() ... alerts 'bar'

    set object in data with

    $(selector).data('foo', { 'a':'b', 'c':function(){ alert('blah'); } });
    $(selector).data('foo').a ... returns "b"
    $(selector).data('foo').c() ... alerts "blah"

  17. David Clarke says

    Wow, data() seems to have struck a chord. Prior to discovering data() I was using the attr() function to add data to elements. As with data(), attr() can also be used to add arbitrary objects to elements. Obviously adding attr(“class”) to an element is going to have some potentially serious side affects whereas data(“class”) won’t but it is possible to add arbitrary attributes to HTML elements, i.e. you don’t have to repurpose valid HTML attributes such as “rel” or “alt”. I’m sure there are many opinions as to the efficacy of such an approach.

    I guess my concern is more about whether either approach represents a good practice. Adding some data to an element in one module and accessing that data from another results in coupling so I would use it sparingly and only within a single module.

  18. Frank says

    Thanks for the tips! I’m still a bit of a newbie, but I love jQuery! I just found this awesome jQuery Cheat Sheet for the iPhone today. It’s really great. I’ve only had it for a day and it’s already making my life a lot easier.

    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=302090867&mt=8

    Looks like there’s also a CSS Cheat Sheet from the same guys.

    http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=301093674&mt=8

  19. earpick says

    Started using jQuery a few weeks ago and noticed the data method in the docs. Quite useful indeed. Wish I knew about it a few months ago when I was coding pure JS.

    I suppose I built something rather similar to it though, as I have had .js classes representing the logic and data storage of the application, with an array of references to appropriate DOM elements for each of the objects. In essence, every DOM element would be represented by an object. Just had to ensure that when I stringify the objects into JSON for storage in a database that all the references to DOM are removed. Took a while to put together but worked well; I’m sure I could have slashed the development time by half had I used jQuery though.

  20. ege says

    Excellent post. Ditto with Mike Branski, I never heard of the .data() even though I have been using jQuery for some time. Very useful indeed.

  21. says

    What an great article on JQuery!!
    Personally, I find this type of article a lot more useful than others that only touch surface of great effects.
    I especially like the point on event delegation and livequery.

  22. says

    I rarely comment on an article. But this one is too good. Wish I knew data 2 months back. Now I’ll have to rewrite my entire code. I hated doing it the attr way. Wish I had known all the best practices. I have already rewritten my code 3 times in 4 months!

    Thanks Marc, you’re on my RSS reader now :)

  23. says

    Tip 3 – jquery 1.3 has “live” method as standard, which is essentially the same as the livequery plugin.

    Nice article! :)

  24. says

    Marc,

    I’ve been using jQuery at big commercial companies for a few years now and although everyone likes to use it not many project path decision makers ever seem to be all that concerned with really using it well as much as they just want the project out the door quick.

    So I appreciate this tight concise list as it gives me a few more paths to get to the finish line that will undoubtedly help shed min/hours off future projects.

  25. says

    Hi ,
    I like your points.
    Add this too :

    // Checking the element type of the selected element, eg;
    if($(this).is('form')){
    //welcome
    }
    else{
    throw new Error('This block works only with a form');
    }

  26. says

    Like everyone else here, I also didn’t know about the data function, and I have a sideproject that is going to need heavy modification now … =]

  27. James Collins says

    Hi Marc,

    Thanks for intruducing me to the data() feature in jQuery. It looks like a great way to store and retrieve data once a page is loaded.

    How would you recommend I store the data during page rendering?

    For example, my PHP script retrieves product information from a MySQL database, and renders the page based on this data.

    Obviously only the data() method can be used once the page loads, so how can I embed this product content in the HTML markup so it can be used once the page loads?

    I’m currently using classes and the rel attribute, but it’s messy.

    Thanks.

  28. jquereal says

    Hey Marc,
    that’s the most useful few lines of code I’ve read on jQuery, inside 5 minutes, in many days :-)
    THANKS A TON !!
    I suggest you start a separate tips section with wise little snippets of code like the ones above. I’m sure you have more of those ;-D
    (I also offer to help making a list of tips- if you want someone to share some of the grunt work. Serious.)

  29. Atul says

    Great Information, thanks for sharing this information.
    Speciall .data() function is amazing, I never used that, this is going to change so many things for me.
    Thanks again.
    Atul K.

  30. says

    Curious for a better explanation on the use of .data. I would like to better understand your reasoning why it is better than using custom attributes on the dom element.
    From my perspective one big advantage of using custom elements is you can use them in selectors too, like:

    $(‘p [myAttr=myVal]’)

    Which AFAIK, you can’t do with the data cache.

    Thanks for the info though.

  31. says

    .data is much faster because you aren’t manipulating the DOM. What you are doing is just fine for smaller bits of strings, but you also can’t drop in a JavaScript objects or closures into DOM attributes.

  32. Reinder says

    Good shizzle. So, I’ve been wondering – what’s the best way to use .data()? Is it possible to add multiple data’s to one selector? And is it a good practice to add all your (relevant) data’s to one DOM Element? I can see myself forgetting to which element I attached something. All attachments have a name, which means they can be meaningful and do not have to rely on the ‘meaning’ of the element its attached to. Any thought on this?

  33. says

    Wish I’d seen #2 earlier ,)

    Number #3 probably needs updating with version 1.7, seeing as people are still refering to this information :)

  34. says

    You people overreact the same way with every pre-sale. Just be patient, you’ll get tickets with everyone else when they go on general sale. It’s not like he’s Jeff Mangum or this is his last show ever or anything system