getting started with jquery - adam's note · pdf file12.08.2000 · dom...
TRANSCRIPT
Outline• Philosophy of jQuery and API Walkthrough
• Dev Tools
• Bare-bones JavaScript
• jQuery Selectors and Traversing
DOM Scripting
Books
Jeremy Keith Peter-Paul Koch Jonathan Snook
domscripting.com quirksmode.org snook.ca
DOM Scripting•Verbose
if (!document.getElementsByTagName) { return false; }
var quotes =
document.getElementsByTagName("blockquote");
for (var i=0; i<quotes.length; i++) {
var source = quotes[i].getAttribute("cite");
if (source) {
var link = document.createElement("a");
link.setAttribute("href",source);
var text = document.createTextNode("source");//!?
link.appendChild(text);
var para = document.createElement("p");
para.className = "attribution";
para.appendChild(link);
quotes[i].appendChild(para);
}
}
Just a few of jQuery's
Benefits•Lets you move quickly from beginner to
advanced
•Improves developer efficiency
•Excellent documentation // pats self on back
•Unobtrusive from the ground up
•Reduces browser inconsistencies
•At its core, a simple concept
var x,y;
if (self.innerHeight) { // all except Explorer
x = self.innerWidth;
y = self.innerHeight;
}
else if (document.documentElement &&
document.documentElement.clientHeight) {
// Explorer 6 Strict Mode
x = document.documentElement.clientWidth;
y = document.documentElement.clientHeight;
}
else if (document.body) { // other Explorers
x = document.body.clientWidth;
y = document.body.clientHeight;
}
DOM Scripting
Documentation &
Support– API: api.jquery.com
– Forum: forum.jquery.com
– IRC: irc.freenode.net, #jquery
– Coming Soon: learn.jquery.com
Do Something
1. Let elements "listen" for something to happen
…
• the document is ready
• user does something
• another "listener" acts
• a certain amount of time elapses
Do Something
2. … and then do something
a. Manipulate elements
b. Animate elements
c. Communicate with the server
Dev Tools
• up to five browsers to test against
• Firefox
• Chrome
• Internet Explorer
• Safari
• Opera
• developer tools can make your life much easier
Browser Support
• Modernizr
• http://www.modernizr.com
• Can I Use?
• http://caniuse.com
• TextMate
• jQuery Bundle:
http://github.com/kswedberg
• JavaScript Tools Bundle:
http://github.com/subtleGradient
• Sublime Text 2
• MacVim
• Espresso
• jQuery Sugar:
• code.google.com/p/espresso-jquery-sugar
Text EditorsMac OS X
• E
• jQuery Bundle:
http://github.com/kswedberg
• Eclipse / Aptana
• Notepad++
• Visual Studio
• and so on.
Text EditorsWindows
• Console
• DOM Viewer
• JavaScript debugger
• Net view
• Lots of extensions
http://getfirebug.com/wiki/index.php/Firebug_Extensions
Firefox: Firebug
Chrome Developer
Tools• In many ways, leapfrogging Firebug
• Live debugging, code changing
• Lots of "hidden" goodies
• http://code.google.com/chrome/devtools/
• Paul Irish screencast: http://youtu.be/nOEw9iiopwI
• Included since Safari 3.1
• Similar to Chrome Dev Tools, but not as advanced
• Activate via Preferences > Advanced
Safari: Developer
Menu
• Much, much better than in previous versions.
• Finally includes a console.
Internet Explorer 8+:
Developer Tools
• CompanionJS:
tinyurl.com/companionjs
• IETester:
tinyurl.com/dbtester
• MS Developer Toolbar:
tinyurl.com/msdevtoolbar
• Script Debugger:
tinyurl.com/msscriptdebug
• None of them comes even close to the tools available in
other browsers
Internet Explorer <= 7
The Basics
• Strings: textual content. wrapped in quotation marks
(single or double).
• 'hello, my name is Karl'
• "hello, my name is Karl"
• Numbers: integer (2) or floating point (2.4) or octal (012)
or hexadecimal (0xff) or exponent literal (1e+2)
• Booleans: true or false
In JavaScript, you can work with the following things:
The Basics
• Arrays: simple lists. indexed starting with 0
• ['Karl', 'Sara', 'Ben', 'Lucia']
• ['Karl', 2, 55]
• [ ['Karl', 'Sara'], ['Ben', 'Lucia']]
• Objects: lists of key, value pairs
• {firstName: 'Karl', lastName: 'Swedberg'}
• {parents: ['Karl', 'Sara'], kids: ['Ben', 'Lucia']}
In JavaScript, you can work with the following things:
Variables
• Always declare your variables!
• If you don't, they will be placed in the global scope
(more about that later).
• bad: myName = 'Karl';
• good: var myName = 'Karl';
• still good: var myName = 'Karl';
// more stuff
myName = 'Joe';
Conditionals and
Operators
• conditionals:
• if, else
• switch
• operators:
• +, -, *, %, ++, --
• >, <, ==, !=, >=, <=, ===, !==
• !, &&, ||
Loops
• Loops iterate through a list of some kind.
• A common pattern in JavaScript is to build a list, or
collection, and then do something with each item in that
list.
Loops
• CSS uses implicit iteration.
• div { color: red; } /* applies to ALL divs */
• JavaScript relies on explicit iteration. Must explicitly loop
through each div
• jQuery allows for both (because it does the looping for
you)
Loops
• The two most common loops...
• for loops — for general-purpose iteration. Used with
arrays or array-like objects)
• for-in loops — used with arrays or objects (but don't
use with arrays)
• The other two are...
• while loops
• do-while loops
for (initial value; condition; increment) {
// code block
}
for Loops
• three statements and a code block
1. initial value
2. condition
3. increment
for Loopsfor (var i = 0; i < 3; i++) {
alert(i+1);}
This is your variable,
so it can be anything!
(but developers often
use “i”)
for Loopsvar divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {// do something with each div individually
divs[i].style.color = 'red';
}
for Loopsvar divs = document.getElementsByTagName('div');
// better to store length in variable first
var divCount = divs.length
for (var i = 0; i < divCount; i++) {// do something with each div individually
divs[i].style.color = 'red';
}
for Loopsvar divs = document.getElementsByTagName('div');
// can store it directly in the initializer
for (var i=0, divCount=divs.length; i < divCount; i++) {// do something with each div individually
divs[i].style.color = 'red';
}
for-in Loopsvar family = {
dad: 'Karl',mom: 'Sara',son: 'Benjamin',daughter: 'Lucia'
}
for (var person in family) {alert('The ' + person + ' is ' + family[person]);
}
This is your variable,
so it can be anything!
while and do-whilevar i = 1;
while (i < 4) {
alert(i);
i++;
}
var j = 1;
// code block always executed at least once
do {
alert(j);
j++;
} while (j < 4)
The Basics: Functions
• Functions allow you to define a block of code, name that block,
and then call it later as many times as you want.
• function myFunction( ) { /* code goes here */ } // defining
• myFunction( ) // calling the function myFunction
• You can define functions with parameters
• function myFunction(param1, param2 ) { /* code goes here */
}
• You can call functions with arguments:
• myFunction('one', 'two')
In JavaScript, you can also work with functions:
Functions// define a functionfunction doSomething() {
alert('I am something');}
// call the functiondoSomething();
Functions// define a functionfunction sumThing(a, b) {
return a + b;}
// call the functionalert( sumThing(1, 2) );
Functions// define a functionfunction sumThing(a, b) {
return a + b;}
var mySum = sumThing(1, 2);
// call the functionalert( mySum );
The arguments
Object• Every function has an arguments object
• a collection of the arguments passed to the function
when it is called
• an "array-like object" in that it is indexed and has a
length property but can't attach array methods to it
• can be looped through
• allows for variable number of arguments
Functions// call the function
function logThing() {
for (var i=0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
// call the function
logThing(1, 2, 'three');
/* prints to the console:
>> 1
>> 2
>> three
*/
Exercise
Convert the sumThing function to allow for variable
number of arguments.
function sumThing(a, b) {
return a + b;
}
Use a for loop to loop through the arguments object, adding to a "sum" variable with each iteration.After the loop, return sum.
(Simple) Solution// define a functionfunction sumThing() {
var sum = 0,countArgs = arguments.length;
for (var i = 0; i < countArgs; i++) {sum += arguments[i];
}return sum;
}// call the functionconsole.log( sumThing(1, 2, 4 ) );
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
Returning Functions• Functions can return other functions
Named vs.
Anonymous
Functions• Named:
• function foo() { } // function declaration
• var foo = function foo() { }; // function expression
• Anonymous:
• var foo = function() { }; // function expression
Anonymous Functions• Prevalent in jQuery
• Good for creating closures
• Used as "callback" functions
• Can be used as object properties (methods)
• let’s take a look ...
function() {
// variables are defined within this scope
// avoid name collisions
}
Anonymous Functions• Good for creating closures
(function() {
// variables are defined within this scope
// avoid name collisions
})();
Anonymous Functions• Good for creating closures
• Can be defined and then immediately invoked:
“immediately invoked function expression,” ( a.k.a. IIFE;
pronounced “iffy”)
(function($) { // "$" is the function's param
})(jQuery); // function is called with "jQuery"
Anonymous Functions• Good for creating closures
• Used by plugins to keep jQuery safe.
$('p').slideDown('slow', function() {
// code in here is not executed
// until after the slideDown is finished
// jQuery calls the code in here when effect
ends
});
Anonymous Functions• Used as "callback" functions
Objects
• Objects are objects : { }
• Arrays are objects : [ ]
• even Functions are objects : function( ) { }
• jQuery is an object
• Numbers, strings, and booleans (true/false) are primitive
data types, but they have object wrappers.
In JavaScript, everything is an object. Well, almost everything.
Global Object
• location
• parseInt(); parseFloat()
• isNaN()
• encodeURI(); decodeURI()
• setTimeout(); clearTimeout()
• setInterval(); clearInterval()
In the browser environment, the global object is windowIt collects all functions and variables that are global in scope.
Usually implied.
Comes with some useful properties and methods:
Date Object
var now = new Date(); // current date and time
var then = new Date('08/12/2000 14:00');
console.log( then.getTime() ); // 966103200000
console.log( then.toString() );
// Sat Aug 12 2000 14:00:00 GMT-0400 (EDT)
console.log( then.getMonth() ); // 7 !!!!
RegExp ObjectRegular Expression
• Object constructor
• var re = new RegExp('hello');
• Regular expression literal
• var re = /hello/;
Creating a RegExp• Object constructor
• var re = new RegExp('hello');
• Regular expression literal
• var re = /hello/;
Using a RegExpvar text = 'The quick brown fox';
var re = new RegExp('quick');
console.log( re.test(text) ); // true
console.log( /brown/.test(text) ); // true
console.log( /red/.test(text) ); // false
RegExp Syntax• Most characters (incl. all alphanumerics) represent
themselves
• Special characters can be escaped with a backslash (\)
Character Classes• /t.p/ matches 'tap' and 'tip' and 'top'
• /t[ai]p/ matches 'tap' and 'tip', not 'top'
• /t[a-k]p/ matches 'tap' and 'tip', not 'top'
• /t[^m-z]p/ matches 'tap' and 'tip', not 'top'
Repetition• /frog*/ matches 'fro', 'frog', 'frogg', ...
• /frog+/ matches 'frog', 'frogg', ...
• /frog?/ matches 'fro' or 'frog'
• /frog{2,3}/ matches 'frogg' or 'froggg'
Grouping• Grouping
• /(frog)*/ matches "frog" or "frogfrog"
• Alternation
• /th(is|at)/ matches "this" and "that"
Anchor Points• ^ matches the beginning of a string
• $ matches the end of a string
• \b matches word boundaries
Exercises
Write a regular expression that matches any word that
starts with a vowel.
Write a regular expression that matches any HTML tag.
String RegExp
Methods• str.search(re)
• str.match(re)
• str.replace(re, replacement)
• str.split(re)
String Replacementvar str =
'The quick brown fox jumps over the lazy dog.';
console.log(str.replace(/[aeiou]/, '*'));
// Th* quick brown fox jumps over the lazy dog.
RegExp Flags• Placed after closing / character
• Global (g): find as many as possible
• Case insensitive (i)
• Multiline (m): ^ and $ work with newlines
String Replacementvar str =
'The quick brown fox jumps over the lazy dog.';
console.log(str.replace(/[aeiou]/g, '*'));
// Th* q**ck br*wn f*x j*mps *v*r th* l*zy d*g.
console.log(str.replace(/the/gi, 'a'));
// a quick brown fox jumps over a lazy dog.
Backreferencesvar str = 'The quick brown fox jumps over the lazy dog.';
console.log(str.replace(/r(.)/g, '$1x'));
// The quick boxwn fox jumps ove xthe lazy dog.
Replacement
Functionsvar str = 'Kill 5+9 birds with 2+5 stones.';
function add(match, first, second) {return parseInt(first, 10) + parseInt(second, 10);
}str = str.replace(/([0-9]+)\+([0-9]+)/g, add);console.log(str);// Kill 14 birds with 7 stones.
Exercises
Write a function that uppercases all the vowels in
a string.
Write a function that strips the angle brackets
from around any HTML tags in a string.
Greediness• Repeat operators usually match as much of the string as
possible; they are greedy
• JavaScript supports reluctant repetition as well
• Append ? to the repeat operator
And Much More• JavaScript supports most Perl regular expression
extensions
• POSIX character classes
• Unicode character escapes
• Look-ahead assertions
Math Object
• Not a constructor, a singleton
• Gathers useful methods and properties
• Math.PI
• Math.abs(), Math.sin(), Math.pow(),
Math.random(),
• Math.max(), Math.min()
• Math.round(), Math.floor(), Math.ceil()
CSS:
h3 {
font-size: 1.2em;
line-height: 1;
}
JS:
var h3 = {
fontSize: '1.2em',
'line-height': 1
};
CSS Tip
• Object literal notation looks a lot like CSS style rule
notation!
var person = {firstName: 'Karl',lastName: 'Swedberg',hello: function() {return 'Hello, my name is ' +
this.firstName + ' ' + this.lastName;}
};
Object Literals• person is the object
• firstName and lastName are properties
• hello is a method (a property that is a function)
var person = {
firstName: 'Karl',
lastName: 'Swedberg',
hello: function() {
return 'Hello, my name is ' +
this.firstName + ' ' + this.lastName;
},
interests: {
athletic: ['racquetball', 'karate', 'running'],
musical: ['rock', 'folk', 'jazz', 'classical']
}
};
Object Literals• interests is a property and an object
Object Literalsvar person = {
firstName: 'Karl',
lastName: 'Swedberg',
hello: function() {
return 'Hello, my name is ' +
this.firstName + ' ' + this.lastName;
} // ⬅ notice, no comma here!
};
Object Literals“dot” notation
var person = {
firstName: 'Karl',
lastName: 'Swedberg',
hello: function() {
return 'Hello, my name is ' +
this.firstName + ' ' + this.lastName;
}
};
// "dot" notation
person.firstName; // 'Karl'
person.lastName; // 'Swedberg'
person.hello() // 'Hello, my name is Karl Swedberg'
Object Literalsarray notation
var person = {
firstName: 'Karl',
lastName: 'Swedberg',
hello: function() {
return 'Hello, my name is ' +
this.firstName + ' ' + this.lastName;
}
};
// array notation
person['firstName']; // 'Karl'
person['lastName']; // 'Swedberg'
person['hello']() // 'Hello, my name is Karl Swedberg'
var person = {
firstName: 'Karl',
lastName: 'Swedberg',
hello: function() {
return 'Hello, my name is ' +
this.firstName + ' ' + this.lastName;
},
interests: {
athletic: ['racquetball', 'karate', 'running'],
musical: ['rock', 'folk', 'jazz', 'classical']
}
};
// person['interests']['musical'][1] == ??
// == person.interests.musical[1]
Object Literals
Object Literalsvar person = {firstName: 'Karl',lastName: 'Swedberg',hello: function() {return 'Hello, my name is ' +
this.firstName + ' ' + this.lastName;
}
};person.firstName = 'Karl';
var prop = 'firstName';person[ prop ]; // 'Karl'
prop = 'lastName';person[ prop ]; // 'Swedberg'
Object Literalsvar blah;var person = {
firstName: 'Karl',lastName: 'Swedberg',hello: function() {return 'Hello, my name is ' +
this.firstName + ' ' + this.lastName;}
};
for (var el in person) {blah = typeof person[el] == 'function' ?
person[el]() :person[el];
console.log( blah );}
doSomething({
speed: 'fast',
height: 500,
width: 200,
somethingElse: 'yes'
});
doSomething({width: 300});
Object Literals
• Great as function arguments
• single argument allows flexibility when calling the function
JSONJavaScript Object Notation
• a data interchange format. In other words, a format for
passing data back and forth
• “discovered” and popularized by Douglas Crockford
• a subset of JavaScript Object Literal Notation
• a tree-like structure of object(s) and/or array(s)
• no functions
• all strings, including object keys, take double quotes
JSON{
"firstName": "Karl",
"lastName": "Swedberg",
"age": 24,
"interests": {
"athletic": [
"racquetball",
"karate"
]
}
}
JSON{"firstName":"Karl","lastName":"Swedberg","age":24,"intere
sts":{"athletic":["racquetball","karate"]}}
CSS Selectors
• element {}
• #id {}
• .class {}
• selector1, selector2 {}
• ancestor descendant {}
• parent > child {}
• :nth-child() {}
CSS Selectors
• $('element')
• $('#id')
• $('.class')
• $('selector1, selector2')
• $('ancestor descendant')
• $('parent > child')
• $(':nth-child(n)')
(jQuery Equivalents)
CSS Selectors
• $('element')
• $('#id')
• $('.class')
• $('selector1, selector2')
• $('ancestor descendant')
• $('parent > child')
• $(':nth-child(n)')
(jQuery Equivalents)
• and others …
• $('prev + selector')
• $('prevAll ~
selector')$(':nth-
child(an+b')$(':not(select
or)')
• $(':checked')
• $(':disabled')
CSS Attribute
Selectors• $('input[name=firstname\\[\\]]')
• $('[title]') has the attribute
• $('[attr="val"]') attr equals val
• $('[attr!="val"]') attr does not equal val
• $('[attr~="val"]') attr has val as one of space-sep.
vals
• $('[attr^="val"]') attr begins with val
• $('[attr$="val"]') attr ends with val
• $('[attr*="val"]') attr has val anywhere within
Custom Form
Selectors• $('div.myclass :checkbox')
• $(':input') <input>, <textarea>, <select>,
<button>
• $(':text') <input type="text">
• $(':radio') <input type="radio">
• $(':button') <input type="button">, <button>
• $(':selected') <option selected="selected">
• etc.
Custom Misc.
Selectors• $(':animated')
• $(':has(descendant)')
• $(':eq(n)')
• $(':lt(n)')
• $(':gt(n)')
• $(':even')
• $(':odd')
• $(':visible')
$(':hidden')$(':header')$
(':contains(string)')
Selectors• List of all selectors on the jQuery API site
• http://api.jquery.com/category/selectors
<ul> <li>level 1 <ul class="foo"> <li>level 2
<ul> <li class="bottom"><span>level</span>
3</li> </ul> </li> </ul> </li></ul>
Move Up• parent() : up one level $('li.bottom').parent();
• parents() : up multiple levels $('span').parents('ul');
• parentsUntil() : possibly multiple
$('span').parentsUntil('ul');
<ul> <li>level 1 <ul> <li>level 2 <ul>
<li class="bottom"><span>level</span> 3</li>
</ul> </li> </ul> </li></ul>
Move Up• .closest(selector) : up 0 or more levels
• $('span').closest('ul');
• $('.bottom').closest('li');
Move Sideways• .siblings()
• .next()
• .nextAll()
• .nextUntil()
• .prev()
• .prevAll()
• .prevUntil()
Filter• .filter(selector)
• .filter('.some-class')
• .filter(function)
• .filter(function() {
• return $(this).parents('li').length >=
2;
• });
Filter• .not(selector)
• .not('.some-class')
• .not(function)
• .not(function() {
• return $(this).parents('li').length >=
2;
• });
Context• $('selector', 'context')
• Different from "or" selector – $('selector1, selector2')
• Same as $('context').find('selector')
• Not worth using; too confusing.
• .add()
• .andSelf()
• .end()
Traversal Methods• List of all traversal methods on the jQuery API site
• http://api.jquery.com/category/traversing
Chaining• JavaScript has chaining built in.
• 'swap this text'.replace(/w/, 'n').replace(/this/,'that');
• '616-555-1212'.split('-').join('.');
• jQuery takes advantage of this concept by having almost
all methods return the jQuery object.
$('a').addClass('foo').parent('li').removeClass('foo')
Chaining
• DOM Traversal methods are different from other jQuery
chaining methods!
• New jQuery instance is created with each one.
var lis = $('.container li:first').addClass('first-li')
.next()
.addClass('second-li').end()
.nextAll()
.addClass('not-first-li').end(); // unnecessary; added for symmetry
Chaining
• JavaScript ignores white space, so use it to your advantage.
$('li').removeClass('myclass'); //implicit
$('li').each(function(index) { //explicit$(this).append( ' #' + (index+1) );
});
Looping
• Implicit Iteration
• Explicit Iteration (Looping)
$('li').each(function() {
console.log( this ); // DOM element
console.log( $(this) );
});
this Keyword
• Refers to the current object
• jQuery sets this to matched elements in the jQuery object.
var $listItems = $('li');var numItems = $listItems.length
//no need for length check
$listItems.addClass('pretty');
if (numItems) {
// do something with other elements
}
Tips
• Store selectors used more than once in variables
• Use length property to check existence
• ...but often no need for the check
$('#menu li').each(function(index) { $(this).click(function() {$('#footer li:eq(' + index + ')').addClass('active');
});});
Tips
• Concatenate to pass in a variable
// bad$(':checkbox') // better$('input:checkbox')// best$('input[type="checkbox"]')
Tips
• Avoid jQuery's custom selectors when possible
// uncool$('div:first')
// cool$('div').first();
Tips
• Avoid jQuery's custom selectors when possible
// slower$('li:eq(3)')$('li:lt(3)')
// faster$('li').eq(3)$('li').slice(0, 3)
Tips
• Avoid jQuery's custom selectors when possible
Loading Events
• $(document).ready();
• .load()
• Typically used with $(window)
• Also helpful with images, but be careful!
Multiple “Ready”
Handlers• All are executed
• Execution takes place in order defined
• Can even be defined after the document is ready!
$('button').bind('click', function(event) {// button got clicked
});
Low-level methods.bind()
• add an event listener to elements
• can be a native event like "click"
• can be a custom event, triggered by other code
$('button').bind('click', function(event) {// this is the <button> DOM element// this.className += ' clicked';// $(this) returns jQuery object w/ 1 element// $(this).addClass('clicked');
});
Method Context• The “this” keyword
• DOM Elements vs. jQuery Objects
$('button').trigger('click');
Low-level methods.trigger()
• Trigger events programmatically
• Works for native and custom events
Low-level methods.bind() and .trigger()
// this listens for a click on a span$('span').bind('click', function() {
/* this stuff happens when a span is clicked */
});
// maybe the user will click on a span. Or...
// this triggers any click event bound to a span$('span').trigger('click');
$('button').bind('click', clickListener).bind('click', otherListener);
// unbind all click listeners$('button').unbind('click');
// unbind only the specified listener$('button').unbind('click', clickListener);
Low-level methods .unbind()
• remove an event listener from elements
• remove all listeners, or just the specified one
$('button').click(clickListener);
// == $('button').bind('click', clickListener);
$('button').click();
// == $('button').trigger('click');
Shorthand Syntax
Shorthand Syntax
• .submit()
• .change()
• .focus()
• .focusin()
• .blur()
• .focusout()
• .mouseover()
• .mouseout()
• .mouseenter()
• .mouseleave()
• .mousemove()
• .dblclick()
• .keydown()
• .keypress()
• .keyup()
• .scroll()
• .resize()
• .error()
Event Propagation
a.k.a. “event bubbling”a.k.a. “event bubbling”http://www.quirksmode.org/js/events_order.html
Event Propagation
a.k.a. “event bubbling”http://www.quirksmode.org/js/events_order.html
Two Event Tutorials
• How to ensure that new elements added to the DOM have
events bound to them.
• by using event delegation:
Working with Events, part 1 ( tinyurl.com/eventdelegation )
• by re-binding:
Working with Events, part 2 ( tinyurl.com/eventrebinding )
Event Propagation
• Sometimes we don't want events to bubble.
• Responding to hovers on menus
• (which, maybe, we shouldn't do anyway)
• mouseover vs. mouseenter demo
• alternative event handling architecture
• scales much better
• makes it trivial to add and remove elements
• uses event.target rather than this
*(but jQuery's delegation methods map this to event.target)
• don't ask every element for events, ask a parent instead
• effort is moved from binding to handling
Event delegation
Event Delegation
• .live()
• binds an event handler to the document.
• triggered when element acted upon or one of its ancestors
matches selector
• .die()
• unbinds an event handler
$('button').live('click', function(event) {// button got clicked
});
// unbind click on button$('button').die('click');
Event Delegation• .live() and .die() look just like .bind() and .unbind()
Event Delegation
•Stop using .live() and .die()• They are deprecated as of jQuery 1.7
• They don't work as expected in some situations:
• $('#wrapper').find('a, span').live('click', fn);
• They require events to bubble all the way up to document.
• But, if you're using them successfully with older
jQuery versions, no worries!
Event Delegation• .delegate()
• binds an event handler to jQuery set.
• triggered when element indicated in first argument is
acted upon or one of its ancestors matches the first
argument
• more "optimized" delegation
• .undelegate()
• unbinds an event handler
$('#wrapper').delegate('button', 'click', function(event) {
// button got clicked});
// unbind click on button$('#wrapper').undelegate('button', 'click');
Event Delegation
Event Delegation• .on()
• new in jQuery 1.7
• the future of jQuery event handling
• one event handler method to rule them all
• use instead of .bind() and .live() and .delegate()
• .off()
• unbinds event handlers bound by .on()
$('button').on('click', clickListener).on('click', otherListener);;
// remove all click listeners$('button').off('click');
// remove only the specified listener$('button').off('click', clickListener);
Direct Event Binding
$('#wrapper').on('click', 'button',function(event) {
// button got clicked});
// remove click listeners$('#wrapper').off('click', 'button');
Event Delegation
event object• normalized by jQuery to provide consistent information
across browsers
• event.target to access the element that triggered the event
• event.pageX/Y for mouse position
• event.preventDefault() to prevent an event's default action
• event.stopPropagation() to prevent an event from bubbling
• event.which to identify which key is pressed
• more event properties at
http://api.jquery.com/category/events/event-object/
$('a.toggler').on('click', function(event) {event.preventDefault();event.stopPropagation();
$(this).parent().next().slideToggle();
// or, return false to both // preventDefault and stopPropagation// (but problematic)
});
event object example• prevent the default action from occurring
• stop the event's propagation up the DOM
$('button').on('mouseenter mouseleave', function(event) {var isEntered = event.type == 'mouseenter';
$('#something').toggleClass('active-related', isEntered);
if (isEntered) {// do one thing
} else {// do another
}});
event object example• identify the type of event being triggered
event object
• Very useful for key events
• event.which : key code normalized by jQuery
• event.metaKey : command / ⌘ on Mac, control on Win
• event.altKey : alt / option / ⌥ on Mac
• event.ctrlKey : control key everywhere
• event.shiftKey
• key event demo
if (document.createTouch) {
$('body').bind('touchstart touchmove touchend', function(event) {
// use the original event:event = event.originalEvent;
// pass the first touch object as a second argumentvar touch = event.targetTouches[0];sideSwipe[ event.type ](event, touch);
});}
event object
• access newer event types through the original event
// declare some variables up here (startcoords, endcoords, etc.)
var sideSwipe = {touchstart: function(event, firstTouch) {
startcoords = {x: firstTouch.pageX, y: firstTouch.pageY};},touchmove: function(event, firstTouch) {
if (event.targetTouches.length === 1) {event.preventDefault();endcoords = {x: firstTouch.pageX, y: firstTouch.pageY};
} else {endcoords = startcoords;
}},touchend: function(event) {// direction of horizontal swipe?// also, far enough horiz, not too far vert.?// if so, do something
}};
what?• sideSwipe[ event.type ](event, touch);
var sideSwipe = {touchstart: function(event, firstTouch) { },touchmove: function(event, firstTouch) { },touchend: function(event) { }
};
// if event.type equals 'touchstart', then:
/*
sideSwipe.touchstart() == sideSwipe['touchstart']()
sideSwipe['touchstart']() == sideSwipe[event.type]()
*/
what?• sideSwipe[ event.type ](event, touch);
var myEvents = {focus: function() {
alert('focused!');},blur: function() {
alert('blurry!');}
};
$('input').on( myEvents );
Wait!
• There must be a better way...
• First argument for .on() and .bind() can accept a map of event
types and their handler functions
var sideSwipe = {'touchstart touchmove': function(event) {
event = event.originalEvent;var firstTouch = event.targetTouches[0];
if (event.type == 'touchstart') {startcoords = {x: firstTouch.pageX, y: firstTouch.pageY};return;
}
if (event.targetTouches.length === 1) {event.preventDefault();endcoords = {x: firstTouch.pageX, y: firstTouch.pageY};
} else {endcoords = startcoords;
}},touchend: function(event) {
// get direction of horizontal swipe// also, far enough horiz, not too far vert.?// if so, do something
}};
event map
var $foo = $('#foo');var karlClicks = function() { /*do something*/ };
$foo.on('mouseenter.karl', function() { /*do something*/ });$foo.on('click.karl', karlClicks);
$foo.on('click', function() { /* do something */ });
$foo.off('.karl'); // stop doing .karl things
• Namespace events to ease unbinding
• Especially nice in plugins
Namespacing events
Custom Events• Awesome for "evented" programming
• Set up a bunch of behaviors all in one place.
• Fire at will ( .trigger() )
$(document).on('start.game', myGameStartFn);
$(document).on('stop.game', myGameStopFn);
$(document).on('updateScore.game', function(event, data) {
$.ajax('/gameserver/', data);
$('#scoreboard .score').html( data.score );
});
$(document).on('updateBoard.game', function(event, data) {
if (data.killed) {
$(event.target).fadeOut(400, function() {
$(this).remove();
});
}
});
$('div.alien').on('click', function(event) {
score += 1000;
var data = {
score: score,
killed: this.className,
name: $(this).data('name')
};
$(this)
.trigger('updateBoard.game')
.trigger('updateScore.game', [data]);
if ( score > 1000000) {
$(document).trigger('stop.game');
}
});
Custom Events Fake Example
• Create Elements
• Insert Elements
• Element Content
• Remove Elements
• Element Properties and Attributes
• Styles and Dimensions
DOM Manipulation
$('<div/>', {'class': 'test',html: '<b>Click me!</b>',click: function(){$(this).toggleClass('test');
}});
reserved word
$('<div/>', {'class': 'test',html: '<b>Click me!</b>',click: function(){$(this).toggleClass('test');
}}).appendTo('body');
• add and move elements
• inside others with .append(), .appendTo(), .prepend() and
.prependTo()
• before and after others with
.after(), .insertAfter(), .before() and .insertBefore()
• around others with .wrap(), .wrapAll() and .wrapInner()
• in place of others with .replaceWith() and .replaceAll()
Insert Elements(or move them)
• $('<div></div>').appendTo('#mydiv');
• $('#mydiv').append('<div></div>');
• $('<div></div>').insertAfter('#mydiv');
• $('#mydiv').after('<div></div>');
• // and so on
Insert Elements(or move them)
• In 1.4 and above, a subset of these methods can take a
function
• .append()
• .prepend()
• .after()
• .before()
• .wrap()
• .wrapInner()
• In the function, you'll need to return the content you want to
insert
Insert Elements(or move them)
• Remove elements with .remove()
• Cleans up data and events
• Remove elements with .detach()
• Leaves data and events alone
• Remove their content with .empty()
• Cleans up data and events
Remove Elements
• Get and set HTML content via .html()
• executes embedded JavaScript when setting
• Get and set text content via .text()
• escapes HTML entities (<, >, &)
• recursive (drills down / concatenates)
• Get and set form element values with .val()
Element Content
Attributes &
Properties• Get and set any property with .prop()
• Remove properties with .removeProp()
• Get and set any attribute with .attr()
• Remove attributes with .removeAttr()
Attributes &
Propertieswhat's the difference?• Attributes are what you see in the HTML.
• Properties are ... well ... properties of DOM elements (objects)
Attributes &
Propertieswhat's the difference?• Some props don't have attr equivalents
• Some props and attrs have different names
prop attrselectedIndex, tagName, nodeName,
nodeType, ownerDocumentnothing, nada, zilch,
nil, goose egg
htmlFor for
className class
Attributes &
Propertieswhat's the difference?• Some attributes are considered boolean attributes
• For these, you really ought to get and set with .prop()
• ... even though jQuery will still coddle you if you do it wrong
Attributes &
Propertieswhat's the difference?• <input type="checkbox" checked="checked">
• <script>
• // DOM property
• // Will change with checkbox state
• elem.checked == true;
• // Will change with checkbox state
• $(elem).prop("checked") == true;
• </script>
Attributes &
Propertieswhat's the difference?• <input type="checkbox" checked="checked">
• <script>
• // DOM method
• // Initial state of the checkbox; does not change
• elem.getAttribute("checked") == "checked";
• //(1.6) Initial state of the checkbox; does not change
• $(elem).attr("checked") == "checked";
• //(1.6.1+) Will change with checkbox state
• $(elem).attr("checked") == "checked";
Attributes &
Properties• Remember me?
$('<div/>', {
'class': 'test'
});
• I use .attr() (so you must use "class", not "className")
$('input').attr({title: 'this is my title', name: 'some_name'
});
$('input').attr('title', 'this is my title');
Attributes
• set attribute:
$('img').attr({title: function(index, value) {return 'I do believe that ' + value;
}, name: 'some_name'
});
$('a').attr('title', function() {return 'go to ' + this.href;
});
Attributes
• set attribute:
$('input').prop({title: 'this is my title', name: 'some_name'
});
$('input').prop('title', 'this is my title');
Properties
• set property:
$('img').prop({title: function(index, value) {return 'I do believe that ' + value;
}, name: 'some_name'
});
$('a').prop('title', function() {return 'go to ' + this.href;
});
Properties
• set property:
• Use .css() to modify the style property
• Use .addClass(), .removeClass() and .toggleClass() to modify
the class attribute
• When possible, manipulate the class attribute to change
appearance, separating the actual design from the behavior
Styles
$('a').css({backgroundColor: 'red', 'margin-top': '10px'
});
$('a').css('backgroundColor', 'red');
Style Properties• set style property
Notice!
either DOM
prop or CSS
syntax
$('a').css('fontSize', function() {
return parseInt($(this).css('fontSize'),10) + 2 + 'px';
});
$('a').css({
backgroundColor: 'red',
marginTop: function(index, value) {
return parseInt(value,10) * 1.4;
}
});
Style Properties• set style property:
• Get and set width and height via .width() and .height()
• return a number
• nice for calculations
• Get and set the element offset relative to the document with
.offset()
• returns an object
• e.g. {top: 34, left: 50}
• Get the element offset relative to its "offset parent" with
.position()
Dimensions
• associate data with elements
• plugin settings
• plugin instances
• avoid storing data directly on DOM elements
• avoid memory leaks
• Set data: $('div').data('personalInfo', {firstname:'karl'});
• Get data: $('div').data('personalInfo');
• Remove data: $('div').removeData('personalInfo');
Data
• As of jQuery 1.4.4, can read HTML5 data-* attributes.
• jQuery guesses what the type is and treats it accordingly.
• To parse a data value as an object, it must appear as
valid JSON.
• Read learningjquery.com/2011/09/using-jquerys-data-
apis
• <div data-img='{"alt":"pic","src":"path/file.jpg"}'>
</div>
• $('div').data('img');
Data
Ajax
• Unobtrusive client-server data exchange
• avoid page refresh
• Affords much more interactive applications
• becoming nearly indistinguishable from desktop applications
• Progressive Enhancement is essential
$.ajax
• jQuery's low-level abstraction for Ajax
• all high-level methods build on it
• Configured per request or global defaults
$.ajax({url: '/url/to/serverResource'
});
$.ajax options: url
• Address of the server-side resource
• Can contain query string
• use data instead
$.ajax('/url/to/serverResource');
$.ajax options: url
• Address of the server-side resource
• Can be passed as a string to first argument (as of 1.5)
$.ajax({url: '/url/to/serverResource',data: {key1: 'value1',key2: 'value2'
}});
$.ajax options: data
• To send information from client to server
• with GET: Appended to url as query string
• with POST: Sent as POST body
$('#myform').submit(function(event) {event.preventDefault();
var formUrl = $(this).attr('action'),formData = $(this).serialize();
$.ajax({url: formUrl,data: formData
});
});
$.ajax options: data
• When submitting a form, use .serialize( )
$.ajax options:
dataType• 'html' for HTML to insert into document
• 'xml' for XML documents, eg. web services
• 'json' for compact alternative to XML
• parsed using browser's native JSON parser if available
• much easier to use in JS than XML
• 'jsonp' for remote resources. Gets around same-origin
policy.
• Response acts like a function with a JSON string as its
argument. jQuery calls it and parses the JSON.
• 'script' for JavaScript files
• Evaluates the response as JavaScript and returns it as
plain text.
$.ajax({url: '/url/to/serverResource',dataType: 'json'
});
$.ajax options:
dataType• Specifies expected response
• Default based on MIME Type of the response
$.ajax options:
Lots More• Read all about 'em at api.jquery.com/jQuery.ajax/
$.ajax({
url: '/url/to/serverResource',
success: function(response, status, xhr) {
// do something after successful request
},
error: function(xhr, status, errorThrown) {
// handle failed request
},
complete: function(xhr, status) {
// do something whether success or error
}
});
$.ajax responses• Before jQuery 1.5, these were handled by three more options (!!)
• { success: function(){}, error: function(){}, complete:
function(){} }
• don't use them anymore
Ajax error handling
• Explicit testing for ajax errors is important
• Network failures don't occur in local development
environment
• p.s. JSON parsing errors throw an exception
$.ajax responses• $.ajax implements the Promise interface
• returns a jqXHR object (superset of xhr), a Promise
• Promise objects are derived from the Deferred object
• Not enough time to dive into that today
• Read api.jquery.com/category/deferred-object/
• jQuery 1.5+:
• .done() and .fail() methods
• jQuery 1.6+:
• .always() method
$.ajax responses1.5+
• Methods can be called multiple times to add more than one
handler.
• Can store result of Ajax request in variable and attach handlers
later for more manageable code structure.
• Handlers will be invoked immediately if the Ajax operation is
already complete when they are attached
• Ajax requests can be cached in a simple, elegant way
$.ajax responses1.5+• var myOptions = {
• url: 'http://api.jquery.com/jsonp/',
• dataType: 'jsonp',
• data: {
• title: search
• }
• };
• $.ajax( myOptions )
• .done( successFn )
• .fail( errorFn )
• .always( completeFn );
request.done(successFnA, successFnB, successFnC);
request.done([successFnD, successFnE, successFnF]);
request.done(successFnG).done(successFnH).done(successFnJ);
$.ajax responses1.5+
• Multiple function arguments
• Array of functions
• Multiple, chained .done() methods
Caching Ajax
Responses• A simple approach
• For more generic, abstracted approach, see Script Junkie:
"Creating Responsive Applications Using jQuery Deferred and
Promises" bit.ly/tph6F6
Caching Ajax
Responses• (function() {
• var api = {}, $response = $('#response');
• $('#ajaxForm').bind('submit', function(event) {
• event.preventDefault();
• var search = $('#title').val();
• $response.empty().addClass('loading');
•
•
Caching Ajax
Responses• (function() {
• var api = {}, $response = $('#response');
• $('#ajaxForm').bind('submit', function(event) {
• event.preventDefault();
• var search = $('#title').val();
• $response.empty().addClass('loading');
• var ajaxResults = $.ajax({
• url: 'http://api.jquery.com/jsonp/',
• dataType: 'jsonp',
• data: {
• title: search
• },
• timeout: 15000
• });
Caching Ajax
Responses• (function() {
• var api = {}, $response = $('#response');
• $('#ajaxForm').bind('submit', function(event) {
• event.preventDefault();
• var search = $('#title').val();
• $response.empty().addClass('loading');
• api[search] = $.ajax({
• url: 'http://api.jquery.com/jsonp/',
• dataType: 'jsonp',
• data: {
• title: search
• },
• timeout: 15000
• });
Caching Ajax
Responses• (function() {
• 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
• });
Caching Ajax
Responses• (function() {
• 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
• });
$('#myid').load('/foo.html #anotherid');
$('#myid').load('/foo.html #anotherid', function() {// do something on complete
});
Ajax Convenience
Methods• $('elem').load( )
• The "convenientest" of all …
• Single argument can do it all. Often no need for callback
function.
Introduction
• Effects can enhance user interaction
• Prefer subtle over in-your-face
• jQuery provides a base set of animations
• make animations:
• long enough to be noticeable
• short enough to not annoy
Fades• great to show/hide overlay elements
• tooltips
• dialogs
• warning/info messages
• Examples:
• $('.tooltip').fadeIn();
• $('.tooltip').fadeOut('slow');
• $('.tooltip').fadeToggle(250);
• $('.tooltip').fadeTo(200, 0.5);
$('div.panel').wrapAll('<div class="panel-wrapper"></div>');
$('div.panel-heading a').click(function() {$(this).parent().next('.panel-wrapper').slideToggle();return false;
});
Slides
• show and hide elements within the page structure
• less jarring than un-animated show/hide
$('div.toRemove').slideUp('slow', function() {$(this).remove();
});
$('div.move').slideDown(250).promise().done(function() {alert('Finished!');
});
Callback
• Function executed when the animation ends
• Called once for each animated element
• Consider using .promise()
Animation Order
• By default multiple animations occur:
• in sequence for the same element(s)
• simultaneously for different element(s)
Custom Animations
• $('div.toMove').animate(propsObject, duration, easing, callbackFn);
• $('div.toMove').animate(propsObject, optionsObject);
• Properties can be animated
• by number, percent, etc.
• relatively ("+=200px", "-=20%", etc.)
• by keyword: "hide", "show", or "toggle"
$('.toMove').animate({left: '+=300px'
}, 800);
// same thing$('.toMove').animate({
left: '+=300px'}, {
duration: 800});
Custom Animations
• Create custom animations
• Example, slowly moving an element 300px to the right:
Custom Animations• Options object allows for fine tuning:
• duration: A string or number determining how long the animation will run.
• easing: A string indicating which easing function to use for the transition.
("linear", "swing". More with plugin.)
• complete: A function to call once the animation is complete. (callback
function.)
• step: A function to be called after each step of the animation.
• queue: A Boolean indicating whether to place the animation in the effects
queue. If false, the animation will begin immediately.
• specialEasing: A map of one or more of the CSS properties defined by the
properties argument and their corresponding easing functions (added 1.4).
$('#foo').animate({height: 'toggle'}, {
duration: 600,
easing: 'linear'
});
Easing
• Changes the velocity at different points in the animation
• A number of standard equations first created by Robert Penner
• Available with jQuery UI
• Also, stand-alone at http://gsgd.co.uk/sandbox/jquery/easing/
$('#clickme').click(function() {$('#book').animate({
width: ['toggle', 'swing'],height: ['toggle', 'swing'],opacity: 'toggle'
}, 5000, 'linear', function() {$(this).after('<div>complete!</div>');
});});
Easing
• Per-property easing available as of jQuery 1.4.
$('.toMove').click(function() {if (!$(this).is(':animated')) {
$(this).animate({left: '+=300px'
}, 'slow');}
});
Currently Animated
• Identify elements that are currently animated
$('#badges li').hover(function(){$(this).stop(true,
true)
.animate({bottom:"30px"}, 200);},
function(){$(this).stop(true, false)
.animate({bottom:"8px"}, 500);});
Stop
• Stop current animations from continuing.
• Two arguments: clearQueue and gotoEnd (both boolean)
$('#warning').fadeIn(600).delay(4000).fadeOut();
Delay
• Delays any further items in the queue from executing for a
specified period of time.
// animation will complete in 400ms$('#foo').slideToggle();
// modify default globally for all future effects$.fx.speeds._default = 250;
// animation will complete in 250ms$('#foo').slideToggle();
Global Duration
• Globally change the duration that all animations will use unless
a duration is specified.
$('.animations').click(function() {
$.fx.off = !$.fx.off;
});
Global Off
• Globally prevent all animations from occurring