Advan
 ced
Sergi
  o
Pereir
Sergio
•http://
sergiopereira.com/
blog        look

•@sergiopereira
•Chicago ALT.NET
•Chicago Code
The Plan
•not just Tips &
Tricks but, yeah,
some of those
•overlooked jQuery
features
•coding the jQuery
The Plan
Is Subject To
   Change
Quick
Wins
end()
breadcrumbs for
your navigation
end() Command

<div class=menu>
 <ul>
    <li class=current>New</li>
    <li>Open...</li>
    <li>Print...</li>
 </ul>
</div>
<div class=menu>
 ...
</div>
end() Command
$('.menu').find('li')



      <div class=menu>
       <ul>
          <li class=current>New</li>
          <li>Open...</li>
          <li>Print...</li>
       </ul>
      </div>
      <div class=menu>
       ...
      </div>
end() Command
$('.menu').find('li')
       .filter('.current')

      <div class=menu>
       <ul>
          <li class=current>New</li>
          <li>Open...</li>
          <li>Print...</li>
       </ul>
      </div>
      <div class=menu>
       ...
      </div>
end() Command
$('.menu').find('li')
       .filter('.current')
       .end()
      <div class=menu>
       <ul>
          <li class=current>New</li>
          <li>Open...</li>
          <li>Print...</li>
       </ul>
      </div>
      <div class=menu>
       ...
      </div>
end() Command
$('.menu').find('li')
       .filter('.current')
       .end().end()
      <div class=menu>
       <ul>
          <li class=current>New</li>
          <li>Open...</li>
          <li>Print...</li>
       </ul>
      </div>
      <div class=menu>
       ...
      </div>
Computed
for when a simple
 expression isn’t
     enough
Computed Values

$('#buttons li')
 .css('margin-left', function(ix, val) {

        return ix*10;
  });
Computed Values
• attr(name,
 function(i,v){ })
• prop(name,
 function(i,v){ })
• val(function(i,v){ })
• css(name,
 function(i,v){ })
Relative CSS
  incremental
Relative CSS

$('#volumeUp').click(function(){
    var $volBar = $('#volBar');
    var width = $volBar.css('width');
    //easy mistake
    $volBar.css('width', width + 10);
});
Relative CSS

$('#volumeUp').click(function(){
    $('#vol').css('margin-left', '+=10');
});
data()
goodbye memory
     leaks
data() Storage
var myForm = $('#myform')[0];
var formResult = {
   errors: validateForm(myForm),
   form: myForm
};
myForm.result = formResult;

//later...
var result = $('#myform')[0].result;
if(result.errors.length){
   alert('Fix the errors.');
}
data() Storage
var formResult = {
   errors: validateForm(myForm),
   form: $('#myform')
};
$('#myform').data('result', formResult);

//later...
var result = $('#myform').data('result');
if(result.errors.length){
   alert('Fix the errors.');
}
data() Storage
  <ul>
   <li data-movie-id="131">Crash</li>
   <li data-movie-id="722">Up</li>
  </ul>


var id = $('li:first').data('movieId');
// ==> id == 131
data() Storage
data attributes
•will try to use
correct data type
•parses JSON
values
map() Utility
projections for your
       arrays
map() Utility
  array-like: has
 most of what's
needed to be used
    as an array
    var arrayLike = {
       length: 2,
       0: 'first',
       1: 'second'
    };
map() Utility
   bonus utility:
   makeArray()
var arr = $.makeArray(arrayLike);
// ==> ['first','second']
map() Utility

var users = getUsersArray();

var emails =
  $.map(users, function(user, i){
      return user.profile.email;
  });
map() Utility

var users = getUsersArray();

var emails =
  $.map(users, function(user, i){
      return user.profile.email;
  });
map() Utility
    the callback
      function
•return new value
for the position
•return null to
exclude that position
re
Quick



                  ca
•




                    p
 end(): avoid
unnecessary
traversals
•computed
attributes
•relative CSS
attributes
Event
Handling
jQuery
determine which
 element and...
bind(), live(),
 delegate(),
well, yes - choices
bind() vs. live()
$('#container .action')
   .bind('click', function(){
       //do stuff here
   });
//same as: $('#container .action')
//      .click(function(){...});

