
Works great with Modernizr (www.modernizr.com)
yepnope([{
test : Modernizr.geolocation,
yep : 'normal.js',
nope : ['polyfill.js', 'wrapper.js']
}]);
yepnope([{
load: '//ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js',
complete: function () {
if (!window.jQuery) {
yepnope('local/jquery.min.js');
}
}
}, {
load: 'jquery.plugin.js',
complete: function () {
jQuery(document).ready(function($) {
$('div').plugin();
});
}
}]);
JavaScript is like your little sister, the art school student.
jQuery is your little sister's extreme makeover.
White Space Doesn't Matter
var fish = {
one : 'red'
, two : 'blue' ,
three: 'Lucy'
};
$('div').
addClass(fish.one)
. removeClass(
fish.two );
White Space Doesn't Matter — Unless It Does.
// Bad (returns undefined):
return
{
myName: 'Karl'
};
// Good (returns an object):
return {
myName: 'Karl'
};
Loose typing is fun — and frustrating.
'' == 0 // true 0 == '0' // true '' == '0' // false
false == 'false' // false false == '0' // true
false == undefined // false false == null // false null == undefined // true typeof null // "object" typeof undefined // "undefined"
Loose typing is fun — and frustrating.
'' === 0 // false 0 === '0' // false '' === '0' // false false === 'false' // false false === '0' // false false === undefined // false false === null // false null === undefined // false
Metamorphosis!
if ( !(window.matchMedia) ) {
window.matchMedia = (function(doc,undefined) {
// ... prep work ... do this stuff once, immediately
return function(q){
// ... other stuff ...
// do this each time matchMedia called
};
})(document);
}
Functions can return functions
function multiple(n) {
function f(x) {
return x * n;
}
return f;
}
var triple = multiple(3);
var quadruple = multiple(4);
console.log( triple(5) ); // 15
console.log( quadruple(5) ); // 20
console.log( multiple(4)(5) ); // 20
$ == jQuery
$() == jQuery()
$('<div id="rover" class="dog"><div class="tail">wag</div></div>')
.appendTo('body')
.bind('click', function() {
$(this).find('div.tail').effect('shake');
})
.trigger('click');
$('<div id="rover" class="dog"></div>')
.append('<div class="tail">wag</div>')
.appendTo('body')
.bind('click', function() {
$(this).find('div.tail').effect('shake');
})
.trigger('click');
$('<div></div>', {
id: 'rover',
'class': 'dog',
html: '<div class="tail">wag</div>',
click: function() {
$(this).find('div.tail').effect('shake');
}
}).appendTo('body')
.trigger('click');
var dog = {
id: 'rover',
'class': 'dog',
html: '<div class="tail">wag</div>',
click: function() {
$(this).effect('shake');
}
};
$('<div></div>', dog)
.appendTo('body').click();
var $listItems = $('li');
var numItems = $listItems.length
//no need for length check
$listItems.addClass('pretty');
if (numItems) {
// do something with other elements
}
$('#menu li').each(function(index) {
$(this).click(function() {
$('#footer li:eq(' + index + ')')
.toggleClass('active');
});
});
...like the one in the previous slide.
:eq(), :lt(), :gt():first, :last, :odd, :even:checkbox, :radio, :password, :text.eq(), .slice(0, n), .slice(n).first(), .last()input[type="checkbox"], input[type="radio"], input[type="password"], input[type="text"]:odd and :even
:nth-child(odd) and :nth-child(even) are entirely different
$('#nav a').each(function(index) {
// DOM
var thisId = this.id; // good
var otherId = $(this).prop('id'); // unnecessary
// jQuery
var thisHref = this.href; // unreliable
var otherHref = $(this).attr('href'); // better
// both
$(this).prop('id', this.id + index).addClass('indexed');
});
var foo = function() { /* do something */ };
$('div.reckless').slideToggle(300, function() {
/* do something */
});
$('div.endangerment').slideToggle(150, foo);
var KS = {};
(function() {
var foo = 'bar';
KS.foo = 'table';
})();
// foo = undefined;
// KS.foo == 'table';
var KS = function(arg) {
if ( !(this instanceof KS) ) {
return new KS(arg);
}
// do something with arg
this.arg = arg;
return this;
};
KS.prototype.foo = function(bar) {
// do something
return this;
};
KS.foo = function(bar) {
return (bar || 1) * 2;
}
var jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
};
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
init: function( selector, context, rootjQuery ) {
var match, elem, ret, doc;
// Handle $(""), $(null), or $(undefined)
if ( !selector ) {
return this;
}
// Handle $(DOMElement)
if ( selector.nodeType ) {
this.context = this[0] = selector;
this.length = 1;
return this;
}
// handle all sorts of other stuff
};
.live() … and its complementary .die().delegate() … and its complementary .undelegate()$('tr')
.bind('click', function() {
$(this).css({color: 'red'});
})
.live('click', function() {
$(this).css({backgroundColor: 'yellow'});
});
| heading | another | yet another |
|---|---|---|
| data | more data | even more |
| data | more data | even more |
.live() is better in the <head>
// live actually binds to the document element
// and it's always available, even in the head
$('a.special').live('click', function(event) {
event.preventDefault();
$('body').append('I think you are special, too!');
});
.delegate() is like a scalpel to .live()'s sledgehammer.delegate().
$('#dwrapper').delegate('span', 'click', colormeblue);
$('#ddiv').delegate('span', 'click', mybgyellow);
$('#dbtn').bind('click', injectddiv);
var myCallback = function() {
// I'mma gonna do something
}
function yourCallback() {
// You do something, too!
};
$('.mydiv').slideUp(250, myCallback);
$('.yourdiv').slideUp(250, yourCallback);
The Problem:
The Evidence:
$('.mydiv').eq(0).fadeOut('slow', function() {
$('.mydiv').eq(1).fadeOut('slow', function() {
$('.mydiv').eq(2).fadeOut('slow', function() {
$('.mydiv').eq(3).fadeOut('slow', function() {
$('.mydiv').eq(4).fadeOut('slow', function() {
// abandon all hope
});
});
});
});
});
The Solution:
var $sequence = $('div.sequence'),
index = 0;
(function sequencer() {
$sequence.eq(index++)
.animate({opacity: 'toggle'}, 'slow', sequencer);
})();
var $pulse = $('div.pulse'),
index = 0,
total = 10;
(function pulse() {
if (index++ < total) {
$pulse
.animate({opacity: 'toggle'}, pulse);
}
})();
$.fn.pulsee = function(options) {
var counter = 0, self = this;
var opts = $.extend({}, $.fn.pulsee.defaults,
typeof options === 'number' ? {total: options} : options || {}
);
(function pulse() {
if (counter++ < opts.total) {
self.animate({opacity: 'toggle'}, opts.duration, opts.easing,
function() {
opts.complete.call(this, counter-1);
pulse();
}
);
}
})();
return self;
};
$.fn.pulsee.defaults = {total: 10, complete: $.noop};
var colors = ['#900', '#090', '#009', '#cc0', '#0cc', '#c0c'];
var pulseOpts = {
total: 9,
duration: 489,
complete: function(i) {
this.style.backgroundColor = colors[i % 6];
}
};
$('#pulseer').click(function() {
$('div.pulsee').slice(0,5).pulsee(11);
$('div.pulsee').slice(5).pulsee(pulseOpts);
});
$.ajax({
url: 'http://api.jquery.com/jsonp/',
dataType: 'jsonp',
data: {
title: search
},
timeout: 15000,
success: successFn,
error: errorFn,
complete: completeFn
});
As of jQuery 1.5 (deferred.always() as of 1.6)
$.ajax({
url: 'http://api.jquery.com/jsonp/',
dataType: 'jsonp',
data: {
title: search
},
timeout: 15000
})
.done(successFn)
.fail(errorFn)
.always(completeFn);
var request = $.ajax({
url: 'http://api.jquery.com/jsonp/',
dataType: 'jsonp',
data: {
title: search
},
timeout: 15000
});
request.done(successFn);
request.fail(errorFn);
request.always(completeFn);
.done() methodsrequest.done(successFnA, successFnB, successFnC); request.done([successFnD, successFnE, successFnF]); request.done(successFnG).done(successFnH).done(successFnJ);
var api = {}, $response = $('#response');
$('#ajaxForm').bind('submit', function(event) {
event.preventDefault();
var search = $('#title').val();
$response.empty().addClass('loading');
if (!api[search]) {
api[search] = $.ajax({
url: 'http://api.jquery.com/jsonp/',
dataType: 'jsonp',
data: {
title: search
},
timeout: 15000
});
}
api[search].done(successFn).fail(errorFn).always(completeFn);
});
Thanks for listening!
Any questions?
Check out the presentation again at pres.learningjquery.com/annarbor/
Contact: