views:

4129

answers:

26

I am starting a project with jQuery.

What pitfalls/errors/misconceptions/abuses/misuses did you have in your jQuery project?

+2  A: 

Excessive use of chaining.

See this:

this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent, this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);

Explanation

SolutionYogi
It looks funny, it's a sort of obfuscation.
Dykam
Chaining (on it's own) is difficult to use 'in excess'. It looks like that code makes excessive use of the javascript ternary operator. See http://en.wikipedia.org/wiki/Ternary_operation#JavaScript for more information.
Dan Esparza
I'm glad I don't have to maintain your code.
cdmckay
A: 

Not understanding event binding. JavaScript and jQuery work differently.

By popular demand, an example:

In jQuery:

$("#someLink").click(function(){//do something});

Without jQuery:

<a id="someLink" href="page.html" onClick="SomeClickFunction(this)">Link</a>
<script type="text/javascript">
SomeClickFunction(item){
    //do something
}
</script>

Basically the hooks required for JavaScript are no longer necessary. I.e. use inline markup (onClick, etc) because you can simply use the ID's and classes that a developer would normally leverage for CSS purposes.

Jason
Care to elaborate? Preferably an example?
SolutionYogi
Doesn't JavaScript provide addEventListener() and attachEvent() to do this?
alex
+9  A: 

If you bind() the same event multiple times it will fire multiple times . I usually always go unbind('click').bind('click') just to be safe

Scott Evernden
This is not specific to jQuery, though important thing to keep in mind.
SolutionYogi
You could use live events to not have to bind the same event twice.
R. Bemrose
live has its own (performance) issues if used to excess. Better in 1.3.3 where you can give context.
redsquare
+19  A: 

While using $.ajax function for Ajax requests to server, you should avoid using the complete event to process response data. It will fire whether the request was successful or not.

Rather than complete, use success.

See Ajax Events in the docs.

Artem Barger
I've been back and forth on success vs complete, can you expand on why you think complete is better?
Neil N
I'm not saying complete is better. What I was trying to say is that you need to avoid misleading use of complete and should use success in order to be able to process the response data.
Artem Barger
Well it always gets called. However I would disagree. Complete is best for hiding a loading gif etc. You should use the success for handling the response and the error for any errors of course.
redsquare
He is suggesting to use success instead of complete. 'complete' always fires when the ajax request is 'complete', doesn't matter it completed successfully or unsuccessfully.
SolutionYogi
Ah context confusion!
redsquare
@redsquare, can you expand on that exactly you disagree with? I was referring to data process and didn't mind any pictures hiding/showing opportunities you have with complete handler .
Artem Barger
Like Neil N I got the wrong tone of the answer
redsquare
Ok, I see. I've putted the mark to get it more understandable.
Artem Barger
-1 so? maybe are scenarios where you need it .use it only if you know how it works.
Elzo Valugi
I just tried to say that people frequently confuses between those two, so just tried to warn that it has different semantic notation. So if you going this way you should downvote all answers here, since all of them is not helpful much once you know how things in jquery works.
Artem Barger
+17  A: 

Try to split out anonymous functions so you can reuse them.

//Avoid
$('#div').click( function(){
   //do something
});

//Do do
function divClickFn (){
   //do something    
}

$('#div').click( divClickFn );
redsquare
I think this applies to roughly the same degree that synchronous (inline) code should be broken up into named functions. If you've got a chunk of code that is begging to be given a name, then go for it. But don't move the code out of line simply because you're wrapping it inside a function; anonymous functions exist for good reason.
Dan Breslau
Actually I like to give 'name' to my function. It is very useful when you are debugging the code and instead of seeing an endless list of anonymous functions, you see properly named functions.
SolutionYogi
Your point is well taken, and I've probably been tripped by this myself a few times. Even so, "*roughly* the same degree" still works for me.
Dan Breslau
esp. if the binding is happening in a loop!
MyWhirledView
+7  A: 

Avoid multiple creation of the same jQuery objects

//Avoid
function someFunc(){
   $(this).fadeIn();
   $(this).fadeIn();
}

//Cache the obj
function someFunc(){
   var $this = $(this).fadeIn();
   $this.fadeIn();
}
redsquare
var $this = $(this).fadeIn();? you're caching an effect?
Jason
it returns the element, Its called chaining!
redsquare
you can set a variable and perform an action on it at the same time?
Jason
Indeed, but dont take my word for it. Try it. How do you think the following is possible if the jquery object representing the element is not returned? $('#divId').hide().show().fadeIn()....etc
redsquare
That works, but I think it's more readable to have `$this = $(this);` on a separate line. If you can (without making a mess), forget about `$this` and just chain everything: `$(this).fadeIn().fadeIn();`
Patrick McElhaney
Why when then works just fine. Your just making extra lines for no reason. It is still just as readable. Typically when doing an animation you will use the callback so a cached var is needed.
redsquare
The reason why is because it's more idiomatic.
cdmckay
you are also effectively calling $(this).fadeIn().fadeIn(); every time you call someFunc()
scottm
yes yes it was just an example.....not meant for use, was to show the caching!
redsquare
+79  A: 

Being unaware of the performance hit and overusing selectors instead of assigning them to local variables. For example:-

$('#button').click(function() {
    $('#label').method();
    $('#label').method2();
    $('#label').css('background-color', 'red');
});

Rather than:-

$('#button').click(function() {
    var $label = $('#label');
    $label.method();
    $label.method2();
    $label.css('background-color', 'red');
});

Or even better with chaining:-

$('#button').click(function() {
    $("#label").method().method2().css("background-color", "red"); 
});

I found this the enlightening moment when I realized how the call stacks work.

Edit: incorporated suggestions in comments.

Gavin Gilmour
yup look up 1 answer!
redsquare
+1 for the youtube link. holy crap i learned a lot.
Jason
I think assigning things to local variables is great but don't forget about the power of chaining (from your example): $("#label").method().method2().css("background-color", "red");
Lance McNearney
The YouTube video was great. I've seen other Google presentations on the subject and I *still* learned a few things! Thanks!
Gabriel Hurley
+1 for the link as well, excellent!
Josh Stodola
It's kind of a convention to use a dollar sign for variables with jQuery context. So you may wanna write `var $label = $('#label');`
Tim Büthe
I've edited this to reflect Lance and Tim's comments.
Gavin Gilmour
+9  A: 

Misunderstanding of using this identifier in the right context. For instance:

$( "#first_element").click( function( event)
{
   $(this).method( ); //referring to first_element
   $(".listOfElements").each( function()
   {
      $(this).someMethod( ); // here this is not referring first_element anymore.
   })
});

And here one of the samples how you can solve it:

$( "#first_element").click( function( event)
{
   $(this).method( ); //referring to first_element
   var $that = this;
   $(".listOfElements").each( function()
   {
      $that.someMethod( ); // here this is not referring first_element anymore.
   })
});
Artem Barger
+1 More a javascript problem than a jquery problem, but I used to get tripped up by this a lot.
mmacaulay
+2  A: 

Using ClientID to get the "real" id of the control in ASP.NET projects.

jQuery('#<%=myLabel.ClientID%>');

Also, if you are using jQuery inside SharePoint you must call jQuery.noConflict().

Repo Man
? How is this a pitfall? It's a workaround for ASP.NET behavior.
SolutionYogi
Yeah. It is nto a jQuery issue. It is a fault of asp.net webforms.
redsquare
Agreed. But this is something you need to be aware of when using jQuery in ASP.NET regardless.
Repo Man
the OP didn't mention asp.net
redsquare
+20  A: 
  • Avoid abusing document ready.
  • Keep the document ready for initialize code only.
  • Always extract functions outside of the doc ready so they can be reused.

I have seen hundreds of lines of code inside the doc ready statement. Ugly, unreadable and impossible to maintain.

redsquare
+1. In general, most of the jQuery code I have seen uses functions with hundreds of lines. I don't know why 'jQuery developers' don't like to use smaller functions.
SolutionYogi
@SolutionYogi because most are just JS noobs?
Infinity
+39  A: 

Don't use bare class selectors, like this:

$('.button').click(function() { /* do something */ });

This will end up looking at every single element to see if it has a class of "button".

Instead, you can help it out, like:

$('span.button').click(function() { /* do something */ });
$('#userform .button').click(function() { /* do something */ });

I learned this last year from Rebecca Murphy's blog

BrianH
This makes all the sense in the world to me but I could of swore that it was the otherway around for some reason. I thought people were saying that it is a bad idea to help" it which made no sense to me so glad to see this is correct
jasondavis
I was also under the impression that the reverse was true. Perhaps this is the case in browsers that don't implement getElementsByClassName, but otherwise you are just giving jQuery more work to do. I would very much like to see Rebecca post some benchmarks :)
Alex Barrett
You're REDUCING the amount of work it has to do. It's like telling somebody to get your socks out of the drawer in your dresser instead of telling them to get the socks out of your room. Reduces the amount of 'looking' it has to do substantially.
Sneakyness
+30  A: 

Understand how to use context. Normally, a jQuery selector will search the whole doc:

// This will search whole doc for elements with class myClass
$('.myClass'); // 

But you can speed things up by searching within a context:

var ct = $('#myContainer');
// This will search for elements with class myClass within the myContainer child elements
$('.myClass', ct[0]);
slolife
Aaaaaaah! Well, that's about 1,000,000 of my bugs fixed. +1
jammus
It seems your last point is incorrect - http://groups.google.co.uk/group/jquery-dev/browse_thread/thread/b8c414b373163895
J-P
Thanks for pointing this out JP. Now, what to do... Should I delete my answer so no one else goes hog wild and changes their code for nothing?
slolife
Nah, it's still a good point, optimization-wise. :)
J-P
+10  A: 

Pitfall: Using loops instead of selectors.

If you find yourself reaching for the jQuery '.each' method to iterate over DOM elements, ask yourself if can use a selector to get the elements instead.

More information on jQuery selectors:
http://docs.jquery.com/Selectors

Pitfall: NOT using a tool like Firebug

Firebug was practically made for this kind of debugging. If you're going to be mucking about in the DOM with Javascript, you need a good tool like Firebug to give you visibility.

More information on Firebug: http://getfirebug.com/

Other great ideas are in this episode of the Polymorphic Podcast: (jQuery Secrets with Dave Ward) http://polymorphicpodcast.com/shows/jquery/

Dan Esparza
I've done the first one many times. You just need to remember that most jQuery functions will operate on all elements returned from a selector.
DisgruntledGoat
+1 for Firebug.
Gabriel Hurley
A: 

If you plan to Ajax in lots of data, like say, 1500 rows of a table with 20 columns, then don't even think of using jQuery to insert that data into your HTML. Use plain JavaScript. jQuery will be too slow on slower machines.

Also, half the time jQuery will do things that will cause it to be slower, like trying to parse script tags in the incoming HTML, and deal with browser quirks. If you want fast insertion speed, stick with plain JavaScript.

mkoryak
-1 The _.html()_ function is just as fast as the native approach
roosteronacid
Can you substantiate that?
David Wolever
everyone who is downvoting me obviously hasnt tried inserting a ton of DOM on IE and watch things become slow. Reason jquery is slow is it will not simply insert the dom, it does a few other things, like check if the dom has scripts, and executes them if its in IE, and some other stuff that you dont need to do if you know exactly what kind of data you are inserting
mkoryak
Infinity
+12  A: 

"Chaining" Animation-events with Callbacks.

Suppose you wanted to animate a paragraph vanishing upon clicking it. You also wanted to remove the element from the DOM afterwards. You may think you can simply chain the methods:

$("p").click(function(e) {
  $(this).fadeOut("slow").remove();
});

In this example, .remove() will be called before .fadeOut() has completed, destroying your gradual-fading effect, and simply making the element vanish instantly. Instead, when you want to fire a command only upon finishing the previous, use the callback's:

$("p").click(function(e){
  $(this).fadeOut("slow", function(){
    $(this).remove();
  });
});

The second parameter of .fadeOut() is an anonymous function that will run once the .fadeOut() animation has completed. This makes for a gradual fading, and a subsequent removal of the element.

Jonathan Sampson
+2  A: 

Passing IDs instead of jQuery objects to functions:

myFunc = function(id) { // wrong!
    var selector = $("#" + id);
    selector.doStuff();
}

myFunc("someId");

Passing a wrapped set is far more flexible:

myFunc = function(elements) {
    elements.doStuff();
}

myFunc($("#someId")); // or myFunc($(".someClass")); etc.
Craig Stuntz
+4  A: 

Avoid searching through the entire DOM several times. This is something that really can delay your script.

Bad:

$(".aclass").this();
$(".aclass").that();
...

Good:

$(".aclass").this().that();

Bad:

$("#form .text").this();
$("#form .int").that();
$("#form .choice").method();

Good:

$("#form")
    .find(".text").this().end()
    .find(".int").that().end()
    .find(".choice").method();
googletorp
$(".aclass").this().that(); is not good! class only selectors are slow
redsquare
It's an illustrative example showing Jquery's ability to use several methods on one selection. I made the selection simple (and thus slow) to give greater focus on this technique.
googletorp
While avoiding searching the DOM repeatedly is a good thing — the last example is an unreadable mess where I've got no idea what is going on. If you plan to use the result of a fetch multiple times, store it in a variable. It makes code much more maintainable.
David Dorward
+3  A: 

Always cache $(this) to a meaningful variable especially in a .each()

Like this

$(selector).each(function () {
    var eachOf_X_loop = $(this); 
})
adardesign
+6  A: 

Similar to what Repo Man said, but not quite.

When developing ASP.NET winforms, I often do

$('<%= Label1.ClientID %>');

forgetting the # sign. The correct form is

$('#<%= Label1.ClientID %>');
Ronnie
+5  A: 

Events

$("selector").html($("another-selector").html());

doesn't clone any of the events - you have to rebind them all.

As per JP's comment - clone() does rebind the events if you pass true.

Chris S
Clone() does if you pass true.
J-P
What about live() in jQuery 1.3.2?
jmav
+10  A: 

Don't abuse plug-ins.

Most of the times you'll only need the library and maybe the user interface. If you keep it simple your code will be maintainable in the long run. Not all plug-ins are supported and maintained, actually most are not. If you can mimic the functionality using core elements I strongly recommend it.

Plug-ins are easy to insert in your code, save you some time, but when you'll need an extra something, it is a bad idea to modify them, as you lose the possible updates. The time you save at the start you'll loose later on changing deprecated plug-ins.

Choose the plug-ins you use wisely. Apart from library and user interface, I constantly use $.cookie , $.form, $.validate and thickbox. For the rest I mostly develop my own plug-ins.

Elzo Valugi
What about grid? You make your own?
jmav
yes. from project to project data comes in various ways. I prefer to have full control that realizing that grid only helps me to the middle and then I have to improvise.
Elzo Valugi
+9  A: 

10 Ways to Instantly Increase Your jQuery Performance

Check this article.

Daniel Moura
+3  A: 

I say this for JavaScript as well, but jQuery, JavaScript should NEVER replace CSS.

Also, make sure the site is usable for someone with JavaScript turned off (not as relevant today as back in the day, but always nice to have a fully usable site).

Martin
A: 

Using jQuery in a small project that can be completed with just a couple of lines of ordinary JavaScript.

vise
I don't mind being modded down, but please argument your choice.
vise
-1 jQuery abstracts a broken API. This way you are always sure your code is working. Say you've written some code using jQuery and some random browser-bug gets introduced with a new version--all you need to do is import an updated version of the jQuery framework. Versus having to figure out how to solve the bug yourself.
roosteronacid
+1 seems reasonable to me - if you're using just a few lines, make sense to just use vanilla JS.
alex
@roosteronacid, your argument misses the point. It's very unlikely for a browser to introduce a regression in a script of lesser complexity, or dealing with crossbrowser issues for that matter.Two years ago I've working with mootools and under a certain circumstance it was unable to read an elements content on IE. After a few hours of tring to figure out the problem I just rewrote that part with plain js. So, it's actually more likely for jQuery to break rather than plain javascript to fail due to a browser upgrade.I'd solve a bug my self any day rather than hacking through a libraries code.
vise
`couple of lines of ordinary JavaScript` Sure no problem. But when is it ever just that?People that say "why not use vanilla javascript??" haven't been bitten hard enough by IE yet... and not to mention how much cruft and boilerplate code you have to write to do simple things in plain old JS.
Infinity
@vise I'm surprised you found a bug in MooTools. After 3 years working on mainly JS, I have yet to find a bug in either MooTools or jQuery. I think one of the tens of thousands of users of the framework would notice a bug and open a ticket or submit a bugfix before you can finish typing `alert()` ;-)
Infinity
A: 

If you want users to see html entities in their browser, use 'html' instead of 'text' to inject a Unicode string, like:

$('p').html("Your Unicode string")
A: 

my two cents)

Usually, working with jquery means you don't have to worry about DOM elements actual all the time. You can write something like this - $('div.mine').addClass('someClass').bind('click', function(){alert('lalala')}) - and this code will execute without throwing any errors.

In some cases this is useful, in some cases - not at all, but it is a fact that jquery tends to be, well, empty-matches-friendly. Yet, replaceWith will throw an error if one tries to use it with an element which doesn't belong to the document. I find it rather counter-intuitive.

Another pitfall is, in my opinion, the order of nodes returned by prevAll() method - $('<div><span class="A"/><span class="B"/><span class="C"/><span class="D"/></div>').find('span:last-child').prevAll(). Not a big deal, actually, but we should keep in mind this fact.

shabunc