becoming a jquery expert
DESCRIPTION
A workshop I gave at Dr. Dobbs India in the cities of Bangalore and Pune.TRANSCRIPT
Becoming a jQuery Expert
Code
Download:http://bit.ly/drdobbs-jq-zip
Browser Console
Chrome: Option-Command-J or Control-Shift-J
Firefox: Option-Command-K or Control-Shift-K
Internet Explorer: F12
Safari:
• Advanced Settings
• Check box next to “Show Develop menu in menu bar”•Option-Command-C
DOM Traversal
DOM Traversal
$('p');
[<p></p>]
DOM Traversal
Filtering$('p').first();[<p id= "s1p1" class= "active section1"> Paragraph 1 </p>]
$('p').last();[<p id= "s2p4" class= "active section2"> Paragraph 4 </p>]
$('ul').find('li');[<li data-price= "100"> Unordered list item 1 </li>,<li data-price= "275"> Unordered list item 2 </li>,<li data-price= "50"> Unordered list item 3 </li>,<li data-price= "150"> Unordered list item 4 </li>]
DOM Traversal
Filtering$('p').filter('.inactive');[<p id= "s1p2" class= "inactive section1"> Paragraph 2 </p> , <p id= "s2p2" class= "inactive section2"> Paragraph 2 </p>]
$('p').filter(function () { return $(this).hasClass('inactive');});
$('p').map(function () { return this.id;});
["s1p1", "s1p2", "s1p3", "s1p4", "s2p1", "s2p2", "s2p3", "s2p4"]
DOM Traversal
A deeper look at .map
$('p').map(function (idx, el) { var text = $(el).text(), num = text.replace(/Paragraph\s/, ''), num = parseInt(num, 10); return num % 2 === 0 ? el : undefined;});[<p id= "s1p2" class= "inactive section1"> Paragraph 2 </p>,<p id= "s1p4" class= "active section1"> Paragraph 4 </p>,<p id= "s2p2" class= "inactive section2"> Paragraph 2 </p>,<p id= "s2p4" class= "active section2"> Paragraph 4 </p>]
Try it!Try it!
DOM Traversal
Getting elements relative to a start point$('#s2').prev();[<section id= "s1"> … </section>]
$('#s2p4').prevAll();[<p id= "s2p3" class= "active section2"> Paragraph 3 </p>,<p id= "s2p2" class= "inactive section2"> Paragraph 2 </p>,<p id= "s2p1" class= "active section2"> Paragraph 1 </p>, <h1> Section 2 </h1>]
$('#s2p4').prevUntil('.inactive');[<p id= "s2p3" class= "active section2"> Paragraph 3 </p>]
DOM Traversal
Getting elements relative to a start point$('#s1').next();[<section id= "s2"> … </section>]
$('#s1p1').nextAll();[<p id= "s1p2" class= "inactive section1"> Paragraph 2 </p>, <p id= "s1p3" class= "active section1"> Paragraph 3</p>, <p id= "s1p4" class= "active section1"> Paragraph 4</p>, <ul> … </ul>]
$('#s1p1').nextUntil('ul');<p id= "s1p2" class= "inactive section1"> Paragraph 2 </p>,<p id= "s1p3" class= "active section1"> Paragraph 3 </p>, <p id= "s1p4" class= "active section1"> Paragraph 4 </p>]
DOM Traversal
Getting elements relative to a start point$('#s1').parent();[<div id="markup"> … </div>]
$('p').closest('section');[<section id= "s1"> … </section>,<section id= "s2"> … </section>]
$('#s1p3').siblings();[<h1> Section 1 </h1>,<p id= "s1p1" class= "active section1"> Paragraph 1</p>,<p id= "s1p2" class= "inactive section1"> Paragraph 2 </p>,<p id= "s1p4" class= "active section1"> Paragraph 4</p>,<ul> … </ul>]
DOM Traversal
Chaining traversal methods$('#s1p3').siblings().andSelf();[<h1> Section 1 </h1>,<p id="s1p1" class="active section1"> Paragraph 1</p>,<p id="s1p2" class="inactive section1"> Paragraph 2 </p>,<p id="s1p3" class="inactive section1"> Paragraph 3 </p>,<p id="s1p4" class="active section1"> Paragraph 4</p>,<ul> … </ul>]
$('#s1p4').parent().next();[<section id= "s2"> … </section>]
$('#s2p1').add($('#s1p1'));[<p id= "s1p1" class= "active section1"> Paragraph 1 </p>, <p id= "s2p1" class= "active section2"> Paragraph 1 </p>]
Try it!Try it!
DOM Traversal
Some filters can be expressed as selectors.*
*May impact performance.
DOM Traversal
Filters as selectors$('p:even');[<p id= "s1p1" class= "active section1"> Paragraph 1 </p>, <p id= "s1p3" class= "active section1"> Paragraph 3 </p>, <p id= "s2p1" class= "active section2"> Paragraph 1 </p>,<p id= "s2p3" class= "active section2"> Paragraph 3 </p>] // zero-based
$('p:odd');
$('p:first');
$('p:last');
$('p:not(".inactive")');
DOM Traversal
More selectors$(':header');[<h1> Section 1 </h1>, <h1> Section 2 </h1>]
$('li:nth-child(2)');[<li data-price= "275"> Unordered list item 2 </li>, <li> Ordered list item 2 </li>]
DOM Traversal
Adding context to narrow things down$('li');[<li data-price= "100"> Unordered list item 1 </li>, <li data-price= "275"> Unordered list item 2 </li>, <li data-price= "50"> Unordered list item 3 </li>, <li data-price= "150"> Unordered list item 4 </li>, <li> Ordered list item 1 </li>, <li> Ordered list item 2 </li>, <li> Ordered list item 3 </li>, <li> Ordered list item 4 </li>]
$('li', 'ul');[<li data-price= "100"> Unordered list item 1 </li>, <li data-price= "275"> Unordered list item 2 </li>, <li data-price= "50"> Unordered list item 3 </li>, <li data-price= "150"> Unordered list item 4 </li>]
DOM Traversal
Adding context to narrow things down$(':nth-child(2)');[<style> … </style>, <body> … </body>, <p id= "s1p1" class= "active section1"> Paragraph 1 </p>, <li data-price= "275"> Unordered list item 2 </li>, <section id= "s2"> … </section>, <p id= "s2p1" class= "active section2"> Paragraph 1 </p>, <li> Ordered list item 2 </li>]
$(':nth-child(2)', 'ul');[<li data-price= "275"> Unordered list item 2 </li>]
Try it!Try it!
DOM Traversal
Reading the inner HTML of an element$('ol').html();" <li>Ordered list item 1</li> <li>Ordered list item 2</li> <li>Ordered list item 3</li> <li>Ordered list item 4</li> "
DOM Traversal
Reading the inner text of an element$('ol').text();" Ordered list item 1 Ordered list item 2 Ordered list item 3 Ordered list item 4 "
DOM Manipulation
DOM Manipulation
Element Creation
$('<p></p>');[<p></p>]
Fragment. Detached from DOM.
DOM Manipulation
Element Creation$('<p>Where’s the party?</p>').appendTo('#s1');
$('#s1').append('<p>I’m new!</p>');
$('#s1').prepend('<p>So am I!</p>');
Try it!Try it!
DOM Manipulation
Element Creation$('li').wrap('<div></div>'); <li>…</li><li>…</li>…
<div> <li>…</li></div><div> <li>…</li></div>…
$('li').unwrap();
DOM Manipulation
Element Creation$('li').wrapInner('<div></div>'); <li>…</li>
<li> <div>…</div></li>
$('li').wrapAll('<div></div>'); <li>…</li><li>…</li>…
<div> <li>…</li> <li>…</li></div>
DOM Manipulation
Attribute Creation$('<p class="foo" id="bar" style="color: red;">hello</p>');
[<p class= "foo" id= "bar" style= "color: red; "> hello </p>]
DOM Manipulation
Attribute Creation$('p')
.addClass('foo')
.attr('id', 'bar')
.css('color', 'red');[<p class= "foo" id= "bar" style= "color: red; "> hello </p>]
Try it!Try it!
Data Storage
Data Storage
Read data-* attributes from the DOM
<div id="appointment1" data-date="2014-04-11">April 11, 2014</div>
$('#appointment1').data('date');
"2014-04-11"
Data Storage
Read data-* attributes from the DOM
<ul> <li data-price="100">Unordered list item 1</li> <li data-price="275">Unordered list item 2</li> <li data-price="50">Unordered list item 3</li> <li data-price="150">Unordered list item 4</li></ul>
$('ul li').data('price');
100
Data Storage
Read data-* attributes from the DOM
<ul> <li data-price="100">Unordered list item 1</li> <li data-price="275">Unordered list item 2</li> <li data-price="50">Unordered list item 3</li> <li data-price="150">Unordered list item 4</li></ul>
$('ul li').each(function (idx, el) { console.log($(el).data('price'));});
Try it!Try it!
Data Storage
Write data-* attributes to elements*
<div id="appointment2">April 11, 2014</div>
$('#appointment1').data('date', '2014-04-11');
*Cached internally. Not written to the DOM.
Data Storage
Write data-* attributes to elements*
$('ol li').data('price', 100);
*Cached internally. Not written to the DOM.
Your turn!
Data Storage
Data Storage
1) Read the price data from the unordered list items
2) Add a 10% tax to each value
3) Write the newly taxed price to each ordered list counterpart
$('ul li').each(function (idx, el) { var price = $(el).data('price') * 1.10; $('ol li').eq(idx).data('price', price);});
Events
Events
Direct event handler assignment
$('a').on('click', function (e) { e.preventDefault(); // do something});
Events
Direct event handler assignment with data
$('a').on('click', {priority: 'high'},function (e) { e.preventDefault(); console.log(e.data.priority);});
Events
Delegated event handler assignment
$(document).on('click', 'a', function (e) { e.preventDefault(); // do something});
Faster.
Future-friendly.
Events
Custom event
$('.state').on('dataReady', function (e, payload) { $(this).addClass(payload.state);});
$('.state').trigger('dataReady', { state: 'pending'});
Events
Namespaced event
$('a').on('click.loggedIn', function (e) { console.log('logged in click')});
$('a').on('mouseover.loggedIn', function (e) { console.log('logged in mouseover');});
$('a').off('.loggedIn');
Events
Stopping propagation
$('li').on('click', function (e) { console.log('li clicked!');});
$('ul').on('click', function (e) { console.log('ul clicked!');});
Events
Stopping propagation
$('li').on('click', function (e) { e.stopPropagation(); console.log('li clicked!');});
$('ul').on('click', function (e) { console.log('ul clicked!');});
Try it!Try it!
Events
Using the right ready
$(document).on('ready', function () { console.log('Will not fire if assigned late.');});
$(document).ready(function () { console.log('Will fire even if assigned late.');});
Custom Selectors
Custom Selectors
We saw:
$('p:first');
Which is actually just:
$.expr[':'].first = function (el) { …}
Custom Selectors
We can write whatever we want:
$.expr[':'].inactive = function (el) { return $(el).hasClass('inactive');};
Which we can then use:
$('p:inactive');[<p id= "s1p2" class= "inactive section1"> Paragraph 2 </p>, <p id= "s2p2" class= "inactive section2"> Paragraph 2 </p>]
Try it!Try it!
Building a Plugin
Building a Plugin
$.fn.hideRemove = function () {
return this.hide('slow', function () {
$(this).remove(); });};
Which we can then use:
$('p').hideRemove();
Try it!Try it!
Thank you!
Happy to answer your questions throughout the conference and afterwards!
twitter.com/ara_p