2. No More Browser Sniffing
✤
As of jQuery 1.3
✤
jQuery.browser is now deprecated
✤
All uses of jQuery.browser have been removed from core.
✤
jQuery.support replaces it.
4. jQuery.support
✤ jQuery.support = {
! ! // IE strips leading whitespace when .innerHTML is used
! ! leadingWhitespace: div.firstChild.nodeType == 3,
! ! // Make sure that tbody elements aren't automatically inserted
! ! // IE will insert them into empty tables
! ! tbody: !div.getElementsByTagName("tbody").length,
! ! // Make sure that link elements get serialized correctly by innerHTML
! ! // This requires a wrapper element in IE
! ! htmlSerialize: !!div.getElementsByTagName("link").length,
! ! // Get the style information from getAttribute
! ! // (IE uses .cssText insted)
! ! style: /red/.test( a.getAttribute("style") ),
! ! // Make sure that URLs aren't manipulated
! ! // (IE normalizes it by default)
! ! hrefNormalized: a.getAttribute("href") === "/a",
! ! // Make sure that element opacity exists
! ! // (IE uses filter instead)
! ! opacity: a.style.opacity === "0.5",
! ! // Verify style float existence
! ! // (IE uses styleFloat instead of cssFloat)
! ! cssFloat: !!a.style.cssFloat,
! ! // Will be defined later
! ! scriptEval: false,
! ! noCloneEvent: true,
! ! boxModel: null
! };
5. Modularity
✤ Starting in 1.3.3 code is broken up even more
✤ Core has been split into many sub-modules
✤ core.js
✤ attributes.js
✤ css.js
✤ manipulation.js
✤ traversing.js
6. Modularity
✤
Starting to reduce dependencies in-between files
✤
Makes it easier to dynamically load portions of the library
✤
(Mobile jQuery!)
7. Mobile jQuery?
✤
“Heavy” core.js
✤
ready event
✤
find() (powered by querySelectorAll)
✤
filter() (very basic functionality)
✤
$.getScript() (for loading modules)
✤
Still experimenting...
8. Sizzle
✤
Standalone selector engine, landed in jQuery 1.3.
Selector % Used # of Uses
✤
Built for selectors that people actually use. #id 51.290% 1431
.class 13.082% 365
tag 6.416% 179
tag.class 3.978% 111
#id tag 2.151% 60
tag#id 1.935% 54
#id:visible 1.577% 44
#id .class 1.434% 40
.class .class 1.183% 33
* 0.968% 27
#id tag.class 0.932% 26
#id:hidden 0.789% 22
tag[name=value] 0.645% 18
.class tag 0.573% 16
[name=value] 0.538% 15
tag tag 0.502% 14
#id #id 0.430% 12
#id tag tag 0.358% 10
9. Right to Left
✤
Most selector engines (including jQuery, pre-1.3) evaluate a selector
left to right
✤
“#id div” - finds the element by ID “id” then finds all divs inside of it.
✤
Sizzle finds all divs then checks to see if theres an ancestor with an id
of “id”.
✤
How CSS engines work in browsers.
✤
Only one query per selector, rest is filtering.
11. Analyzing Performance
✤
Optimizing performance is a huge concern: Faster code = happy
users!
✤
Measure execution time
✤
Loop the code a few times
✤
Measure the difference:
✤
(new Date).getTime();
12. Stack Profiling
✤
jQuery Stack Profiler
✤
Look for problematic methods and plugins
✤
http://ejohn.org/blog/deep-profiling-jquery-apps/
13.
14. FireUnit
✤
A simple JavaScript test suite embedded in Firebug.
✤
http://fireunit.org/
18. ECMAScript 5 Support
✤
New in 1.3.3
✤
Removal of arguments.callee
✤
Switching from ‘RegExp to ‘new RegExp’
✤
Using JSON.parse, where available.
✤
Support for json2.js is auto-baked in.
23. .selector / .context
✤
Added in 1.3
✤
Predominantly used for plugins
✤
var div = jQuery(“div”);
div.selector === “div”;
div.context === document;
✤
jQuery.fn.update = function(){
return this.pushStack( jQuery(this.selector, this.context), “update” );
};
24. jQuery(...) unified
✤
In 1.3.3
✤
jQuery(null), jQuery(false), jQuery(undefined) => jQuery([])
✤
jQuery() is still the same as jQuery(document) (for now)
✤
BUT jQuery(“div”) points back to a common jQuery(document) root.
✤
jQuery(“div”).prevObject === jQuery()
25. jQuery(“TAG”)
✤
In 1.3.3
✤
jQuery(“body”) is now a shortcut for jQuery(document.body)
✤
jQuery(“TAG”) is optimized (skips Sizzle)
26. Position
✤
All in 1.3.3
✤
.get(-N), .eq(-N)
Access elements/jQuery sets using negative indices.
✤
.first(), .last()
Shortcuts for .eq(0) and .eq(-1)
✤
.toArray()
Shortcut for .get()
27. .data()
✤
In 1.3.3
✤
Calling .data() (no args) returns the full data object for an element
✤
jQuery(“#foo”).data(“a”, 1).data(“b”, 2).data() =>
{ a: 1, b: 2 }
31. ID-rooted Queries
✤
Changed in 1.3.3
✤
$(“#id div”) sped up dramatically
✤
#id is detected and used as the root of the query
✤
$(“div”, “#id”) --> $(“#id”).find(“div”)
✤
$(“#id div”) can likely never be as fast as $(“#id”).find(“div”)
✤
$(“#id”) is so hyper-optimized, it’s hard to match raw perf.
33. HTML Fragments
✤
Overhauled in 1.3
✤
.append(“<li>foo</li>”) first converts HTML to a DOM fragment
✤
Fragments act as a loose collection for DOM nodes
✤
Can be used to insert many nodes with a single operation
✤
var fragment = document.createDocumentFragment();
while ( node.firstChild )
fragment.appendChild( node.firstChild );
document.body.appendChild( node );
34. HTML Fragments (redux.)
✤
In 1.3.3
✤
It turns out that using fragments makes it really easy to cache them,
as well.
✤
Look for common cases that can be cached (simple, small, HTML
strings that are built more than once).
✤
Also optimized $(“<some html>”), cut out some unnecessary
intermediary code.
✤
jQuery.fragments[“<some html>”] = fragment;
35. HTML Fragments
✤
Surprising change:
✤
for ( var i = 0; i < 250; i++ ) {
$(“<li>some thing</li>”).attr(“id”, “foo” + i).appendTo(“ul”);
}
✤
Now faster than:
✤
for ( var i = 0; i < 250; i++ ) {
$(“ul”).append(“<li id=‘foo” + i + “‘>some thing</li>”);
}
36. $(“<div/>”)
✤
In 1.3:
✤
$(“<div/>”) was made equivalent to $(document.createElement
(“div”))
✤
In 1.3.3:
✤
Logic for handling createElement moved to jQuery() (performance
improved!)
37. append(function(){ })
✤
In 1.3.3 append, prepend, before, after, wrap, wrapAll, replace, replaceAll all
take a function as an argument
✤
Compliments .attr(“title”, function(){}) (and CSS)
✤
Makes:
$(“li”).each(function(){
$(this).append(“My id: “ + this.id);
});
✤
Also:
$(“li”).append(function(){
return “My id: “ + this.id;
});
38. .detach()
✤
In 1.3.3
✤
Like .remove() but leaves events and data intact.
✤ detach: function( selector ) {
! ! return this.remove( selector, true );
! },
40. .closest()
✤
Added in 1.3
✤
$(this).closest(“div”) checks if ‘this’ is a div, if not keeps going up the
tree until it finds the closest one.
✤
In 1.3.3
✤
$(this).closest(“.test”, document.body)
Prevent the traversal from going too far up the tree.
41. find() perf
✤
In 1.3.3
✤
Reduced the number of function calls - Reduced 16 calls per find() to 5.
✤ find: function( selector ) {
! ! var ret = this.pushStack( "", "find", selector ), length = 0;
! ! for ( var i = 0, l = this.length; i < l; i++ ) {
! ! ! length = ret.length;
! ! ! jQuery.find( selector, this[i], ret );
! ! ! if ( i > 0 ) {
! ! ! ! // Make sure that the results are unique
! ! ! ! for ( var n = length; n < ret.length; n++ ) {
! ! ! ! ! for ( var r = 0; r < length; r++ ) {
! ! ! ! ! ! if ( ret[r] === ret[n] ) {
! ! ! ! ! ! ! ret.splice(n--, 1);
! ! ! ! ! ! ! break;
! ! ! ! ! ! }
! ! ! ! ! }
! ! ! ! }
! ! ! }
! ! }
! ! return ret;
! },
42. find() perf
✤
Perf for $(“...”) improved, as well (hooked into rootQuery, uses less
function calls)
43. .not() / .filter()
✤
.not(function(){}) (1.3.3)
✤
.filter(Element), .filter(function(){}) (1.3.3)
✤
Full API parity inbetween .not() and .filter()
44. .index()
✤
In 1.3.3
✤
$(“div”).index() - position of element relative to siblings
✤
$(“#foo”).index(“div”) - position relative to all divs
46. Live Events
✤
Super-efficient event delegation - uses .closest(), introduced in 1.3.
✤
1.3.3 adds context and data object support.
✤
1.3.3 will ship once “submit”, “change”, and “focus/blur” events
work in .live() (in all browsers).
47. .bind() `thisObject`
✤
In 1.3.3
✤
You can now bind functions enforcing this `this`
✤
var obj = { method: function(){} };
$(“div”).bind( “click”, function(){
this.objProp = true;
}, obj );
48. Dynamic Ready Event
✤
In 1.3.3
✤
document.readyState is checked to determine if the body is already
loaded - if so, no need to wait for ready event.