views:

11071

answers:

32

Miscellaneous

Syntax

Optimization

+44  A: 

I'm really not a fan of the $(document).ready(fn) shortcut. Sure it cuts down on the code but it also cuts way down on the readability of the code. When you see $(document).ready(...), you know what you're looking at. $(...) is used in far too many other ways to immediately make sense.

If you have multiple frameworks you can use jQuery.noConflict(); as you say, but you can also assign a different variable for it like this:

var $j = jQuery.noConflict();
$j('#myDiv').hide();

Very useful if you have several frameworks that can be boiled down to $x(...)-style calls.

Oli
@Oli: About the document ready-shorthand; you have a point. But never the less: it is a tip/trick. One which I use in all my code purely because I think it "looks" better. A matter of personal preference, I guess :)
roosteronacid
JoeBloggs
When I see $(function(){...}) I know what's going on. The more usual things should be shorter. That's why we turn frequently called code fragments into functions.
ns
+5  A: 

Judicious use of third-party jQuery scripts, such as form field validation or url parsing. It's worth seeing what's about so you'll know when you next encounter a JavaScript requirement.

harriyott
+8  A: 

I like declare a $this variable at the beginning of anonymous functions, so I know I can reference a jQueried this.

Like so:

jQuery('a').each(function()
{
    var $this = jQuery(this);
});
Ben
I use "that" instead :)
roosteronacid
ROA: Yeah, that'll be the acid :)You can also use arguments.callee to enable an anonymous function to reference itself
JoeBloggs
Joe - just a heads up, callee will be going away with ECMAScript 5 and strict mode. See: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
Mike Robinson
+11  A: 

Not really jQuery only but I made a nice little bridge for jQuery and MS AJAX:

Sys.UI.Control.prototype.j = function Sys$UI$Control$j(){
  return $('#' + this.get_id());
}

It's really nice if you're doing lots of ASP.NET AJAX, since jQuery is supported by MS now having a nice bridge means it's really easy to do jQuery operations:

$get('#myControl').j().hide();

So the above example isn't great, but if you're writing ASP.NET AJAX server controls, makes it easy to have jQuery inside your client-side control implementation.

Slace
Does the ajax clientside library provide a way of finding a control by the original Id you assigned (in the code behind)
Chris S
this.get_id() will return you the ID of the control in the client scope. The server-specified ID is irrelivant as the client ID is generated depending on the parent cotrol hierachy
Slace
+51  A: 

jQuery's data() method is useful and not well known. It allows you to bind data to DOM elements without modifying the DOM.

TenebrousX
data() is indeed of great help.
Pim Jager
+1 this seems really useful.
Neil Aitken
I have noticed that it doesn't work with elements without set ID.
Thinker
@Thinker: Yes, it does.
Alex Barrett
+22  A: 

instead of using a different alias for the jQuery object (when using noConflict), I always write my jQuery code by wrapping it all in a closure. This can be done in the document.ready function:

var $ = someOtherFunction(); // from a different library

jQuery(function($) {
    if ($ instanceOf jQuery) {
        alert("$ is the jQuery object!");
    }
});

alternatively you can do it like this:

(function($) {
    $('...').etc()    // whatever jQuery code you want
})(jQuery);

I find this to be the most portable. I've been working on a site which uses both Prototype AND jQuery simultaneously and these techniques have avoided all conflicts.

nickf
The second example is nice'r for the eyes :)
roosteronacid
There is a difference though, the first example will wait for the document.ready() event to fire, while the second won't.
SamBeran
@SamBeran: True, the second example will run immediately; however, if you are wrapping an object-literal, you can use $(document).ready(...) inside the object-literal which means you can specify when you'd like to run each piece of code.
wilmoore
+128  A: 

Creating an HTML Element and keeping a reference:

var newDiv = $('<div/>');
newDiv.attr("id","myNewDiv").appendTo("body");
//Now whenever I want to append the new div I created, 
//I can just reference it from the 'newDiv' variable

Checking if an element exists:

