$30 off During Our Annual Pro Sale. View Details »

Contextual jQuery in Practice

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.

Doug Neiner

October 02, 2011
Tweet

More Decks by Doug Neiner

Other Decks in Programming

Transcript

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

    View Slide

  2. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER
    QUICK REVIEW

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  6. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER
    WRITE CODE LIKE YOU
    BUY A CAR
    Always weigh the difference
    between cost and quality

    View Slide

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

    View Slide

  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

    View Slide

  9. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER
    DELEGATED POWER
    Understanding and using delegated events

    View Slide

  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", … );

    View Slide

  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

    View Slide

  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" );
    ! });

    View Slide

  13. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER
    PROBABLE USER ACTIONS
    Pre-initializing for anticipated use

    View Slide

  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

    View Slide

  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

    View Slide

  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({ … });
    ! ! }
    ! );

    View Slide

  17. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER
    EXAMPLE: TECH CRUNCH

    View Slide

  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

    View Slide

  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" );
    ! ! ! }
    ! ! }
    ! );

    View Slide

  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 );
    ! ! ! }
    ! ! }
    ! );

    View Slide

  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

    View Slide

  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

    View Slide

  23. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER
    AUTOMATIC INITIALIZATION
    Using $.Deferred to handle initialization

    View Slide

  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();
    ! ! }
    ! };
    }());

    View Slide

  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();
    ! ! }
    ! };
    }());

    View Slide

  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();
    ! ! }
    ! };
    }());

    View Slide

  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();
    ! ! }
    ! };
    }());

    View Slide

  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();
    ! ! }
    ! };
    }());

    View Slide

  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();
    }
    );

    View Slide

  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();
    });

    View Slide

  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

    View Slide

  32. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER
    PREDICTING USER ACTIONS
    Using localStorage to track patterns

    View Slide

  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

    View Slide

  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();
    }

    View Slide

  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();
    }

    View Slide

  36. CONTEXTUAL JQUERY IN PRACTICE DOUG NEINER
    dougneiner
    [email protected]
    dcneiner
    Doug Neiner
    Doug Neiner

    View Slide