Things You Might Not Know About jQuery
Creating Elements
- jQuery provides an alternative to the traditional DOM
createElement
.
- You get to just write straight up HTML.
$("<li/>");
Creating Elements
- If you wish to modify the element or bind events to it, just use jQuery methods.
$("<li/>")
.click(function(){})
.attr("id", "test")
.addClass("clickable");
Improved Creation
- In jQuery 1.4 we provided a new way to create an element and then modify it.
- All the setting is put into a single object.
$("<li/>", {
click: function(){},
id: "test", // mix ids and jQuery methods
addClass: "clickable"
});
Complex Creation
$("<li><a></a></li>") // li
.find("a") // a
.attr("href", "http://ejohn.org/") // a
.html("John Resig") // a
.end() // li
.appendTo("ul");
- Every traversal method creates a new jQuery set and builds a stack.
- Use
.end()
to get at the previous set.
Caching with Fragments
$("<li><a></a></li>");
- It can be expensive converting that HTML into DOM nodes.
- We can speed up inserting multiple versions if we cache the nodes.
- This is where document fragments really help (we use them in jQuery).
Document Fragments
var div = document.createElement("div");
div.innerHTML = "<li><a></a></li>";
var fragment = document.createDocumentFragment();
while ( div.firstChild ) {
fragment.appendChild( div.firstChild );
}
- A document fragment is just a lightweight container that can hold some DOM nodes.
- It makes it easy to store the nodes for later all while improving the performance of insertion.
Document Fragments
someDiv.appendChild( fragment ); // one operation!
- When you insert, or clone, a fragment all of its contents are automatically inserted or cloned.
- This ends up being really fast, avoid having to insert nodes one-by-one.
Data Storage
$("div").data("test", 5);
$("div").data("test") === 5;
- jQuery has an API for invisibly storing data on DOM nodes.
- You can add data to any element (using .data) and we'll store it in a central repository.
Internal Data Storage
// Get all event handlers bound to an element
$("div").data("events");
- jQuery uses the data storage internally to keep track of all sorts of things.
- We store all the event handlers, toggling information, hide/show state, and various other bits.
Removing Data
// Remove all data bound to an element
$("div").removeData();
$("div").remove(); // also removes data
- Additionally, we'll manage all garbage collection, after the element has been removed.
Data Events
$("div").bind("getData.value", function(){
return myPlugin.realValue;
});
- We can also override the values retrieved or set on the data method by binding to getData and setData.
- Returning a value will set (or return) a completely different result.
- Very useful for plugins that want to override specific data behaviors.
Data Namespaces
$("div").data("events.plugin", { ... });
- You can also give namespaces to data, scoping it to a particular name (such as a plugin).
- This way you can avoid conflicts with other pieces of code that have the same data name, but still be able to use their get/set values.
Event Namespaces
$("div").bind("click.plugin", someFn);
$("div").bind("focus.plugin", otherFn);
$("div").unbind(".plugin");
- When you bind event handler you can also give them a namespace.
- This makes it easy to find later and easy to remove the handlers.
- Saves you from having to keep track of where all your functions are being bound, since you can just remove them by name.
Custom Events
$("div").bind("myplugin", someFn);
$("div").trigger("myplugin");
- You can bind to any event, there is no restriction on what you can or can't bind to.
- Naturally, some events are fired by the browser (click, focus, etc.)
- Everything else needs to be manually triggered.
Custom Events
$("div").bind("remove.pluginA", someFn);
$("div").bind("remove.pluginB", otherFn);
$("div").trigger("remove");
- As it turns out, custom events are a great way for multiple pieces of code (such as plugins) to bind to the same functionality.
- This creates a one to many relationship: You trigger one event but many handlers could be executed.
- This is a very efficient means of creating complex applications.
Special Events
- More complex than regular custom events (custom events don't interact with the browser).
- You can use special events to simulate other events.
- We use it for: submit, change, mouseenter, mouseleave, focusin, focusout.
- In 1.4.2 we added default special events (can be blocked with preventDefault).
Special Events
if ( document.addEventListener ) {
jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
jQuery.event.special[ fix ] = {
setup: function() {
this.addEventListener( orig, handler, true );
},
teardown: function() {
this.removeEventListener( orig, handler, true );
}
};
function handler( e ) {
e = jQuery.event.fix( e );
e.type = fix;
return jQuery.event.handle.call( this, e );
}
});
}
Submit and Change
- In jQuery 1.4 we added in cross-browser support for bubbling submit and change events.
- In IE these events don't normally bubble.
- Submit isn't that hard: You watch for the user clicking on the submit button or hitting enter in a text field.
- Change is hard: You need to track all changes to every input (using data storage) and verify that they've updated.
Event Delegation
- Event delegation is an efficient way to watch for an event on a large number of elements.
- Works by binding to a point farther up the DOM tree and watching for bubbling events.
- jQuery has two ways to do event delgation:
.live()
(as a direct replacement for .bind()) and .delegate()
.
- Works on all current, and future, elements.
.delegate()
$("table").delegate("td", "hover", function(){
$(this).toggleClass("active");
});
- Added the delegate (and undelegate) methods in jQuery 1.4.2.
- These allow you to easily listen for events from a particular context (the table, in this case).
Live Events
$("a.menu").live("hover", function(){
$(this).next().toggle(200);
return false;
});
.proxy()
var obj = { method: function(){} };
$("#foo").click( jQuery.proxy( obj, "method" ) );
$("#foo").unbind( "click", obj.method );
- In 1.4 we added a way to dynamically change the context of a function.
- This isn't a huge deal, in general, but we also made it so that you can easily remove the proxied function.
Custom Selectors
- You can create custom selectors quite easily.
- Add custom selectors to your plugins for easy querying.
jQuery.expr[":"].myplugin = function(elem) {
return !!jQuery.data("myplugin");
};
.load() page fragment
$("div.load").load("file.html h2");
hello!
jQuery UI
- A complete set of themed, cross-browser, user interface components.
- Drag, Drop, Sort, Select, Resize Accordion, Datepicker, Dialog, Slider, Tabs
- New in 1.8: Button, Autocomplete
- More info: http://jqueryui.com/
jQuery CDN
<script src='http://code.jquery.com/jquery.js'></script>
- jQuery, Google, and Microsoft all host jQuery on their CDNs.
- Automatically minified, gzipped, and geopositioned for performance.
Minified and Gzipped
- The best way to transfer JavaScript.
- Minification removes comments, whitespace, and makes other optimizations (Google Closure, YUIMin, and Packer).
- Gzipping that output compresses the filesize even further.
- jQuery goes from 150KB+ down to ~20KB.
Using Native APIs
- We're constantly watching what gets added to the latest browsers and integrating those features back in to jQuery.
- We use:
querySelectorAll
(from the Selectors API) gives us a fast CSS querying API.
- We also use:
JSON.parse
(from ECMAScript 5) that simplifies JSON parsing.
- Looking to use the new
matchesSelector
that will make .filter() and .is() faster.
What are we working on?
- Ajax rewrite - much more extensible.
- Dynamic script loading and dependency management.
- Templating - make it easy to write templating plugins.
- Mobile support - we'll test against all the major mobile browsers and guarantee support.
Bonus: (function(){})()
(function(window, undefined){
// jQuery
})(this);
- You see this convention in jQuery - it's a way of wrapping the internals, keeping it enclosed.
- We define window using 'this' so that we can keep the window name local to jQuery and still guarantee that we're getting the global object.
- We have undefined because it's an easy way to get an undefined variable that we can re-use.