if ($("#someDiv").length) {
    //it exists...
}

Writing your own selectors:

$.extend($.expr[':'], {
    over100pixels: function(a) {
        return $(a).height() > 100;
    }
});

$('.box:over100pixels').click(function() {
    alert('The element you clicked is over 100 pixels high');
});
Andreas Grech
Writing your own selectors is pretty slick
Hugoware
Also, if it's any help, you can actually do $("<div/>") and achieve the same thing as $("<div></div>")
Hugoware
I love the new selector part, didn't know about that.
Pim Jager
Since I can't edit community wikis yet: Combine assignment and existence check with `if ((var someDiv = $("#someDiv")).length) { /* do stuff with someDiv... */ }`
Ben Blank
Adding selectors: amazing! Wish I learned that a long time ago!
TM
Great thing with the first tip. The reference is nice!
furtelwart
@Ben: The reason I avoid such idioms in JavaScript is because I don't want to give the illusion of `someDiv` having being scoped in the `if` statement, because it isn't; JavaScript only supports function scope
Andreas Grech
+41  A: 

Nesting Filters

You can nest filters (as nickf showed here).

.filter(":not(:has(.selected))")
Nathan Long
ooh a shoutout, cheers!
nickf
Although be careful with this... :has performs a full-depth search, so it can get quite expensive.
harpo
+8  A: 

Save and Reuse Searches

Set a variable for a group of elements:

var allItems = $("div.item");
var keepList = $("div#container1 div.item");

Now you can keep working with those jQuery objects. For example, whittle down the "keep list" based on checkboxes whose names correspond to <div> class names:

$(formToLookAt + " input:checked").each(function() {  
   keepList = keepList.filter("." + $(this).attr("name")); 
});

Now hide the items that are NOT included in your filtered list:

allItems.not(keepList).hide();
Nathan Long
My naming convention is to have a `$` in front. e.g. `var $allItems = ...`
Louis
+26  A: 

Check the Index

jQuery has .index but it is a pain to use, as you need the list of elements, and pass in the element you want the index of:

var index = e.g $('#ul>li').index( liDomObject );

The following is much easier:

If you want to know the index of an element within a set (e.g. list items) within a unordered list:

$("ul > li").click(function () {
    var index = $(this).prevAll().length;
});
redsquare
Hey, that's clever!
Mike Robinson
What's wrong with the core index() method? It's been in core since 1.2 at least.http://docs.jquery.com/Core/index
ken
see above @ken !
redsquare
Ok, yes I was playing devil's advocate somewhat, because as I was reviewing jQuery's index() I realized it was kind of a pain in the butt. Thanks for the clarification!
ken
This is cool, but important to know that it doesn't work quite right if you had previous siblings that weren't part of the selection.
TM
I'm pretty sure since jQuery 1.4, you can just use `index()` and get the index from its parent.
alex
@alex - sure, but note the date of this post - it was 5 months before the 1.4 release!
redsquare
@redsquare Yeah I realised that! Mind if I do an edit... ?
alex
@alex, go ahead
redsquare
+9  A: 

On the core jQuery function, specify the context parameter when. Specifying the context parameter allows jQuery to start from a deeper branch in the DOM, rather than from the DOM root. Given a large enough DOM, specifying the context parameter should translate to performance gains.

Reference: http://docs.jquery.com/Core/jQuery#expressioncontext

lupefiasco
+39  A: 

Ooooh, let's not forget jQuery metadata! The data() function is great, but it has to be populated via jQuery calls.

Instead of breaking W3C compliance with custom element attributes such as:

<input 
  name="email" 
  validation="required" 
  validate="email" 
  minLength="7" 
  maxLength="30"/> 

Use metadata instead:

<input 
  name="email" 
  class="validation {validate: email, minLength: 2, maxLength: 50}" />

<script>
    jQuery('*[class=validation]').each(function () {
        var metadata = $(this).metadata();
        // etc.
    });
