5 Tips for Better jQuery Code: jQuery, Tutorial

5 Tips for Better jQuery Code

Category: JavaScript & jQuery Tags: jQuery, Tutorial | Written on Nov 14, 2008

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:

JavaScript:
  1. $('selector').attr('alt', 'this is the data that I am storing');
  2. // then later getting that data with
  3. $('selector').attr('alt');

Why is this a bad thing?  Because "alt" has absolutely no meaning whatsoever, as well as HTML is not meant to store data.

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

JavaScript:
  1. $('selector').data('meaningfullname', 'this is the data I am storing');
  2. // then later getting the data with
  3. $('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 livequery.

Note on March 21st, 2009: New in jQuery 1.3, the live method has adopted many of the same events of livequery into the core of jQuery.

Note on November 16th, 2008: If you understand event delegation, use it as an alternative to using livequery for attaching events.

When you add elements to the page a lot, attaching events to them and running functions on them then use Brandon Aaron's livequery plugin. This way you can do things like:

JavaScript:
  1. $('div.edit').livequery('click', function(){
  2. //go into edit mode
  3. });

Then whenever you add a div to the page with class "edit" it will attach that click event. This works for all other events, as well as if you want to run a function on an element right when it is added you can do this:

JavaScript:
  1. $('span.flag').livequery(function(){
  2. // run this function when a span with class "flag" is added to the page
  3. });

#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.

 

Comments

#1. Mike Branski http://www.leftrightdesigns.com on Nov 14, 2008
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. Marc Grabanski http://marcgrabanski.com on Nov 14, 2008
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. Matt Curry http://www.pseudocoder.com on Nov 14, 2008
I agree w/ Mike about #1. I'm a serial offender of sticking random data in various attributes. I had no idea data() existed.
#4. Matt Wood http://floatmargin.com on Nov 14, 2008
Do you think you get get better performance by flagging with classes rather than flagging with .data()?
#5. Tom Sieron http://mapness.net on Nov 15, 2008
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.
#6. Sean O http://www.sean-o.com on Nov 15, 2008
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?
#7. Marc Grabanski http://marcgrabanski.com on Nov 15, 2008
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!
#8. Michal Wojciechowski http://odyniec.net on Nov 16, 2008
Good tips. Just a little correction -- the post suggests that [attribute=value] is a custom jQuery selector, while it's actually defined in the CSS2 specification (http://www.w3.org/TR/CSS2/selector.html#attribute-selectors).
#9. Leandro http://www.dr-leech.com.ar/ on Nov 17, 2008
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
#10. Marc Grabanski http://marcgrabanski.com on Nov 17, 2008
Leandro: try using the metadata plugin.
#11. Tian on Nov 17, 2008
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!
#12. gregf on Nov 17, 2008
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.
#13. Marc Grabanski http://marcgrabanski.com on Nov 17, 2008
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.
#14. Mike Rundle http://flyosity.com/ on Nov 17, 2008
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.
#15. Ozh http://planetozh.com/ on Nov 17, 2008
Damn. Didn't know about data() neither. Thanks for this :)
#16. Joe McCann http://www.subprint.com on Nov 17, 2008
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('

Another paragraph

');

Instead of constantly referencing the element, $('p.secondary'), set it to a variable which "caches" it locally for quick reuse. Immensely efficient!
#17. Joe McCann http://www.subprint.com on Nov 17, 2008
Just noticed that the append method up there actually used the paragraph tag that I inserted in there...just note that the text "Another Paragraph" is wrapped in a paragraph tag.
#18. Jahdur Rahman http://blog.valenticabd.com on Nov 17, 2008
I have opened the http://brandonaaron.net/docs/livequery/ livequery link. But I found an empty page. What's wrong?
#19. Ben http://blarggstar.com on Nov 18, 2008
Been using jQuery for a few months. data() is new to me also and is exactly what I need!!!!
#20. Jonas http://glamorous.be on Nov 18, 2008
Thank you for letting me know the existence of .data() Didn't knew that eather.

@Jahdur Rahman: Try this link: http://docs.jquery.com/Plugins/livequery
#21. Marc Grabanski http://marcgrabanski.com on Nov 18, 2008
@Jahdur Rahman: Either that or get livequery from Brandon Aaron's github.
#22. olivvv on Nov 20, 2008
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 !
#23. Jeremy Martin http://blog.jeremymartin.name on Nov 20, 2008
@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.
#24. Marc Grabanski http://marcgrabanski.com on Nov 20, 2008
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.
#25. Clinton Montague http://slightlymore.co.uk on Nov 21, 2008
Thanks for tip #1, very useful for those who don't know. I used to use rels, alts, and anything else that I could think of until I found the data() function.
#26. JHollanti on Dec 19, 2008
Ding! You've got a fan :)
#27. Vik http://www.flavorzoom.com on Dec 20, 2008
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?
#28. Marc Grabanski http://marcgrabanski.com on Dec 20, 2008
@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"
#29. David Clarke on Jan 08, 2009

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.

#30. Frank on Jan 16, 2009
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

#31. Aamir Afridi http://www.aamirafridi.com on Jan 25, 2009
I wish i could have read about data() months ago. I, myself was not feeling good using html for storing data but never again. Thanks for this info
#32. Borellus http://www.borellus.com on Jan 28, 2009
Cheers for that, very useful. :)
#33. earpick on Feb 06, 2009
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.
#34. ege on Feb 13, 2009
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.
#35. Bryan Kwon http://bryankwon.com on Feb 22, 2009
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.
#36. Webdesign http://www.artgraphix.de on Feb 24, 2009
Wonderful article about jQuery! Thx for the informations.

Greetings from DE
#37. Arun http://cashonomics.com on Mar 06, 2009
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 :)
#38. Richard http://www.icdw.co.uk on Mar 10, 2009
Tip 3 - jquery 1.3 has "live" method as standard, which is essentially the same as the livequery plugin.

Nice article! :)
#39. Marc Grabanski http://marcgrabanski.com on Mar 10, 2009
Thanks Richard, this article was written before jQuery 1.3 came out.
#40. strony internetowe http://www.londonrecovery.co.uk on May 02, 2009
interesting :)
#41. motoChristo http://motochristo.com on May 03, 2009
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.
#42. Martin Leblanc http://www.iconfinder.net on May 17, 2009
Wow! Great tips - especially the data one. I have a lot of jQuery code to optimize on my site: http://www.iconfinder.net
#43. Stanley @ SEOAdsenseThemes.com http://www.seoadsensethemes.com on May 26, 2009
I admit of being guilty to Tip #1. I did exactly that but having found out about data() function, I immediately modified my codes.
#44. Pokrate http://nifty-tracker.blogspot.com on Jun 01, 2009
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');
}
#45. Yunus http://www.yunuserturk.com 2 weeks, 6 days ago
Thanks for it. its useful really..
#46. widi mawardi http://w3function.com 1 week, 3 days ago
hi.. good tips

Leave a Comment

Other Reading - Categories