Upload
jeresig
View
35.122
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Talk I gave at jQuery Conference '08 and Ajax Experience '08.
Citation preview
jQuery Internals+ Cool Stuff
John Resighttp://ejohn.org/ - http://twitter.com/jeresig/
Overview✦ Why we do what we do✦ Features you may not know about✦ New features coming
Parts of jQuery✦ Common✦ Selectors✦ DOM Modification✦ Events✦ Sniffing
Chaining✦ jQuery("<li><a></a></li>") // li
.find("a") // a .attr("href", "http://ejohn.org/") // a .html("John Resig") // a .end() // li .appendTo("ul");
✦ jQuery("<li><a></a></li>") // li .find("a") // a .attr("href", "http://ejohn.org/") // a .html("John Resig") // a .andSelf() // li, a .addClass(“person”) // li, a .end() // a .end() // li .appendTo("ul");
Isolation✦ jQuery shouldn’t affect outside code
✦ We’re good at this✦ Outside code shouldn’t effect jQuery
✦ Getting better at this✦ (Still hurt by Object.prototype)
jQuery Wrapper✦ (function(){
var jQuery = window.jQuery = function(){ // ... };})();
✦ (function(){ var foo = 5;
})();
Plugin Wrapping✦ (function($){
// Your code...})(jQuery);
✦ (function(){ var $ = jQuery; // Your code...})();
noConflict✦ // Remove $
var $jq = jQuery.noConflict();✦ // Remove $ and jQuery
jQuery.noConflict(true);✦ Can even have multiple copies of jQuery
on the page, simultaneously
noConflict✦ (function(){
var oldjQuery = window.jQuery; var jQuery = window.jQuery = function(){ // ... }; jQuery.noConflict = function(all){ if ( all ) window.jQuery = oldjQuery; return jQuery; };})();
Element Data✦ Added in jQuery 1.2✦ Attaching data to elements can be
hazardous✦ Store data:
jQuery.data(elem, “name”, “value”);✦ Read data:
jQuery.data(elem, “name”);✦ All data is stored in a central cache and
completely garbage collected, as necessary
Element Data (cont.)✦ Added in jQuery 1.2.3✦ Can handle namespacing$(”div”).data(”test”, “original”);$(”div”).data(”test.plugin”, “new data”);$(”div”).data(”test”) == “original”; // true$(”div”).data(”test.plugin”) == “new data”; // true
✦ Advanced data handling can be overridden by plugins$(element).bind(”setData.draggable”, function(event, key, value){ self.options[key] = value;}).bind(”getData.draggable”, function(event, key){ return self.options[key];});
Selectors
How It Works✦ How it currently works✦ “div > p”✦ Find all divs
Loop through each div✦ Find all child elements
✦ Verify if element is paragraph
How It Works✦ “div p”✦ Find all divs
Loop through all divs✦ Find all p, relative to the div
✦ Merge all results✦ Figure out unique results
Sizzle✦ http://github.com/jeresig/sizzle/tree/master✦ New Selector Engine for jQuery✦ 1.5 - 4x faster than other libraries✦ 4KB Compressed✦ No dependencies, can be used by other
libraries (MochiKit, Prototype)
How Does it Work?✦ Query Restructuring✦ “div p”✦ Find all p elements
For each p element✦ check if parent is div
✦ if not, traverse up farther✦ if at top, remove element✦ if so, save element
✦ No merging! No unique!
How Does it Work?✦ Faster for some queries, slower for others✦ Depends on the DOM structure✦ “div > p” much faster, for example✦ Built like how browsers query the DOM
Niceties✦ Query Caching✦ if ( document.addEventListener && !document.querySelectorAll ) {
cache = {}; function invalidate(){ cache = {}; } document.addEventListener("DOMAttrModified", invalidate, false); document.addEventListener("DOMNodeInserted", invalidate, false); document.addEventListener("DOMNodeRemoved", invalidate, false);}
✦ Smart Fallbacks✦ if ( document.getElementsByClassName ) {
Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function(match, context) { return context.getElementsByClassName(match[1]); };}
Manipulation✦ Four common methods:
append, prepend, before, after✦ $(“<li>and this too!</li>”)✦ How does it work?
3-step Process✦ Cleaning the input✦ Converting it into a DOM✦ Injecting it into the DOM
Cleaning✦ Make sure we’re working with HTML
input✦ (Convert XML to HTML)✦ <table/> -> <table></table>✦ elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front,
tag){ return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? all : front + "></" + tag + ">";});
Converting✦ Inject HTML string using innerHTML✦ var div = document.createElement(“div”);
div.innerHTML = html;div.childNodes; // Your meat!
✦ But doesn’t work for all HTML✦ <tr>, <td>, <option>, <legend> (+ others)
must be in correct container elements✦ “<table><tbody>” + html + “</tbody></
table>”
Injecting✦ var elems = div.childNodes;✦ Loop through elems, cloneNode(true)
each, insert into DOM✦ 5 paragraphs✦ 100 divs✦ 2 method calls (insert, clone)✦ 1000 method
✦ *Very* slow✦ Simple plugin provides 10-15x speed-up:
http://dev.jquery.com/~john/ticket/append/
Document Fragments✦ No div.childNodes looping✦ Move the nodes into a Document
Fragment✦ Husk DOM container✦ Whole container can be cloned✦ and whole container can be injected✦ Saves a ton of repetition
Events
Non-DOM Events✦ function User(){}✦ var user = new User();✦ $(user).bind(“login”, function(){
alert(“all done”);});
$(user).trigger(“login”);
Namespaced Events✦ Added in jQuery 1.2✦ Targeted adding and removal of events✦ $(“div”).bind(“click.foo”, function(){
alert(“foo!”);});
✦ Time to clean up!$(“div”).unbind(“click.foo”);
✦ Added in jQuery 1.2.3:$(“div”).unbind(“.foo”);
Special Events✦ Added in jQuery 1.2.2✦ Can create whole shadow event system✦ New events: mouseenter, mouseleave,
mousewheel (w/ plugin), ready✦ $(”li”).bind(”mouseenter”, function(){
$(this).addClass(”hover”);}).bind(”mouseleave”, function(){ $(this).removeClass(”hover”);});
Animations✦ Full Animation plugin (in jQuery 1.2):✦ jQuery.fx.step.corner = function(fx) {
fx.elem.style.top = fx.now + fx.unit; fx.elem.style.left = fx.now + fx.unit;};
✦ $(”#go”).click(function(){ $(”#block”).animate({corner: ‘40px’}, 500);});
Sniffing✦ All major JS libraries use browser sniffing✦ Look at the user agent and make guesses✦ We can get rid of this!✦ Makes our code more resilient to change
Testing & Analysis
Testing✦ Rapid testing✦ ./gen.sh
#!/bin/shsvn co https://jqueryjs.googlecode.com/svn/trunk/jquery $1 &> /dev/nullcp $2.html $1/index.htmlcd $1make &> /dev/null
✦ ./gen.sh 1234 dom
Test Suite✦ qUnit (jQuery Test Suite)
http://docs.jquery.com/QUnit✦ By Joern Zaefferer
qUnit Usage✦ test("a basic test example", function() {
ok( true, "this test is fine" ); var value = "hello"; equals( "hello", value, "We expect value to be hello" );});
module("Module A");test("first test within module", function() { ok( true, "all pass" );});test("second test within module", function() { ok( true, "all pass" );});
module("Module B");test("some other test", function() { expect(1); ok( true, "well" );});
qUnit Output
Profiling✦ Deep Profiling Plugin✦ Watch all method calls and events✦ http://ejohn.org/blog/deep-profiling-
jquery-apps/✦ http://dev.jquery.com/~john/plugins/profile/
github.com.html ✦ javascript:jQuery.displayProfile();
Thank You!✦ John Resig✦ http://ejohn.org/✦ http://twitter.com/jeresig/