</script>
kRON
Pretty genius :)
Vincent
html5 data attributes make this less of an issue; there is discussion afoot on bringing html5 data attribute inline with jquery's data() function: http://forum.jquery.com/topic/patch-feedback-requested-html5-data-attrs-transcend-into-the-fn-data-api
Oskar Austegard
@Oskar - yep this has been implemented in jQuery 1.4.3 -- `data-*` attributes are automatically available via calls to `.data()`
nickf
+10  A: 

Syntactic shorthand-sugar-thing--Cache an object collection and execute commands on one line:

Instead of:

var jQueryCollection = $("");

jQueryCollection.command().command();

I do:

var jQueryCollection = $("").command().command();

A somewhat "real" use case could be something along these lines:

var cache = $("#container div.usehovereffect").mouseover(function ()
{
    cache.removeClass("hover");

    $(this).addClass("hover");
});
roosteronacid
it better to put the $(this) reference in a local variable, because you wil take a minor perfomance hit here, because it will take a little longer...
Sander Versluys
In this case (no pun intended) I am only using "this" one time. No need for caching.
roosteronacid
+19  A: 

Replace anonymous functions with named functions. This really supercedes the jQuery context, but it comes into play more it seems like when using jQuery, due to its reliance on callback functions. The problems I have with inline anonymous functions, are that they are harder to debug (much easier to look at a callstack with distinctly-named functions, instead 6 levels of "anonymous"), and also the fact that multiple anonymous functions within the same jQuery-chain can become unwieldy to read and/or maintain. Additionally, anonymous functions are typically not re-used; on the other hand, declaring named functions encourages me to write code that is more likely to be re-used.

An illustration; instead of:

$('div').toggle(
    function(){
        // do something
    },
    function(){
        // do something else
    }
);

I prefer:

function onState(){
    // do something
}

function offState(){
    // do something else
}

$('div').toggle( offState, onState );
ken
Unfortunately, because jQuery passes the event target as `this`, you can't get "proper" OO without using enclosures. I usually go for a compromise: `$('div').click( function(e) { return self.onClick(e) } );`
Ben Blank
I'm sorry Ben, but I fail to see how your comment has any relevance to my post. Can you elaborate? You can still use 'self' (or any other variable) using my suggestion; it won't change any of that at all.
ken
Yeh, Ben, what exactly do you mean!?
J-P
I must mention: always fur variable and functions in namespace not in root !!
jmav
+35  A: 

Live Event Handlers

Set an event handler for any element that matches a selector, even if it gets added to the DOM after the initial page load:

$('button.someClass').live('click', someFunction);

This allows you to load content via ajax, or add them via javascript and have the event handlers get set up properly for those elements automatically.

Likewise, to stop the live event handling:

$('button.someClass').die('click', someFunction);

These live event handlers have a few limitations compared to regular events, but they work great for the majority of cases.

For more info see the jQuery Documentation.

TM
Yeah, I love the new live stuff. Note that it only works starting with jQuery 1.3.
Nosredna
+1..you have saved me alot of heart ache..I just happened to read your entry and while I was taking a break - trobleshooting why my event was not firing. Thanks
Luke101
for any other late-comers to this article, you may also want to look at delegate(): http://api.jquery.com/delegate/ Similar to live, but more efficient.
Oskar Austegard
+8  A: 

Speaking of Tips and Tricks and as well some tutorials. I found these series of tutorials (“jQuery for Absolute Beginners” Video Series) by Jeffery Way are VERY HELPFUL.

It targets those developers who are new to jQuery. He shows how to create many cool stuff with jQuery, like animation, Creating and Removing Elements and more...

I learned a lot from it. He shows how it's easy to use jQuery. Now I love it and i can read and understand any jQuery script even if it's complex.

Here is one example I like "Resizing Text"

1- jQuery...

