Contextual jQuery in Practice

9cde37f47e4a800ea081ea42de8d749a?s=47 Doug Neiner
October 02, 2011

Contextual jQuery in Practice

Building on the principles taught last year in my session titled "Contextual jQuery" (See http://bit.ly/contextualjquery for a video), we'll take off the kid gloves and dive into the techniques you will need to write adaptive, reusable and responsible jQuery.

9cde37f47e4a800ea081ea42de8d749a?s=128

Doug Neiner

October 02, 2011
Tweet

Transcript

  1. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER CONTEXTUAL JQUERY In Practice

  2. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER QUICK REVIEW

  3. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER JQUERY CODE STYLES •

    Declarative • Large number of selectors running on document ready • Id-centric selections • Traditional Event Binding • Dynamic • Large number of selectors running on document ready • Class-centric selections • Mix of traditional event binding with some delegated events
  4. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER JQUERY CODE STYLES •

    Contextual • Very few selectors run on document ready • Context-centric traversing and filtering • Heavy use of delegated events with some traditional binding
  5. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER WRITE CODE LIKE YOU

    SPEND MONEY Opt to pay a little more later so you don’t risk losing it all on something that never happens
  6. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER WRITE CODE LIKE YOU

    BUY A CAR Always weigh the difference between cost and quality
  7. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER CONTEXTUAL JQUERY In Practice

  8. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER OVERVIEW • Understanding the

    power of delegated events • Detecting probable user behavior • Automatic Initialization with Deferreds • Predicting user behavior with localStorage
  9. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER DELEGATED POWER Understanding and

    using delegated events
  10. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER UNDERSTANDING DELEGATION click click

    click click click click click click click click click click CONTAINER CONTAINER $( "#tile a" ) .bind( "click", … ); $( "#tile" ) .delegate( "a", "click", … ); $( "#tile" ) .on( "click", "a", … );
  11. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER UNDERSTANDING DELEGATION • Event

    bubbling allows it to work (This is patched by jQuery as necessary) • One event on a parent vs. many events on children • Filtering vs. Traversal • Responsible events – only run on user action • Can be added before the document is ready • Forces a contextual approach
  12. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER ONE TIME INITIALIZATION PATTERN

    $( document ) ! .delegate( "li:not(.widget-setup)", "click", function () { ! ! // Do something here ! ! $( this ).addClass( "widget-setup" ); ! });
  13. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER PROBABLE USER ACTIONS Pre-initializing

    for anticipated use
  14. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER CLICK • Action is

    definite • Often too late to avoid delays • Great for actions not requiring remote requests • Loading indicators will probably be needed
  15. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER MOUSEENTER / MOUSELEAVE •

    Action has a high probability • More expensive to listen for • Many false positives • Great for drag and drop initialization
  16. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER MOUSEENTER / MOUSELEAVE //

    Old Way $( document ).ready( function() { // 1000 item iteration, woah! $( "div.item" ).draggable(); }); // With Delegate $( document ) ! .delegate( "div.item:not( .ui-draggable )", "mouseenter", ! ! function ( e ) { // Only ended up running on 15 items $( this ).draggable({ … }); ! ! } ! );
  17. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER EXAMPLE: TECH CRUNCH

  18. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER MOUSE ENTER/LEAVE & DOTIMEOUT

    • jQuery.doTimeout is a plugin by Ben Alman: http://bit.ly/dotimeout • Action has a very high probability • May require a click safety net for fast movers • Fewer false positives
  19. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER MOUSE ENTER/LEAVE & DOTIMEOUT

    function initializeSocialWidgets() { ! // Run setup here } $( document ) ! .delegate( "article", "mouseenter mouseleave", ! ! function ( e ) { ! ! ! var $el = $( this ); ! ! ! ! ! if ( e.type === "mouseenter" ) { ! ! ! ! $el.doTimeout( "social", 500, ! ! ! ! ! $.proxy( initializeSocialWidgets, $el ) ! ! ! ! ); ! ! ! } else { ! ! ! ! $el.doTimeout( "social" ); ! ! ! } ! ! } ! );
  20. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER MOUSE ENTER/LEAVE & DOTIMEOUT

    $( document ) ! .delegate( "article", "mouseenter mouseleave click", ! ! function ( e ) { ! ! ! var $el = $( this ); ! ! ! ! ! if ( e.type === "mouseenter" ) { ! ! ! ! $el.doTimeout( "social", 500, ! ! ! ! ! $.proxy( initializeSocialWidgets, $el ) ! ! ! ! ); ! ! ! } else if ( e.type === "mouseenter" ) { ! ! ! ! $el.doTimeout( "social" ); ! ! ! } else { ! ! ! ! $el.doTimeout( "social", false ); ! ! ! } ! ! } ! );
  21. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER SCROLLING • Action has

    a medium probability, but easy to detect when an action cannot happen • Could be expensive, try to use cached data • jQuery Waypoints: http://bit.ly/jquerywaypoints • jQuery Sonar: http://bit.ly/jquerysonar • Ideas • Initialize tabs widget in footer • Run markup changes on articles before they come into view
  22. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER FOCUS • Action has

    high probability • Great time to initialize something like autocomplete, a date picker, or validation on a form • Remember: focusin and focusout • Ideas: • Load the rest of a multi-step wizard • Load assets for the web app after focus on a signup form
  23. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER AUTOMATIC INITIALIZATION Using $.Deferred

    to handle initialization
  24. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER SETUP CODE var contactPopover

    = ( function () { ! var contact_form; // Private variable ! ! return function () { ! ! if ( contact_form ) { ! ! ! return contact_form; ! ! } else { ! ! ! var dfd = $.Deferred(); ! ! ! $.get( '/contact', function ( data ) { ! ! ! ! contact_form = $( data ).hide().appendTo( document.body ); ! ! ! ! dfd.resolve( contact_form ); ! ! ! }); ! ! ! return dfd.promise(); ! ! } ! }; }());
  25. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER SETUP CODE var contactPopover

    = ( function () { ! var contact_form; // Private variable ! ! return function () { ! ! if ( contact_form ) { ! ! ! return contact_form; ! ! } else { ! ! ! var dfd = $.Deferred(); ! ! ! $.get( '/contact', function ( data ) { ! ! ! ! contact_form = $( data ).hide().appendTo( document.body ); ! ! ! ! dfd.resolve( contact_form ); ! ! ! }); ! ! ! return dfd.promise(); ! ! } ! }; }());
  26. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER SETUP CODE var contactPopover

    = ( function () { ! var contact_form; // Private variable ! ! return function () { ! ! if ( contact_form ) { ! ! ! return contact_form; ! ! } else { ! ! ! var dfd = contact_form = $.Deferred(); ! ! ! $.get( '/contact', function ( data ) { ! ! ! ! contact_form = $( data ).hide().appendTo( document.body ); ! ! ! ! dfd.resolve( contact_form ); ! ! ! }); ! ! ! return dfd.promise(); ! ! } ! }; }());
  27. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER SETUP CODE var contactPopover

    = ( function () { ! var contact_form; // Private variable ! ! return function () { ! ! if ( contact_form ) { ! ! ! return contact_form; ! ! } else { ! ! ! var dfd = $.Deferred(); ! ! ! $.get( '/contact', function ( data ) { ! ! ! ! contact_form = $( data ).hide().appendTo( document.body ); ! ! ! ! dfd.resolve( contact_form ); ! ! ! }); ! ! ! return dfd.promise(); ! ! } ! }; }());
  28. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER SETUP CODE var contactPopover

    = ( function () { ! var contact_form; // Private variable ! ! return function () { ! ! if ( contact_form ) { ! ! ! return contact_form; ! ! } else { ! ! ! var dfd = $.Deferred(); ! ! ! $.get( '/contact', function ( data ) { ! ! ! ! contact_form = $( data ).hide().appendTo( document.body ); ! ! ! ! dfd.resolve( contact_form ); ! ! ! }); ! ! ! return dfd.promise(); ! ! } ! }; }());
  29. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER USE CODE // Immediate

    Use $.when( contactPopover() ).then( function ( $popover ) { $popover.show(); }); // Anticipated Use $( document ).delegate( ".contact:not(.init)", "mouseenter", function() { ! $( this ).addClass( "init" ); ! contactPopover(); } );
  30. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER ADVANCED USE // Show

    loader after 0.5 seconds $.doTimeout( "contact", 500, showLoader ); $.when( contactPopover() ).then( function ( $popover ) { // Cancel showing loader or hide if showing $.doTimeout( "contact" ); hideLoader(); $popover.show(); });
  31. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER BENEFITS • You can

    write your action code without a concern for the initialization status • All setup happens in one easy place • Can be triggered at any time to begin initialization
  32. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER PREDICTING USER ACTIONS Using

    localStorage to track patterns
  33. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER TRACKING USER ACTIONS •

    Store a small number of metrics as a user browses your site or application • Keep the information general – don't go overboard • Read this information on page load and respond accordingly • Amplify.store http://amplifyjs.com
  34. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER LOGIN / APP PRELOADING

    // On the final step of signup, // or inside your web application amplify.store( "member", true ); // On the home page if ( amplify.store( "member" ) ) { // Load login popover loadLoginPopover(); // Preload web application assets loadAppAssets(); }
  35. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER LESS USED ACTIONS //

    On the advanced Edit page or method var timesLoaded = amplify.store( "advancedEdit" ) || 0; timesLoaded += 1; amplify.store( "advancedEdit", timesLoaded ); // On the base page or init method of the app if ( amplify.store( "advancedEdit" ) > 3 ) { ! // Preload advancedEdit ! preoloadAdvanvedEdit(); }
  36. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER dougneiner doug@dougneiner.com dcneiner Doug

    Neiner Doug Neiner