//prefer:
$('#container .action')
   .live('click', function(){
       //do stuff here
   });
bind() vs. live()

•live(): more
efficient usage
•live(): works for
added elements
•live(): forces you
to deal with the
live() vs. delegate()

$('#container .action')
   .live('click', doStuff);

$('#container')
   .delegate('.action','click', doStuff);
live() vs. delegate()

 • live(): syntax is
  slightly easier
 • live(): attaches to
  document
 • delegate():
  attaches closer
Everything vs. on()
$('#close').bind('click', closeWindow);
$('#close').on('click', closeWindow);


$('.popup').delegate(
        '.closeBtn','click', closePopup);

$('.popup').on(
        'click','.closeBtn', closePopup);
Everything vs. on()
$('#close').bind('click', closeWindow);
$('#close').on('click', closeWindow);


$('.popup').delegate(
        '.closeBtn','click', closePopup);

$('.popup').on(
        'click','.closeBtn', closePopup);

                                            1.7
Custom
they remove tight
    coupling
Custom Events
$('#widget').on('start', function(){
    //do stuff
});

//elsewhere, maybe in another js file:
$('#widget').on('start', function(){
    //do other stuff
});

//when appropriate:
$('#widget').trigger('start');
Custom Events
$('#btn1').on('lock', function(){
    $(this).prop('disabled', true);
});

//elsewhere, maybe in another js file:
$('#toolbar').on('lock', function(){
    $(this).find('.icon').remove();
});

//when appropriate:
$.event.trigger('lock');
proxy()
let's put this in
     context
proxy() Utility

var f = $.proxy(obj, 'doSomething');

var f = $.proxy(obj.doSomething, obj);
re
Event



                 ca
•




                   p
 pick the right
binding command
•delegate() over
live()
•on() unifies it all
•decouple with
Extensio
   ns
Custom
the abc of jQuery
     mastery
Custom Commands
 function stripeTable(table, alt) {
   $(table)
       .find('tr:odd')
       .addClass(alt||'alternate');
 }
 //...
 var table = $('#mytable')[0];
 stripeTable(table, 'altRow');
Custom Commands
 jQuery.fn.stripe = function(alt) {
    this
       .children(':odd')
       .addClass(alt||'alternate');
     return this;
 };
 //...
 $('#mytable').stripe('altRow');
Custom Commands
 jQuery.fn.stripe = function(alt) {
    this
       .children(':odd')
       .addClass(alt||'alternate');
     return this;
 };
 //...
 $('#mytable').stripe('altRow');
Custom
expressive means
    readable
Custom

$.expr[':'].myfilter = function(el) {
   //return true if el(ement) matches
}
//...
$('div:myfilter').slideDown();
re
Extensions



                 ca
                   p
•commands
•expressions
•events
1.5




Deferred
 Object
Futures,
decouple the task
   from what
 you do with its
    outcome
Tidy Callbacks
startLongProcess(
   function(result){
      useResult(result);
      logCompletion(result);
   },
   function(error){
      logCompletion(result);
      logFailure(error);
   }
);
Tidy Callbacks
startLongProcess(
   function(result){
      useResult(result, function(res2){
          updateScreen(res2);
      });
      logCompletion(result);
   },
   //...
);
Tidy Callbacks
var task = startLongProcess()
  .done(useResult)
  .always(logCompletion)
  .fail(logFailure);

doSomethingElse();

//time passes...
task.fail(function(){
    alert('error');
});
Tidy Callbacks
var task = startLongProcess()
  .always(logCompletion)
  .fail(logFailure);

$.when(task, otherTask)
 .then(function(args1, args2){
      useResult(args1[0])
       .done(updateScreen);
  });
Deferreds in
 time to relearn
 some features
Ajax

var fetch = $.get('/data.aspx')
    .done(validateResponse)
    .done(doSomething)
    .done(doMoreStuff)
    .fail(reportError);

fetch.fail(resetUI);
when() Utility
$.when(
   $.get('/somedata'),
   $.get('/moredata'),
   $.post('/updatedata', data),
   someOtherDeferred)

 .then(function(){
       alert('all done');
   });
promise()
$('.widget')
   .first().fadeOut(500).end()
   .last().fadeOut(1000).end()
   .promise() //default: 'fx' queue
   .done(function(){
     //do something...
   });
re
Deferred



               ca
                 p
•common way for
callbacks
•returned by jQuery
Ajax
•for command
queues too
The True
 Source
github
     https://
github.com/jquery
github
     https://
github.com/jquery
Build It, Run
check out QUnit
Question
   s?
Reference

•http://
api.jquery.com
•Paul Irish's articles
and videos
Thank
 You

Advanced jQuery

Editor's Notes

  • #2 \n
  • #3 \n
  • #4 \n
  • #5 for this talk I&apos;ll assume you all know the basics of jQuery and have been using it for DOM manipulation and Ajax calls. I&apos;ll show some of the other things in jq that could be labeled as intermediate to advanced. I&apos;ll try to highlight anything that is new in 1.7.\n
  • #6 for this talk I&apos;ll assume you all know the basics of jQuery and have been using it for DOM manipulation and Ajax calls. I&apos;ll show some of the other things in jq that could be labeled as intermediate to advanced. I&apos;ll try to highlight anything that is new in 1.7.\n
  • #7 I normally don&apos;t like presentations that are all about tricks and trips because it&apos;s hard to keep track of everything. I&apos;ll try to keep the machine gun quiet but I still wanted to highlight a handful of helpful gems in jq.\n
  • #8 \n
  • #9 \n
  • #10 \n
  • #11 \n
  • #12 \n
  • #13 DEMO!\n
  • #14 \n
  • #15 DEMO!\n
  • #16 \n
  • #17 \n
  • #18 \n
  • #19 DEMO!\n
  • #20 \n
  • #21 \n
  • #22 \n
  • #23 \n
  • #24 \n
  • #25 \n
  • #26 \n
  • #27 \n
  • #28 this should be familiar to most of you. The Select() Linq extension does that for IEnumerables in .net. We do the conversion with callback.\n
  • #29 this should be familiar to most of you. The Select() Linq extension does that for IEnumerables in .net. We do the conversion with callback.\n
  • #30 But there are a few things to note in the callback function.\n
  • #31 \n
  • #32 Event handling is one of the main reasons we use jquery for...\n
  • #33 It makes it so easy to watch for an event of an element... just choose the element and...\n
  • #34 Oh, that&apos;s that too. It&apos;s easy but it takes a little practice to pick the most efficient route. I&apos;m sure a few of us still has to think about it or look up docs to choose the right one for the task.\n
  • #35 both bind and live allow us to setup handlers for one or many elements in a single command. Select all the elements you want and attach the handler. main diff: dynamically added elements\n
  • #36 unique elements: elements that don&apos;t have a similar purpose with any other element on the page.\n
  • #37 OK, it was easy to figure out between the previous 2. But those two appear to do the same. Attach a handler for a selector.\nDiff: delegate() attaches a handler to the parent, not Doc. Syntax.\n
  • #38 \n
  • #39 on() can also take a data parameter that goes to event.data\n
  • #40 \n
  • #41 \n
  • #42 global events\n
  • #43 \n
  • #44 DEMO!\n
  • #45 \n
  • #46 \n
  • #47 \n
  • #48 \n
  • #49 \n
  • #50 \n
  • #51 \n
  • #52 \n
  • #53 \n
  • #54 \n
  • #55 DEMO!\n
  • #56 \n
  • #57 \n
  • #58 \n
  • #59 this is possible way to invoke a callback-based async function... note the two different callbacks, for success and error. note the duplication too.\n
  • #60 it could get worse. look what would happen if useResult was also async... what if an error happens in useResult? another error callback?\n
  • #61 see how much cleaner the code becomes when we introduce the deferred task object.\nWe can even subscribe later and it will fire immediately if the task has completed already. DEMO1!\n
  • #62 the tasks allow us to compose more complicated scenarios without sacrificing too much the read-ability of the code.\n
  • #63 \n
  • #64 \n
  • #65 DEMO2!\n
  • #66 Internally jQuery can maintain queues of actions. One such queue is the one that allows effects to execute sequentially.\nThe promise command returns a deferred task that resolves when the queue empties.\n
  • #67 \n
  • #68 \n
  • #69 \n
  • #70 show github, show how files are split, show local repo, build\n
  • #71 \n
  • #72 \n
  • #73 \n
  • #74 \n