<script language="javascript" type="text/javascript">
    $(function() {
        $('a').click(function() {
            var originalSize = $('p').css('font-size'); // get the font size 
            var number = parseFloat(originalSize, 10); // that method will chop off any integer from the specified variable "originalSize"
            var unitOfMeasure = originalSize.slice(-2);// store the unit of measure, Pixle or Inch

            $('p').css('font-size', number / 1.2 + unitOfMeasure);
            if(this.id == 'larger'){$('p').css('font-size', number * 1.2 + unitOfMeasure);}// figure out which element is triggered
         });        
     });
</script>

2- CSS Styling...

<style type="text/css" >
body{ margin-left:300px;text-align:center; width:700px; background-color:#666666;}
.box {width:500px; text-align:justify; padding:5px; font-family:verdana; font-size:11px; color:#0033FF; background-color:#FFFFCC;}
</style>

2- HTML...

<div class="box">
    <a href="#" id="larger">Larger</a> | 
    <a href="#" id="Smaller">Smaller</a>
    <p>
    In today’s video tutorial, I’ll show you how to resize text every time an associated anchor tag is clicked. We’ll be examining the “slice”, “parseFloat”, and “CSS” Javascript/jQuery methods. 
    </p>
</div>

Highly recommend these tutorials...

http://blog.themeforest.net/screencasts/jquery-for-absolute-beginners-video-series/

egyamado
+9  A: 

Remove elements from a collection and preserve chainability

Consider the following:

<ul>
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
    <li>Four</li>
    <li>Five</li>
</ul>


$("li").filter(function()
{
    var text = $(this).text();

    // return true: keep current element in the collection
    if (text === "One" || text === "Two") return true;

    // return false: remove current element from the collection
    return false;
}).each(function ()
{
    var text = $(this).text();

    // this will alert: "One" and "Two"       
    alert(text);
});

The filter() function removes elements from the jQuery object. In this case: All li-elements not containing the text "One" or "Two" will be removed.

roosteronacid
Isn't it simpler just to use "each" and move the margin change inside the switch?
DisgruntledGoat
Updated my answer. Please let me know if I'm making myself clear(er)
roosteronacid
Nice jquery trick
Luke101
Does this really REMOVE li elements? It seems to alert with a filtered list of elements.
Cheeso
The filter function removes elements from the collection inside the jQuery object. It does not affect the DOM.
roosteronacid
In your filter function, you can simply write: return !!$(this).text().match(/One|Two/);;)
Vincent
+10  A: 

Optimize performance of complex selectors

Query a subset of the DOM when using complex selectors drastically improves performance:

var subset = $("");

$("input[value^='']", subset);
roosteronacid
Only if that subset is cached/saved.
Dykam
+4  A: 

(This is a shamless plug)

Instead of writing repetitive form handling code, you can try out this plugin I wrote that adds to the fluent API of jQuery by adding form related methods:

// elementExists is also added
if ($("#someid").elementExists())
  alert("found it");

// Select box related
$("#mydropdown").isDropDownList();

// Can be any of the items from a list of radio boxes - it will use the name
$("#randomradioboxitem").isRadioBox("myvalue");
$("#radioboxitem").isSelected("myvalue");

// The value of the item selected. For multiple selects it's the first value
$("#radioboxitem").selectedValue();

// Various, others include password, hidden. Buttons also
$("#mytextbox").isTextBox();
$("#mycheck").isCheckBox();
$("#multi-select").isSelected("one", "two", "three");

// Returns the 'type' property or 'select-one' 'select-multiple'
var fieldType = $("#someid").formElementType();
Chris S
+3  A: 

This one goes out to Kobi.

Consider the following snippet of code:

// hide all elements which contains the text "abc"
$("").each(function ()
{
    var that = $(this);

    if (that.text().indexOf("abc") > -1) that.hide();
});    

Here's a shorthand... which is about twice as fast:

$("p.value:contains('abc')").hide();
roosteronacid
not really the same thing. but not bad
Funky Dude
+4  A: 

It seems that most of the interesting and important tips have been already mentioned, so this one is just a little addition.

The little tip is the jQuery.each(object, callback) function. Everybody is probably using the jQuery.each(callback) function to iterate over the jQuery object itself because it is natural. The jQuery.each(object, callback) utility function iterates over objects and arrays. For a long time, I somehow did not see what it could be for apart from a different syntax (I don’t mind writing all fashioned loops), and I’m a bit ashamed that I realized its main strength only recently.

The thing is that since the body of the loop in jQuery.each(object, callback) is a function, you get a new scope every time in the loop which is especially convenient when you create closures in the loop.

In other words, a typical common mistake is to do something like:

var functions = [];
var someArray = [1, 2, 3];
for (var i = 0; i < someArray.length; i++) {
    functions.push(function() { alert(someArray[i]) });
}

Now, when you invoke the functions in the functions array, you will get three times alert with the content undefined which is most likely not what you wanted. The problem is that there is just one variable i, and all three closures refer to it. When the loop finishes, the final value of i is 3, and someArrary[3] is undefined. You could work around it by calling another function which would create the closure for you. Or you use the jQuery utility which it will basically do it for you:

var functions = [];
var someArray = [1, 2, 3];
$.each(someArray, function(item) {
    functions.push(function() { alert(item) });
});

Now, when you invoke the functions you get three alerts with the content 1, 2 and 3 as expected.

In general, it is nothing you could not do yourself, but it’s nice to have.

Jan Zich
+5  A: 

Update:

Just include this script on the site and you’ll get a Firebug console that pops up for debugging in any browser. Not quite as full featured but it’s still pretty helpful! Remember to remove it when you are done.

<script type='text/javascript' src='http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js'&gt;&lt;/script&gt;

Check out this link:

From CSS Tricks

Update: I found something new; its the the JQuery Hotbox.

JQuery Hotbox

Google hosts several JavaScript libraries on Google Code. Loading it from there saves bandwidth and it loads quick cos it has already been cached.

<script src="http://www.google.com/jsapi"&gt;&lt;/script&gt;  
<script type="text/javascript">  

    // Load jQuery  
    google.load("jquery", "1.2.6");  

    google.setOnLoadCallback(function() {  
        // Your code goes here.  
    });  

</script>

Or

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>

You can also use this to tell when an image is fully loaded.

$('#myImage').attr('src', 'image.jpg').load(function() {  
    alert('Image Loaded');  
});

The "console.info" of firebug, which you can use to dump messages and variables to the screen without having to use alert boxes. "console.time" allows you to easily set up a timer to wrap a bunch of code and see how long it takes.

console.time('create list');

for (i = 0; i < 1000; i++) {
    var myList = $('.myList');
    myList.append('This is list item ' + i);
}

console.timeEnd('create list');
Colour Blend
ppl in Iran can't see web pages loaded with google api. in fact google has restrict Iranians to access google code. so -1
cubny
@cubny: sorry about that.
Colour Blend
I just found out you can use firebug in any browser. That's awesome.
Colour Blend
+10  A: 

Defining properties at element creation

In jQuery 1.4 you can use an object literal to define properties when you create an element:

var e = $("<a />", { href: "#", class: "a-class another-class", title: "..." });

... You can even add styles:

$("<a />", {
    ...
    css: {
        color: "#FF0000",
        display: "block"
    }
});

Here's a link to the documentation.

roosteronacid
+2  A: 

No-conflict mode

jQuery.noConflict();

"Run this function to give control of the $ variable back to whichever library first implemented it. This helps to make sure that jQuery doesn't conflict with the $ object of other libraries.

By using this function, you will only be able to access jQuery using the jQuery variable. For example, where you used to do $("div p"), you now must do jQuery("div p")".

roosteronacid
+9  A: 

Shorthand for the ready-event

The explicit and verbose way:

$(document).ready(function ()
{
    // ...
});

The shorthand:

$(function ()
{
    // ...
});
roosteronacid
Personally I find the explicit way much more readable.
Dan Diplo
+5  A: 

Line-breaks and chainability

When chaining multiple calls on collections...

$("a").hide().addClass().fadeIn().hide();

You can increase readability with linebreaks. Like this:

$("a")
.hide()
.addClass()
.fadeIn()
.hide();
roosteronacid
+5  A: 

Changing the type of an input element

I ran into this issue when I was trying to change the type of an input element already attached to the DOM. You have to clone the existing element, insert it before the old element, and then delete the old element. Otherwise it doesn't work:

var oldButton = jQuery("#Submit");
var newButton = oldButton.clone();

newButton.attr("type", "button");
newButton.attr("id", "newSubmit");
newButton.insertBefore(oldButton);
oldButton.remove();
newButton.attr("id", "Submit");
Vivin Paliath
+4  A: 

Asynchronous each() function

If you have really complex documents where running the jquery each() function locks up the browser during the iteration, and/or Internet Explorer pops up the 'do you want to continue running this script' message, this solution will save the day.

jQuery.forEach = function ( in_array, in_pause_ms, in_callback ) {
 if ( ! in_array.length ) { return; } // make sure array was sent
 var i = 0; // starting index
 bgEach(); // call the function
 function bgEach() {
  if ( in_callback.call(in_array[i], i, in_array[i] ) !== false ) {
    i++; // move to next item
    if (i < in_array.length ) { setTimeout( bgEach, in_pause_ms ); }
  }
 }
 return in_array; // returns array
};
jQuery.fn.forEach = function ( in_callback, in_optional_pause_ms ) {
 if ( in_optional_pause_ms == null ) { in_optional_pause_ms = 10; } //default
 return jQuery.forEach( this, in_optional_pause_ms, in_callback ); //run it
};

The first way you can use it is just like each():

$('your_selector').forEach( function() {} );

An optional 2nd parameter lets you specify the speed/delay in between iterations which may be useful for animations (the following example will wait 1 second in between iterations):

$('your_selector').forEach( function() {}, 1000 );

Remember that since this works asynchronously, you can't rely on the iterations to be complete before the next line of code, for example:

$('your_selector').forEach( function() {}, 500 );
// next lines of code will run before above code is complete

I wrote this for an internal project, and while I am sure it can be improved, it worked for what we needed, so hope some of you find it useful. Thanks -

OneNerd
+3  A: 

Use .stop(true,true) when triggering an animation prevents it from repeating the animation. This is especially helpful for rollover animations.

$("#someElement").hover(function(){
    $("div.desc", this).stop(true,true).fadeIn();
},function(){
    $("div.desc", this).fadeOut();
});
Kenneth J
+2  A: 

using self-executing anonymous functions in a method call such as .append() to iterate through something. IE:

"use strict";
$('<ul>').append(
    (function(){
        var info = ['0','1','2','3','4','5','6'],
            oput = $('<dummy>'), x=-1, y=info.length;
        while (++x<y) {
            oput.append('<li>' + info[x] + '</li>');
        }
        return oput.children();
    }())
);

I use this to iterate through things that would be large and uncomfortable to break out of my chaining to build.

Rixius
A: 

Increment Row Index in name

Here is a neat way to increment a row index of a cloned input element if your input element name contains a row index like '0_row':

$(this).attr('name', $(this).attr('name').replace(/^\d+/, function(n){ return ++n; }));

The cloned element's name will now be '1_row'

adam
+3  A: 

Access jQuery functions as you would an array

Add/remove a class based on a boolean...

function changeState(b)
{
    $("selector")[b ? "addClass" : "removeClass"]("name of the class");
}

Is the shorter version of...

function changeState(b)
{
    if (b)
    {
        $("selector").addClass("name of the class");
    }
    else
    {
        $("selector").removeClass("name of the class");
    }
}

Not that many use-cases for this. Never the less; I think it's neat :)

roosteronacid
This is neat, and has some interesting uses, but it isn't anything specific to jQuery at all... this is just something you can do on any JavaScript object.
TM
Thanks :) ... It's basic JavaScript; yeah. But I would argue that jQuery is JavaScript. I'm not claiming that this is jQuery-specific.
roosteronacid