SlideShare a Scribd company logo
Developing jQuery Plugins
                         creating an edit-on-demand plugin


                     Jakob Westhoff <jakob@php.net>



                                  FrOSCon 2009
                                 August 22, 2009




http://westhoffswelt.de          jakob@westhoffswelt.de        slide: 1 / 36
About Me



        Jakob Westhoff

              Computer science student at the TU Dortmund
              Web-developer for more than 6 years

              Author of Activebar2 (used by http://ie6update.com)
              Active in different Open Source projects




http://westhoffswelt.de        jakob@westhoffswelt.de          slide: 2 / 36
jQuery about itself



   From the jQuery Website:
   jQuery is a fast and concise JavaScript Library that simplifies
   HTML document traversing, event handling, animating, and Ajax
   interactions for rapid web development. jQuery is designed to
   change the way that you write JavaScript.




 http://westhoffswelt.de   jakob@westhoffswelt.de        slide: 3 / 36
jQuery about itself



   From the jQuery Website:
   jQuery is a fast and concise JavaScript Library that simplifies
   HTML document traversing, event handling, animating, and Ajax
   interactions for rapid web development. jQuery is designed to
   change the way that you write JavaScript.




 http://westhoffswelt.de   jakob@westhoffswelt.de        slide: 3 / 36
jQuery about itself



   From the jQuery Website:
   jQuery is a fast and concise JavaScript Library that simplifies
   HTML document traversing, event handling, animating, and Ajax
   interactions for rapid web development. jQuery is designed to
   change the way that you write JavaScript.




 http://westhoffswelt.de   jakob@westhoffswelt.de        slide: 3 / 36
jQuery about itself



   From the jQuery Website:
   jQuery is a fast and concise JavaScript Library that simplifies
   HTML document traversing, event handling, animating, and Ajax
   interactions for rapid web development. jQuery is designed to
   change the way that you write JavaScript.




 http://westhoffswelt.de   jakob@westhoffswelt.de        slide: 3 / 36
jQuery about itself



   From the jQuery Website:
   jQuery is a fast and concise JavaScript Library that simplifies
   HTML document traversing, event handling, animating, and Ajax
   interactions for rapid web development. jQuery is designed to
   change the way that you write JavaScript.




 http://westhoffswelt.de   jakob@westhoffswelt.de        slide: 3 / 36
Introduction to jQuery


         Compact
               only 56kb minified
               19kb minified and gzipped
         Cross-browser compatible
               Internet Explorer 6.0+
               Firefox 2+
               Safari 3.0+
               Opera 9.0+
               Chrome
         Easily extendable




 http://westhoffswelt.de        jakob@westhoffswelt.de   slide: 4 / 36
Introduction to jQuery


         Compact
               only 56kb minified
               19kb minified and gzipped
         Cross-browser compatible
               Internet Explorer 6.0+
               Firefox 2+
               Safari 3.0+
               Opera 9.0+
               Chrome
         Easily extendable




 http://westhoffswelt.de        jakob@westhoffswelt.de   slide: 4 / 36
Introduction to jQuery


         Compact
               only 56kb minified
               19kb minified and gzipped
         Cross-browser compatible
               Internet Explorer 6.0+
               Firefox 2+
               Safari 3.0+
               Opera 9.0+
               Chrome
         Easily extendable




 http://westhoffswelt.de        jakob@westhoffswelt.de   slide: 4 / 36
jQuery Example



      $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ;



         Find all paragraphs with the id example
         Add the css class highlight to them
         Fade in the paragraph slowly




 http://westhoffswelt.de                  jakob@westhoffswelt.de                            slide: 5 / 36
jQuery Example



      $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ;



         Find all paragraphs with the id example
         Add the css class highlight to them
         Fade in the paragraph slowly




 http://westhoffswelt.de                  jakob@westhoffswelt.de                            slide: 5 / 36
jQuery Example



      $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ;



         Find all paragraphs with the id example
         Add the css class highlight to them
         Fade in the paragraph slowly




 http://westhoffswelt.de                  jakob@westhoffswelt.de                            slide: 5 / 36
jQuery Example



      $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ;



         Find all paragraphs with the id example
         Add the css class highlight to them
         Fade in the paragraph slowly




 http://westhoffswelt.de                  jakob@westhoffswelt.de                            slide: 5 / 36
Working with jQuery


      $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ;



         Accessed using $ or jQuery
         Document centric
                 $(css selector).operation
         Fluent interface paradigm
                 operation().operation().operation()




 http://westhoffswelt.de                  jakob@westhoffswelt.de                            slide: 6 / 36
Working with jQuery


      $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ;



         Accessed using $ or jQuery
         Document centric
                 $(css selector).operation
         Fluent interface paradigm
                 operation().operation().operation()




 http://westhoffswelt.de                  jakob@westhoffswelt.de                            slide: 6 / 36
Working with jQuery


      $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ;



         Accessed using $ or jQuery
         Document centric
                 $(css selector).operation
         Fluent interface paradigm
                 operation().operation().operation()




 http://westhoffswelt.de                  jakob@westhoffswelt.de                            slide: 6 / 36
Beginning Plugin Development




         Before you start
               Check http://plugins.jquery.com/
         Read Plugins/Authoring documentation
               http://docs.jquery.com/Plugins/Authoring




 http://westhoffswelt.de     jakob@westhoffswelt.de     slide: 7 / 36
Beginning Plugin Development




         Before you start
               Check http://plugins.jquery.com/
         Read Plugins/Authoring documentation
               http://docs.jquery.com/Plugins/Authoring




 http://westhoffswelt.de     jakob@westhoffswelt.de     slide: 7 / 36
Introducing the Example
         On-Demand-Editing Plugin
         Used by Flickr and others




 http://westhoffswelt.de     jakob@westhoffswelt.de   slide: 8 / 36
Plugin Requirements



         Applyable to every block level element
         Capture on mouseover / mouseout events for color change on
         hovering
         Transform content to edit box and save/cancel buttons onclick
         Execute user-definable callback function once new data is
         provided




 http://westhoffswelt.de     jakob@westhoffswelt.de         slide: 9 / 36
Plugin Requirements



         Applyable to every block level element
         Capture on mouseover / mouseout events for color change on
         hovering
         Transform content to edit box and save/cancel buttons onclick
         Execute user-definable callback function once new data is
         provided




 http://westhoffswelt.de     jakob@westhoffswelt.de         slide: 9 / 36
Plugin Requirements



         Applyable to every block level element
         Capture on mouseover / mouseout events for color change on
         hovering
         Transform content to edit box and save/cancel buttons onclick
         Execute user-definable callback function once new data is
         provided




 http://westhoffswelt.de     jakob@westhoffswelt.de         slide: 9 / 36
Plugin Requirements



         Applyable to every block level element
         Capture on mouseover / mouseout events for color change on
         hovering
         Transform content to edit box and save/cancel buttons onclick
         Execute user-definable callback function once new data is
         provided




 http://westhoffswelt.de     jakob@westhoffswelt.de         slide: 9 / 36
Let’s begin



         Choose a name for our plugin: editable

         Create jquery.editable.css
               Hover effect
               Textbox look and feel
               Button positioning / look and feel




 http://westhoffswelt.de        jakob@westhoffswelt.de   slide: 10 / 36
Stylesheet for our Plugin



         Choose a name for our plugin: editable

         Create jquery.editable.css
               Hover effect
               Textbox look and feel
               Button positioning / look and feel




 http://westhoffswelt.de        jakob@westhoffswelt.de   slide: 10 / 36
Stylesheet for our Plugin
  1   . editable hover ,
  2   . editable active
  3   {
  4      b a c k g r o u n d −c o l o r : #e f e e e e ;
  5   }
  6
  7   . e d i t a b l e c o n t a i n e r span
  8   {
  9       f o n t −s i z e : 12 px ;
 10       c o l o r : #000000;
 11      m a r g i n : 0 8 px 0 8 px ;
 12   }
 13
 14   . e d i t a b l e c o n t a i n e r input ,
 15   . editable container textarea
 16   {
 17       display : block ;
 18   }


 http://westhoffswelt.de               jakob@westhoffswelt.de   slide: 11 / 36
The problem with the $ shortcut


          $ should not be used in plugins
               jQuery allows redefining of this alias for compatability reasons
               May break your plugin
          Always use jQuery

          Or use nifty workaround:

      1    ( function ($) {
      2       ...
      3       // Your p l u g i n c o d e g o e s h e r e
      4       ...
      5    }) ( jQuery ) ;




 http://westhoffswelt.de           jakob@westhoffswelt.de          slide: 12 / 36
The problem with the $ shortcut


          $ should not be used in plugins
               jQuery allows redefining of this alias for compatability reasons
               May break your plugin
          Always use jQuery

          Or use nifty workaround:

      1    ( function ($) {
      2       ...
      3       // Your p l u g i n c o d e g o e s h e r e
      4       ...
      5    }) ( jQuery ) ;




 http://westhoffswelt.de           jakob@westhoffswelt.de          slide: 12 / 36
The problem with the $ shortcut


          $ should not be used in plugins
               jQuery allows redefining of this alias for compatability reasons
               May break your plugin
          Always use jQuery

          Or use nifty workaround:

      1    ( function ($) {
      2       ...
      3       // Your p l u g i n c o d e g o e s h e r e
      4       ...
      5    }) ( jQuery ) ;




 http://westhoffswelt.de           jakob@westhoffswelt.de          slide: 12 / 36
Registering the Plugin Method



          Choose a name for our plugin method: editable

          Register the new method in the jQuery.fn namespace:

      1   jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) {
      2     ...
      3     // P l u g i n method
      4     ...
      5   }




 http://westhoffswelt.de         jakob@westhoffswelt.de                slide: 13 / 36
Registering the Plugin Method



          Choose a name for our plugin method: editable

          Register the new method in the jQuery.fn namespace:

      1   jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) {
      2     ...
      3     // P l u g i n method
      4     ...
      5   }




 http://westhoffswelt.de         jakob@westhoffswelt.de                slide: 13 / 36
Handling Optional Options


          Most plugins need configuration options
          Use a default if a certain option is not provided
          Options are supplied as associative array / object

          Utilize the jQuery.extend function:

      1    var o p t i o n = jQuery . extend ({
      2       ” multiline ” : false ,
      3       ” prefix ”: ”editable ”
      4    } , option ) ;




 http://westhoffswelt.de        jakob@westhoffswelt.de           slide: 14 / 36
Handling Optional Options


          Most plugins need configuration options
          Use a default if a certain option is not provided
          Options are supplied as associative array / object

          Utilize the jQuery.extend function:

      1    var o p t i o n = jQuery . extend ({
      2       ” multiline ” : false ,
      3       ” prefix ”: ”editable ”
      4    } , option ) ;




 http://westhoffswelt.de        jakob@westhoffswelt.de           slide: 14 / 36
Handling Optional Options


          Most plugins need configuration options
          Use a default if a certain option is not provided
          Options are supplied as associative array / object

          Utilize the jQuery.extend function:

      1    var o p t i o n = jQuery . extend ({
      2       ” multiline ” : false ,
      3       ” prefix ”: ”editable ”
      4    } , option ) ;




 http://westhoffswelt.de        jakob@westhoffswelt.de           slide: 14 / 36
Handling Optional Options


          Most plugins need configuration options
          Use a default if a certain option is not provided
          Options are supplied as associative array / object

          Utilize the jQuery.extend function:

      1    var o p t i o n = jQuery . extend ({
      2       ” multiline ” : false ,
      3       ” prefix ”: ”editable ”
      4    } , option ) ;




 http://westhoffswelt.de        jakob@westhoffswelt.de           slide: 14 / 36
this Context inside the Plugin Method


          The this context inside a plugin method ...
               points to the called jQuery object
               may represent a set of DOM elements

          Use each to handle sets correctly:

      1    return $ ( t h i s ) . each ( f u n c t i o n ( ) {
      2       ...
      3       // ” t h i s ” maps t o t h e c u r r e n t l y h a n d l e d e l e m e n t
      4       ...
      5    }) ;




 http://westhoffswelt.de            jakob@westhoffswelt.de                   slide: 15 / 36
Using each to Handle Sets


          The this context inside a plugin method ...
               points to the called jQuery object
               may represent a set of DOM elements

          Use each to handle sets correctly:

      1    return $ ( t h i s ) . each ( f u n c t i o n ( ) {
      2       ...
      3       // ” t h i s ” maps t o t h e c u r r e n t l y h a n d l e d e l e m e n t
      4       ...
      5    }) ;




 http://westhoffswelt.de            jakob@westhoffswelt.de                   slide: 15 / 36
What we have got so far
  1   ( function ($) {
  2      jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) {
  3
  4         // O p t i o n h a n d l i n g
  5         var o p t i o n = jQuery . extend ({
  6            ” option ” : ” default value ” ,
  7            ...
  8         } , option ) ;
  9
 10         // H a n d l e s e t s c o r r e c t l y .
 11         // E n s u r e t h e f l u e n t i n t e r f a c e p a r a d i g m .
 12         return $ ( t h i s ) . each ( f u n c t i o n ( ) {
 13            ...
 14            // ” r e a l ” p l u g i n c o d e g o e s i n h e r e
 15            ...
 16         }) ;
 17
 18      }
 19   }) ( jQuery ) ;

 http://westhoffswelt.de             jakob@westhoffswelt.de                      slide: 16 / 36
Modifying the Container Element


          Add a css class to the container element:

      $( this ) . addClass ( option [ ’ p r e f i x ’ ] + ’ container ’ ) ;

          Register events for onhover effect:

      1   $ ( t h i s ) . bind ( ” mouseenter mouseleave ” ,
      2       function (e) {
      3          $( this ) . toggleClass (
      4               option [ ’ p r e f i x ’ ] + ’ hover ’
      5          );
      6       }
      7   );




 http://westhoffswelt.de        jakob@westhoffswelt.de               slide: 17 / 36
Modifying the Container Element


          Add a css class to the container element:

      $( this ) . addClass ( option [ ’ p r e f i x ’ ] + ’ container ’ ) ;

          Register events for onhover effect:

      1   $ ( t h i s ) . bind ( ” mouseenter mouseleave ” ,
      2       function (e) {
      3          $( this ) . toggleClass (
      4               option [ ’ p r e f i x ’ ] + ’ hover ’
      5          );
      6       }
      7   );




 http://westhoffswelt.de        jakob@westhoffswelt.de               slide: 17 / 36
Enter Edit Mode on Click


          On click enter edit mode
               Registered using one as once only event
               Calling plugin private function enterEditMode

      1   $ ( t h i s ) . one ( ’ c l i c k ’ ,
      2       function () {
      3          enterEditMode ( $ ( t h i s ) ) ;
      4       }
      5   );




 http://westhoffswelt.de        jakob@westhoffswelt.de           slide: 18 / 36
Private Plugin Functions

          Function in the plugin scope
          Access to all variables globally declared (option)
          Access to all plugin method parameters (savefn)

      1    jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) {
      2      var option = . . .
      3
      4       return $ ( t h i s ) . each ( f u n c t i o n ( ) {
      5          ...
      6       }) ;
      7
      8       f u n c t i o n enterEditMode ( c o n t a i n e r ) {
      9           // A c c e s s t o : c o n t a i n e r , s a v e f n , o p t i o n
     10       }
     11   }



 http://westhoffswelt.de              jakob@westhoffswelt.de                      slide: 19 / 36
Private Plugin Functions

          Function in the plugin scope
          Access to all variables globally declared (option)
          Access to all plugin method parameters (savefn)

      1    jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) {
      2      var option = . . .
      3
      4       return $ ( t h i s ) . each ( f u n c t i o n ( ) {
      5          ...
      6       }) ;
      7
      8       f u n c t i o n enterEditMode ( c o n t a i n e r ) {
      9           // A c c e s s t o : c o n t a i n e r , s a v e f n , o p t i o n
     10       }
     11   }



 http://westhoffswelt.de              jakob@westhoffswelt.de                      slide: 19 / 36
Private Plugin Functions

          Function in the plugin scope
          Access to all variables globally declared (option)
          Access to all plugin method parameters (savefn)

      1    jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) {
      2      var option = . . .
      3
      4       return $ ( t h i s ) . each ( f u n c t i o n ( ) {
      5          ...
      6       }) ;
      7
      8       f u n c t i o n enterEditMode ( c o n t a i n e r ) {
      9           // A c c e s s t o : c o n t a i n e r , s a v e f n , o p t i o n
     10       }
     11   }



 http://westhoffswelt.de              jakob@westhoffswelt.de                      slide: 19 / 36
Private Plugin Functions

          Function in the plugin scope
          Access to all variables globally declared (option)
          Access to all plugin method parameters (savefn)

      1    jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) {
      2      var option = . . .
      3
      4       return $ ( t h i s ) . each ( f u n c t i o n ( ) {
      5          ...
      6       }) ;
      7
      8       f u n c t i o n enterEditMode ( c o n t a i n e r ) {
      9           // A c c e s s t o : c o n t a i n e r , s a v e f n , o p t i o n
     10       }
     11   }



 http://westhoffswelt.de              jakob@westhoffswelt.de                      slide: 19 / 36
Needed Private Functions



         enterEditMode( container )
               Called whenever data input should be possible
         leaveEditMode( container, updatedText )
               Called whenever the edit process is complete and the normal
               state should be restored




 http://westhoffswelt.de        jakob@westhoffswelt.de           slide: 20 / 36
Needed Private Functions



         enterEditMode( container )
               Called whenever data input should be possible
         leaveEditMode( container, updatedText )
               Called whenever the edit process is complete and the normal
               state should be restored




 http://westhoffswelt.de        jakob@westhoffswelt.de           slide: 20 / 36
enterEditMode - Cleanup a little bit

         Store the original content

      v a r o r i g i n a l T e x t C o n t e n t = c o n t a i n e r . h t ml ( ) ;

         Disable onhover effects

      c o n t a i n e r . unbind ( ’ mouseenter mouseleave ’ ) ;
      container . removeClass ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ;

         Warning: This removes all mouseenter and mouseleave
         event handlers of this node

         Set correct css classes

      container . addClass ( option [ ’ p r e f i x ’ ] + ’ a c t iv e ’ ) ;



 http://westhoffswelt.de                jakob@westhoffswelt.de                           slide: 21 / 36
enterEditMode - Cleanup a little bit

         Store the original content

      v a r o r i g i n a l T e x t C o n t e n t = c o n t a i n e r . h t ml ( ) ;

         Disable onhover effects

      c o n t a i n e r . unbind ( ’ mouseenter mouseleave ’ ) ;
      container . removeClass ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ;

         Warning: This removes all mouseenter and mouseleave
         event handlers of this node

         Set correct css classes

      container . addClass ( option [ ’ p r e f i x ’ ] + ’ a c t iv e ’ ) ;



 http://westhoffswelt.de                jakob@westhoffswelt.de                           slide: 21 / 36
enterEditMode - Cleanup a little bit

         Store the original content

      v a r o r i g i n a l T e x t C o n t e n t = c o n t a i n e r . h t ml ( ) ;

         Disable onhover effects

      c o n t a i n e r . unbind ( ’ mouseenter mouseleave ’ ) ;
      container . removeClass ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ;

         Warning: This removes all mouseenter and mouseleave
         event handlers of this node

         Set correct css classes

      container . addClass ( option [ ’ p r e f i x ’ ] + ’ a c t iv e ’ ) ;



 http://westhoffswelt.de                jakob@westhoffswelt.de                           slide: 21 / 36
enterEditMode - Create input field and buttons


         Create the needed input field

      v a r e d i t = $ ( ’<i n p u t t y p e =” t e x t ”></ i n p u t > ’ ) ;

         Create the needed buttons

      v a r s a v e = $ ( ’<b u t t o n c l a s s =” s a v e ”>Save </b u t t o n > ’ ) ;

      var cancel =
        $ ( ’<b u t t o n c l a s s =” c a n c e l ”>C a n c e l </b u t t o n > ’ ) ;




 http://westhoffswelt.de              jakob@westhoffswelt.de                       slide: 22 / 36
enterEditMode - Create input field and buttons


         Create the needed input field

      v a r e d i t = $ ( ’<i n p u t t y p e =” t e x t ”></ i n p u t > ’ ) ;

         Create the needed buttons

      v a r s a v e = $ ( ’<b u t t o n c l a s s =” s a v e ”>Save </b u t t o n > ’ ) ;

      var cancel =
        $ ( ’<b u t t o n c l a s s =” c a n c e l ”>C a n c e l </b u t t o n > ’ ) ;




 http://westhoffswelt.de              jakob@westhoffswelt.de                       slide: 22 / 36
enterEditMode - Register button onClick

          Register onClick for Cancel

      1    cancel . bind ( ’ c l i c k ’ , function ( e ) {
      2       e . stopPropagation () ;
      3       leaveEditMode ( container , originalTextContent ) ;
      4    }) ;

          Register onClick for Save

      1    save . bind ( ’ c l i c k ’ , function ( e ) {
      2       e . stopPropagation () ;
      3       leaveEditMode (
      4           container ,
      5           savefn ( edit . val () )
      6       );
      7    }) ;



 http://westhoffswelt.de          jakob@westhoffswelt.de      slide: 23 / 36
enterEditMode - Register button onClick

          Register onClick for Cancel

      1    cancel . bind ( ’ c l i c k ’ , function ( e ) {
      2       e . stopPropagation () ;
      3       leaveEditMode ( container , originalTextContent ) ;
      4    }) ;

          Register onClick for Save

      1    save . bind ( ’ c l i c k ’ , function ( e ) {
      2       e . stopPropagation () ;
      3       leaveEditMode (
      4           container ,
      5           savefn ( edit . val () )
      6       );
      7    }) ;



 http://westhoffswelt.de          jakob@westhoffswelt.de      slide: 23 / 36
enterEditMode - Replace current content



          Replace the current content with input field and buttons

      1    c o n t a i n e r . empty ( )
      2        . append ( e d i t )
      3        . append ( s a v e )
      4        . append ( c a n c e l ) ;




 http://westhoffswelt.de              jakob@westhoffswelt.de   slide: 24 / 36
leaveEditMode - Reactivate onHover



         Remove state from css classes

      container . removeClass ( option [ ’ p r e f i x ’ ] + ’ a c t i v e ’ ) ;

         Bind events for onHover effect

      c o n t a i n e r . bind ( ” mouseenter mouseleave ” , f u n c t i o n ( e ) {
          container . t o g g l e C l a s s ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ;
      }) ;




 http://westhoffswelt.de           jakob@westhoffswelt.de                 slide: 25 / 36
leaveEditMode - Reactivate onHover



         Remove state from css classes

      container . removeClass ( option [ ’ p r e f i x ’ ] + ’ a c t i v e ’ ) ;

         Bind events for onHover effect

      c o n t a i n e r . bind ( ” mouseenter mouseleave ” , f u n c t i o n ( e ) {
          container . t o g g l e C l a s s ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ;
      }) ;




 http://westhoffswelt.de           jakob@westhoffswelt.de                 slide: 25 / 36
leaveEditMode - Reactivate onClick



          Re-register the onClick handler

      1   $ ( t h i s ) . one ( ’ c l i c k ’ ,
      2       function () {
      3          enterEditMode ( $ ( t h i s ) ) ;
      4       }
      5   );




 http://westhoffswelt.de        jakob@westhoffswelt.de   slide: 26 / 36
leaveEditMode - Update text content




         Update the container with the given text content

      c o n t a i n e r . html ( updatedText ) ;




 http://westhoffswelt.de          jakob@westhoffswelt.de      slide: 27 / 36
Calling the plugin



         Simply call the editable method on the selected node.


      $ ( ” h1 ” ) . e d i t a b l e ( f u n c t i o n ( c o n t e n t ) {
          // Do some AJAX magic h e r e . . .
          return content ;
      }) ;




 http://westhoffswelt.de                  jakob@westhoffswelt.de               slide: 28 / 36
editable Live Demo




  Let’s take a look

                         Live Demo!




http://westhoffswelt.de   jakob@westhoffswelt.de   slide: 29 / 36
6 Golden Rules of Plugin Development


      1   Name your file jquery.[insert name of plugin].js
               eg. jquery.myplugin.js
      2   Attach new methods to the jQuery.fn object
      3   Attach new functions to the jQuery object itself
      4   Methods have always to return the object they are working on
      5   Use each to ensure your method is applied to all elements in
          a set
      6   Always use jQuery instead of the $ shortcut in your plugins
               or use the nifty trick shown




 http://westhoffswelt.de        jakob@westhoffswelt.de         slide: 30 / 36
6 Golden Rules of Plugin Development


      1   Name your file jquery.[insert name of plugin].js
               eg. jquery.myplugin.js
      2   Attach new methods to the jQuery.fn object
      3   Attach new functions to the jQuery object itself
      4   Methods have always to return the object they are working on
      5   Use each to ensure your method is applied to all elements in
          a set
      6   Always use jQuery instead of the $ shortcut in your plugins
               or use the nifty trick shown




 http://westhoffswelt.de        jakob@westhoffswelt.de         slide: 30 / 36
6 Golden Rules of Plugin Development


      1   Name your file jquery.[insert name of plugin].js
               eg. jquery.myplugin.js
      2   Attach new methods to the jQuery.fn object
      3   Attach new functions to the jQuery object itself
      4   Methods have always to return the object they are working on
      5   Use each to ensure your method is applied to all elements in
          a set
      6   Always use jQuery instead of the $ shortcut in your plugins
               or use the nifty trick shown




 http://westhoffswelt.de        jakob@westhoffswelt.de         slide: 30 / 36
6 Golden Rules of Plugin Development


      1   Name your file jquery.[insert name of plugin].js
               eg. jquery.myplugin.js
      2   Attach new methods to the jQuery.fn object
      3   Attach new functions to the jQuery object itself
      4   Methods have always to return the object they are working on
      5   Use each to ensure your method is applied to all elements in
          a set
      6   Always use jQuery instead of the $ shortcut in your plugins
               or use the nifty trick shown




 http://westhoffswelt.de        jakob@westhoffswelt.de         slide: 30 / 36
6 Golden Rules of Plugin Development


      1   Name your file jquery.[insert name of plugin].js
               eg. jquery.myplugin.js
      2   Attach new methods to the jQuery.fn object
      3   Attach new functions to the jQuery object itself
      4   Methods have always to return the object they are working on
      5   Use each to ensure your method is applied to all elements in
          a set
      6   Always use jQuery instead of the $ shortcut in your plugins
               or use the nifty trick shown




 http://westhoffswelt.de        jakob@westhoffswelt.de         slide: 30 / 36
6 Golden Rules of Plugin Development


      1   Name your file jquery.[insert name of plugin].js
               eg. jquery.myplugin.js
      2   Attach new methods to the jQuery.fn object
      3   Attach new functions to the jQuery object itself
      4   Methods have always to return the object they are working on
      5   Use each to ensure your method is applied to all elements in
          a set
      6   Always use jQuery instead of the $ shortcut in your plugins
               or use the nifty trick shown




 http://westhoffswelt.de        jakob@westhoffswelt.de         slide: 30 / 36
Thanks for listening



          Questions, comments or annotations?


         Slides: http://westhoffswelt.de/portfolio.htm
                Contact: Jakob Westhoff <jakob@php.net>




 http://westhoffswelt.de    jakob@westhoffswelt.de    slide: 31 / 36
Unit testing with QUnit



         Unit testing? YES you want to!
         QUnit
               jQuerys unit testing framework
               http://docs.jquery.com/QUnit
               No stable release, yet
               However core features are extremly stable




 http://westhoffswelt.de        jakob@westhoffswelt.de       slide: 32 / 36
Unit testing with QUnit



         Unit testing? YES you want to!
         QUnit
               jQuerys unit testing framework
               http://docs.jquery.com/QUnit
               No stable release, yet
               However core features are extremly stable




 http://westhoffswelt.de        jakob@westhoffswelt.de       slide: 32 / 36
Unit testing with QUnit



         Unit testing? YES you want to!
         QUnit
               jQuerys unit testing framework
               http://docs.jquery.com/QUnit
               No stable release, yet
               However core features are extremly stable




 http://westhoffswelt.de        jakob@westhoffswelt.de       slide: 32 / 36
Unit testing with QUnit



         Unit testing? YES you want to!
         QUnit
               jQuerys unit testing framework
               http://docs.jquery.com/QUnit
               No stable release, yet
               However core features are extremly stable




 http://westhoffswelt.de        jakob@westhoffswelt.de       slide: 32 / 36
Unit testing with QUnit



         Unit testing? YES you want to!
         QUnit
               jQuerys unit testing framework
               http://docs.jquery.com/QUnit
               No stable release, yet
               However core features are extremly stable




 http://westhoffswelt.de        jakob@westhoffswelt.de       slide: 32 / 36
Simple QUnit example
         Include js and css

      < s c r i p t s r c=” j q u e r y − l a t e s t . j s ”></ s c r i p t>
      < s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” q u n i t / t e s t r u n n e r .
              j s ”></ s c r i p t>
      < l i n k r e l=” s t y l e s h e e t ” h r e f=” q u n i t / t e s t s u i t e . c s s ”
              type=” t e x t / c s s ” media=” s c r e e n ” />

         Create a simple html page to be filled with information

      <h1>QUnit e x a m p l e</h1>

      <h2 i d=” b a n n e r ”></h2>
      <h2 i d=” u s e r A g e n t ”></h2>

      <o l i d=” t e s t s ”></ o l>

      <d i v i d=” main ”></ d i v>


 http://westhoffswelt.de               jakob@westhoffswelt.de                        slide: 33 / 36
Simple QUnit example
         Include js and css

      < s c r i p t s r c=” j q u e r y − l a t e s t . j s ”></ s c r i p t>
      < s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” q u n i t / t e s t r u n n e r .
              j s ”></ s c r i p t>
      < l i n k r e l=” s t y l e s h e e t ” h r e f=” q u n i t / t e s t s u i t e . c s s ”
              type=” t e x t / c s s ” media=” s c r e e n ” />

         Create a simple html page to be filled with information

      <h1>QUnit e x a m p l e</h1>

      <h2 i d=” b a n n e r ”></h2>
      <h2 i d=” u s e r A g e n t ”></h2>

      <o l i d=” t e s t s ”></ o l>

      <d i v i d=” main ”></ d i v>


 http://westhoffswelt.de               jakob@westhoffswelt.de                        slide: 33 / 36
Simple QUnit example



         Define a module (optional)

      module ( ”My s i m p l e e x a m p l e module ” ) ;

         Add a test

      t e s t ( ”My f i r s t t e s t ” , f u n c t i o n ( ) {
          ok ( t r u e , ” E v e r y t h i n g i s f i n e . ” ) ;
      }) ;




 http://westhoffswelt.de               jakob@westhoffswelt.de          slide: 34 / 36
Simple QUnit example



         Define a module (optional)

      module ( ”My s i m p l e e x a m p l e module ” ) ;

         Add a test

      t e s t ( ”My f i r s t t e s t ” , f u n c t i o n ( ) {
          ok ( t r u e , ” E v e r y t h i n g i s f i n e . ” ) ;
      }) ;




 http://westhoffswelt.de               jakob@westhoffswelt.de          slide: 34 / 36
Possible QUnit assertions



         ok(state, [message])
               A boolean assertion, equivalent to JUnit’s assertTrue
         equals(actual, expected, [message])
               A comparison assertion, equivalent to JUnit’s assertEquals
         same(actual, expected, [message])
               A deep recursive comparison




 http://westhoffswelt.de        jakob@westhoffswelt.de            slide: 35 / 36
Possible QUnit assertions



         ok(state, [message])
               A boolean assertion, equivalent to JUnit’s assertTrue
         equals(actual, expected, [message])
               A comparison assertion, equivalent to JUnit’s assertEquals
         same(actual, expected, [message])
               A deep recursive comparison




 http://westhoffswelt.de        jakob@westhoffswelt.de            slide: 35 / 36
Possible QUnit assertions



         ok(state, [message])
               A boolean assertion, equivalent to JUnit’s assertTrue
         equals(actual, expected, [message])
               A comparison assertion, equivalent to JUnit’s assertEquals
         same(actual, expected, [message])
               A deep recursive comparison




 http://westhoffswelt.de        jakob@westhoffswelt.de            slide: 35 / 36
Assyncronous assertions



         Use start() and stop() for asyncronous testing

      t e s t ( ”My a s y n c t e s t ” , f u n c t i o n ( ) {
          stop () ;
          setTimeout ( f u n t i o n () {
              ok ( t r u e , ” E v e r y t h i n g i s f i n e ” ) ;
              start () ;
          } , 1000) ;
      }) ;




 http://westhoffswelt.de               jakob@westhoffswelt.de            slide: 36 / 36

More Related Content

Developing jQuery Plugins with Ease

  • 1. Developing jQuery Plugins creating an edit-on-demand plugin Jakob Westhoff <jakob@php.net> FrOSCon 2009 August 22, 2009 http://westhoffswelt.de jakob@westhoffswelt.de slide: 1 / 36
  • 2. About Me Jakob Westhoff Computer science student at the TU Dortmund Web-developer for more than 6 years Author of Activebar2 (used by http://ie6update.com) Active in different Open Source projects http://westhoffswelt.de jakob@westhoffswelt.de slide: 2 / 36
  • 3. jQuery about itself From the jQuery Website: jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript. http://westhoffswelt.de jakob@westhoffswelt.de slide: 3 / 36
  • 4. jQuery about itself From the jQuery Website: jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript. http://westhoffswelt.de jakob@westhoffswelt.de slide: 3 / 36
  • 5. jQuery about itself From the jQuery Website: jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript. http://westhoffswelt.de jakob@westhoffswelt.de slide: 3 / 36
  • 6. jQuery about itself From the jQuery Website: jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript. http://westhoffswelt.de jakob@westhoffswelt.de slide: 3 / 36
  • 7. jQuery about itself From the jQuery Website: jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript. http://westhoffswelt.de jakob@westhoffswelt.de slide: 3 / 36
  • 8. Introduction to jQuery Compact only 56kb minified 19kb minified and gzipped Cross-browser compatible Internet Explorer 6.0+ Firefox 2+ Safari 3.0+ Opera 9.0+ Chrome Easily extendable http://westhoffswelt.de jakob@westhoffswelt.de slide: 4 / 36
  • 9. Introduction to jQuery Compact only 56kb minified 19kb minified and gzipped Cross-browser compatible Internet Explorer 6.0+ Firefox 2+ Safari 3.0+ Opera 9.0+ Chrome Easily extendable http://westhoffswelt.de jakob@westhoffswelt.de slide: 4 / 36
  • 10. Introduction to jQuery Compact only 56kb minified 19kb minified and gzipped Cross-browser compatible Internet Explorer 6.0+ Firefox 2+ Safari 3.0+ Opera 9.0+ Chrome Easily extendable http://westhoffswelt.de jakob@westhoffswelt.de slide: 4 / 36
  • 11. jQuery Example $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ; Find all paragraphs with the id example Add the css class highlight to them Fade in the paragraph slowly http://westhoffswelt.de jakob@westhoffswelt.de slide: 5 / 36
  • 12. jQuery Example $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ; Find all paragraphs with the id example Add the css class highlight to them Fade in the paragraph slowly http://westhoffswelt.de jakob@westhoffswelt.de slide: 5 / 36
  • 13. jQuery Example $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ; Find all paragraphs with the id example Add the css class highlight to them Fade in the paragraph slowly http://westhoffswelt.de jakob@westhoffswelt.de slide: 5 / 36
  • 14. jQuery Example $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ; Find all paragraphs with the id example Add the css class highlight to them Fade in the paragraph slowly http://westhoffswelt.de jakob@westhoffswelt.de slide: 5 / 36
  • 15. Working with jQuery $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ; Accessed using $ or jQuery Document centric $(css selector).operation Fluent interface paradigm operation().operation().operation() http://westhoffswelt.de jakob@westhoffswelt.de slide: 6 / 36
  • 16. Working with jQuery $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ; Accessed using $ or jQuery Document centric $(css selector).operation Fluent interface paradigm operation().operation().operation() http://westhoffswelt.de jakob@westhoffswelt.de slide: 6 / 36
  • 17. Working with jQuery $ ( ”p#e x a m p l e ” ) . a d d C l a s s ( ” h i g h l i g h t ” ) . f a d e I n ( ” s l o w ” ) ; Accessed using $ or jQuery Document centric $(css selector).operation Fluent interface paradigm operation().operation().operation() http://westhoffswelt.de jakob@westhoffswelt.de slide: 6 / 36
  • 18. Beginning Plugin Development Before you start Check http://plugins.jquery.com/ Read Plugins/Authoring documentation http://docs.jquery.com/Plugins/Authoring http://westhoffswelt.de jakob@westhoffswelt.de slide: 7 / 36
  • 19. Beginning Plugin Development Before you start Check http://plugins.jquery.com/ Read Plugins/Authoring documentation http://docs.jquery.com/Plugins/Authoring http://westhoffswelt.de jakob@westhoffswelt.de slide: 7 / 36
  • 20. Introducing the Example On-Demand-Editing Plugin Used by Flickr and others http://westhoffswelt.de jakob@westhoffswelt.de slide: 8 / 36
  • 21. Plugin Requirements Applyable to every block level element Capture on mouseover / mouseout events for color change on hovering Transform content to edit box and save/cancel buttons onclick Execute user-definable callback function once new data is provided http://westhoffswelt.de jakob@westhoffswelt.de slide: 9 / 36
  • 22. Plugin Requirements Applyable to every block level element Capture on mouseover / mouseout events for color change on hovering Transform content to edit box and save/cancel buttons onclick Execute user-definable callback function once new data is provided http://westhoffswelt.de jakob@westhoffswelt.de slide: 9 / 36
  • 23. Plugin Requirements Applyable to every block level element Capture on mouseover / mouseout events for color change on hovering Transform content to edit box and save/cancel buttons onclick Execute user-definable callback function once new data is provided http://westhoffswelt.de jakob@westhoffswelt.de slide: 9 / 36
  • 24. Plugin Requirements Applyable to every block level element Capture on mouseover / mouseout events for color change on hovering Transform content to edit box and save/cancel buttons onclick Execute user-definable callback function once new data is provided http://westhoffswelt.de jakob@westhoffswelt.de slide: 9 / 36
  • 25. Let’s begin Choose a name for our plugin: editable Create jquery.editable.css Hover effect Textbox look and feel Button positioning / look and feel http://westhoffswelt.de jakob@westhoffswelt.de slide: 10 / 36
  • 26. Stylesheet for our Plugin Choose a name for our plugin: editable Create jquery.editable.css Hover effect Textbox look and feel Button positioning / look and feel http://westhoffswelt.de jakob@westhoffswelt.de slide: 10 / 36
  • 27. Stylesheet for our Plugin 1 . editable hover , 2 . editable active 3 { 4 b a c k g r o u n d −c o l o r : #e f e e e e ; 5 } 6 7 . e d i t a b l e c o n t a i n e r span 8 { 9 f o n t −s i z e : 12 px ; 10 c o l o r : #000000; 11 m a r g i n : 0 8 px 0 8 px ; 12 } 13 14 . e d i t a b l e c o n t a i n e r input , 15 . editable container textarea 16 { 17 display : block ; 18 } http://westhoffswelt.de jakob@westhoffswelt.de slide: 11 / 36
  • 28. The problem with the $ shortcut $ should not be used in plugins jQuery allows redefining of this alias for compatability reasons May break your plugin Always use jQuery Or use nifty workaround: 1 ( function ($) { 2 ... 3 // Your p l u g i n c o d e g o e s h e r e 4 ... 5 }) ( jQuery ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 12 / 36
  • 29. The problem with the $ shortcut $ should not be used in plugins jQuery allows redefining of this alias for compatability reasons May break your plugin Always use jQuery Or use nifty workaround: 1 ( function ($) { 2 ... 3 // Your p l u g i n c o d e g o e s h e r e 4 ... 5 }) ( jQuery ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 12 / 36
  • 30. The problem with the $ shortcut $ should not be used in plugins jQuery allows redefining of this alias for compatability reasons May break your plugin Always use jQuery Or use nifty workaround: 1 ( function ($) { 2 ... 3 // Your p l u g i n c o d e g o e s h e r e 4 ... 5 }) ( jQuery ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 12 / 36
  • 31. Registering the Plugin Method Choose a name for our plugin method: editable Register the new method in the jQuery.fn namespace: 1 jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) { 2 ... 3 // P l u g i n method 4 ... 5 } http://westhoffswelt.de jakob@westhoffswelt.de slide: 13 / 36
  • 32. Registering the Plugin Method Choose a name for our plugin method: editable Register the new method in the jQuery.fn namespace: 1 jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) { 2 ... 3 // P l u g i n method 4 ... 5 } http://westhoffswelt.de jakob@westhoffswelt.de slide: 13 / 36
  • 33. Handling Optional Options Most plugins need configuration options Use a default if a certain option is not provided Options are supplied as associative array / object Utilize the jQuery.extend function: 1 var o p t i o n = jQuery . extend ({ 2 ” multiline ” : false , 3 ” prefix ”: ”editable ” 4 } , option ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 14 / 36
  • 34. Handling Optional Options Most plugins need configuration options Use a default if a certain option is not provided Options are supplied as associative array / object Utilize the jQuery.extend function: 1 var o p t i o n = jQuery . extend ({ 2 ” multiline ” : false , 3 ” prefix ”: ”editable ” 4 } , option ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 14 / 36
  • 35. Handling Optional Options Most plugins need configuration options Use a default if a certain option is not provided Options are supplied as associative array / object Utilize the jQuery.extend function: 1 var o p t i o n = jQuery . extend ({ 2 ” multiline ” : false , 3 ” prefix ”: ”editable ” 4 } , option ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 14 / 36
  • 36. Handling Optional Options Most plugins need configuration options Use a default if a certain option is not provided Options are supplied as associative array / object Utilize the jQuery.extend function: 1 var o p t i o n = jQuery . extend ({ 2 ” multiline ” : false , 3 ” prefix ”: ”editable ” 4 } , option ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 14 / 36
  • 37. this Context inside the Plugin Method The this context inside a plugin method ... points to the called jQuery object may represent a set of DOM elements Use each to handle sets correctly: 1 return $ ( t h i s ) . each ( f u n c t i o n ( ) { 2 ... 3 // ” t h i s ” maps t o t h e c u r r e n t l y h a n d l e d e l e m e n t 4 ... 5 }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 15 / 36
  • 38. Using each to Handle Sets The this context inside a plugin method ... points to the called jQuery object may represent a set of DOM elements Use each to handle sets correctly: 1 return $ ( t h i s ) . each ( f u n c t i o n ( ) { 2 ... 3 // ” t h i s ” maps t o t h e c u r r e n t l y h a n d l e d e l e m e n t 4 ... 5 }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 15 / 36
  • 39. What we have got so far 1 ( function ($) { 2 jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) { 3 4 // O p t i o n h a n d l i n g 5 var o p t i o n = jQuery . extend ({ 6 ” option ” : ” default value ” , 7 ... 8 } , option ) ; 9 10 // H a n d l e s e t s c o r r e c t l y . 11 // E n s u r e t h e f l u e n t i n t e r f a c e p a r a d i g m . 12 return $ ( t h i s ) . each ( f u n c t i o n ( ) { 13 ... 14 // ” r e a l ” p l u g i n c o d e g o e s i n h e r e 15 ... 16 }) ; 17 18 } 19 }) ( jQuery ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 16 / 36
  • 40. Modifying the Container Element Add a css class to the container element: $( this ) . addClass ( option [ ’ p r e f i x ’ ] + ’ container ’ ) ; Register events for onhover effect: 1 $ ( t h i s ) . bind ( ” mouseenter mouseleave ” , 2 function (e) { 3 $( this ) . toggleClass ( 4 option [ ’ p r e f i x ’ ] + ’ hover ’ 5 ); 6 } 7 ); http://westhoffswelt.de jakob@westhoffswelt.de slide: 17 / 36
  • 41. Modifying the Container Element Add a css class to the container element: $( this ) . addClass ( option [ ’ p r e f i x ’ ] + ’ container ’ ) ; Register events for onhover effect: 1 $ ( t h i s ) . bind ( ” mouseenter mouseleave ” , 2 function (e) { 3 $( this ) . toggleClass ( 4 option [ ’ p r e f i x ’ ] + ’ hover ’ 5 ); 6 } 7 ); http://westhoffswelt.de jakob@westhoffswelt.de slide: 17 / 36
  • 42. Enter Edit Mode on Click On click enter edit mode Registered using one as once only event Calling plugin private function enterEditMode 1 $ ( t h i s ) . one ( ’ c l i c k ’ , 2 function () { 3 enterEditMode ( $ ( t h i s ) ) ; 4 } 5 ); http://westhoffswelt.de jakob@westhoffswelt.de slide: 18 / 36
  • 43. Private Plugin Functions Function in the plugin scope Access to all variables globally declared (option) Access to all plugin method parameters (savefn) 1 jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) { 2 var option = . . . 3 4 return $ ( t h i s ) . each ( f u n c t i o n ( ) { 5 ... 6 }) ; 7 8 f u n c t i o n enterEditMode ( c o n t a i n e r ) { 9 // A c c e s s t o : c o n t a i n e r , s a v e f n , o p t i o n 10 } 11 } http://westhoffswelt.de jakob@westhoffswelt.de slide: 19 / 36
  • 44. Private Plugin Functions Function in the plugin scope Access to all variables globally declared (option) Access to all plugin method parameters (savefn) 1 jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) { 2 var option = . . . 3 4 return $ ( t h i s ) . each ( f u n c t i o n ( ) { 5 ... 6 }) ; 7 8 f u n c t i o n enterEditMode ( c o n t a i n e r ) { 9 // A c c e s s t o : c o n t a i n e r , s a v e f n , o p t i o n 10 } 11 } http://westhoffswelt.de jakob@westhoffswelt.de slide: 19 / 36
  • 45. Private Plugin Functions Function in the plugin scope Access to all variables globally declared (option) Access to all plugin method parameters (savefn) 1 jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) { 2 var option = . . . 3 4 return $ ( t h i s ) . each ( f u n c t i o n ( ) { 5 ... 6 }) ; 7 8 f u n c t i o n enterEditMode ( c o n t a i n e r ) { 9 // A c c e s s t o : c o n t a i n e r , s a v e f n , o p t i o n 10 } 11 } http://westhoffswelt.de jakob@westhoffswelt.de slide: 19 / 36
  • 46. Private Plugin Functions Function in the plugin scope Access to all variables globally declared (option) Access to all plugin method parameters (savefn) 1 jQuery . fn . e d i t a b l e = f u n c t i o n ( savefn , option ) { 2 var option = . . . 3 4 return $ ( t h i s ) . each ( f u n c t i o n ( ) { 5 ... 6 }) ; 7 8 f u n c t i o n enterEditMode ( c o n t a i n e r ) { 9 // A c c e s s t o : c o n t a i n e r , s a v e f n , o p t i o n 10 } 11 } http://westhoffswelt.de jakob@westhoffswelt.de slide: 19 / 36
  • 47. Needed Private Functions enterEditMode( container ) Called whenever data input should be possible leaveEditMode( container, updatedText ) Called whenever the edit process is complete and the normal state should be restored http://westhoffswelt.de jakob@westhoffswelt.de slide: 20 / 36
  • 48. Needed Private Functions enterEditMode( container ) Called whenever data input should be possible leaveEditMode( container, updatedText ) Called whenever the edit process is complete and the normal state should be restored http://westhoffswelt.de jakob@westhoffswelt.de slide: 20 / 36
  • 49. enterEditMode - Cleanup a little bit Store the original content v a r o r i g i n a l T e x t C o n t e n t = c o n t a i n e r . h t ml ( ) ; Disable onhover effects c o n t a i n e r . unbind ( ’ mouseenter mouseleave ’ ) ; container . removeClass ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ; Warning: This removes all mouseenter and mouseleave event handlers of this node Set correct css classes container . addClass ( option [ ’ p r e f i x ’ ] + ’ a c t iv e ’ ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 21 / 36
  • 50. enterEditMode - Cleanup a little bit Store the original content v a r o r i g i n a l T e x t C o n t e n t = c o n t a i n e r . h t ml ( ) ; Disable onhover effects c o n t a i n e r . unbind ( ’ mouseenter mouseleave ’ ) ; container . removeClass ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ; Warning: This removes all mouseenter and mouseleave event handlers of this node Set correct css classes container . addClass ( option [ ’ p r e f i x ’ ] + ’ a c t iv e ’ ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 21 / 36
  • 51. enterEditMode - Cleanup a little bit Store the original content v a r o r i g i n a l T e x t C o n t e n t = c o n t a i n e r . h t ml ( ) ; Disable onhover effects c o n t a i n e r . unbind ( ’ mouseenter mouseleave ’ ) ; container . removeClass ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ; Warning: This removes all mouseenter and mouseleave event handlers of this node Set correct css classes container . addClass ( option [ ’ p r e f i x ’ ] + ’ a c t iv e ’ ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 21 / 36
  • 52. enterEditMode - Create input field and buttons Create the needed input field v a r e d i t = $ ( ’<i n p u t t y p e =” t e x t ”></ i n p u t > ’ ) ; Create the needed buttons v a r s a v e = $ ( ’<b u t t o n c l a s s =” s a v e ”>Save </b u t t o n > ’ ) ; var cancel = $ ( ’<b u t t o n c l a s s =” c a n c e l ”>C a n c e l </b u t t o n > ’ ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 22 / 36
  • 53. enterEditMode - Create input field and buttons Create the needed input field v a r e d i t = $ ( ’<i n p u t t y p e =” t e x t ”></ i n p u t > ’ ) ; Create the needed buttons v a r s a v e = $ ( ’<b u t t o n c l a s s =” s a v e ”>Save </b u t t o n > ’ ) ; var cancel = $ ( ’<b u t t o n c l a s s =” c a n c e l ”>C a n c e l </b u t t o n > ’ ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 22 / 36
  • 54. enterEditMode - Register button onClick Register onClick for Cancel 1 cancel . bind ( ’ c l i c k ’ , function ( e ) { 2 e . stopPropagation () ; 3 leaveEditMode ( container , originalTextContent ) ; 4 }) ; Register onClick for Save 1 save . bind ( ’ c l i c k ’ , function ( e ) { 2 e . stopPropagation () ; 3 leaveEditMode ( 4 container , 5 savefn ( edit . val () ) 6 ); 7 }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 23 / 36
  • 55. enterEditMode - Register button onClick Register onClick for Cancel 1 cancel . bind ( ’ c l i c k ’ , function ( e ) { 2 e . stopPropagation () ; 3 leaveEditMode ( container , originalTextContent ) ; 4 }) ; Register onClick for Save 1 save . bind ( ’ c l i c k ’ , function ( e ) { 2 e . stopPropagation () ; 3 leaveEditMode ( 4 container , 5 savefn ( edit . val () ) 6 ); 7 }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 23 / 36
  • 56. enterEditMode - Replace current content Replace the current content with input field and buttons 1 c o n t a i n e r . empty ( ) 2 . append ( e d i t ) 3 . append ( s a v e ) 4 . append ( c a n c e l ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 24 / 36
  • 57. leaveEditMode - Reactivate onHover Remove state from css classes container . removeClass ( option [ ’ p r e f i x ’ ] + ’ a c t i v e ’ ) ; Bind events for onHover effect c o n t a i n e r . bind ( ” mouseenter mouseleave ” , f u n c t i o n ( e ) { container . t o g g l e C l a s s ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ; }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 25 / 36
  • 58. leaveEditMode - Reactivate onHover Remove state from css classes container . removeClass ( option [ ’ p r e f i x ’ ] + ’ a c t i v e ’ ) ; Bind events for onHover effect c o n t a i n e r . bind ( ” mouseenter mouseleave ” , f u n c t i o n ( e ) { container . t o g g l e C l a s s ( option [ ’ p r e f i x ’ ] + ’ hover ’ ) ; }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 25 / 36
  • 59. leaveEditMode - Reactivate onClick Re-register the onClick handler 1 $ ( t h i s ) . one ( ’ c l i c k ’ , 2 function () { 3 enterEditMode ( $ ( t h i s ) ) ; 4 } 5 ); http://westhoffswelt.de jakob@westhoffswelt.de slide: 26 / 36
  • 60. leaveEditMode - Update text content Update the container with the given text content c o n t a i n e r . html ( updatedText ) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 27 / 36
  • 61. Calling the plugin Simply call the editable method on the selected node. $ ( ” h1 ” ) . e d i t a b l e ( f u n c t i o n ( c o n t e n t ) { // Do some AJAX magic h e r e . . . return content ; }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 28 / 36
  • 62. editable Live Demo Let’s take a look Live Demo! http://westhoffswelt.de jakob@westhoffswelt.de slide: 29 / 36
  • 63. 6 Golden Rules of Plugin Development 1 Name your file jquery.[insert name of plugin].js eg. jquery.myplugin.js 2 Attach new methods to the jQuery.fn object 3 Attach new functions to the jQuery object itself 4 Methods have always to return the object they are working on 5 Use each to ensure your method is applied to all elements in a set 6 Always use jQuery instead of the $ shortcut in your plugins or use the nifty trick shown http://westhoffswelt.de jakob@westhoffswelt.de slide: 30 / 36
  • 64. 6 Golden Rules of Plugin Development 1 Name your file jquery.[insert name of plugin].js eg. jquery.myplugin.js 2 Attach new methods to the jQuery.fn object 3 Attach new functions to the jQuery object itself 4 Methods have always to return the object they are working on 5 Use each to ensure your method is applied to all elements in a set 6 Always use jQuery instead of the $ shortcut in your plugins or use the nifty trick shown http://westhoffswelt.de jakob@westhoffswelt.de slide: 30 / 36
  • 65. 6 Golden Rules of Plugin Development 1 Name your file jquery.[insert name of plugin].js eg. jquery.myplugin.js 2 Attach new methods to the jQuery.fn object 3 Attach new functions to the jQuery object itself 4 Methods have always to return the object they are working on 5 Use each to ensure your method is applied to all elements in a set 6 Always use jQuery instead of the $ shortcut in your plugins or use the nifty trick shown http://westhoffswelt.de jakob@westhoffswelt.de slide: 30 / 36
  • 66. 6 Golden Rules of Plugin Development 1 Name your file jquery.[insert name of plugin].js eg. jquery.myplugin.js 2 Attach new methods to the jQuery.fn object 3 Attach new functions to the jQuery object itself 4 Methods have always to return the object they are working on 5 Use each to ensure your method is applied to all elements in a set 6 Always use jQuery instead of the $ shortcut in your plugins or use the nifty trick shown http://westhoffswelt.de jakob@westhoffswelt.de slide: 30 / 36
  • 67. 6 Golden Rules of Plugin Development 1 Name your file jquery.[insert name of plugin].js eg. jquery.myplugin.js 2 Attach new methods to the jQuery.fn object 3 Attach new functions to the jQuery object itself 4 Methods have always to return the object they are working on 5 Use each to ensure your method is applied to all elements in a set 6 Always use jQuery instead of the $ shortcut in your plugins or use the nifty trick shown http://westhoffswelt.de jakob@westhoffswelt.de slide: 30 / 36
  • 68. 6 Golden Rules of Plugin Development 1 Name your file jquery.[insert name of plugin].js eg. jquery.myplugin.js 2 Attach new methods to the jQuery.fn object 3 Attach new functions to the jQuery object itself 4 Methods have always to return the object they are working on 5 Use each to ensure your method is applied to all elements in a set 6 Always use jQuery instead of the $ shortcut in your plugins or use the nifty trick shown http://westhoffswelt.de jakob@westhoffswelt.de slide: 30 / 36
  • 69. Thanks for listening Questions, comments or annotations? Slides: http://westhoffswelt.de/portfolio.htm Contact: Jakob Westhoff <jakob@php.net> http://westhoffswelt.de jakob@westhoffswelt.de slide: 31 / 36
  • 70. Unit testing with QUnit Unit testing? YES you want to! QUnit jQuerys unit testing framework http://docs.jquery.com/QUnit No stable release, yet However core features are extremly stable http://westhoffswelt.de jakob@westhoffswelt.de slide: 32 / 36
  • 71. Unit testing with QUnit Unit testing? YES you want to! QUnit jQuerys unit testing framework http://docs.jquery.com/QUnit No stable release, yet However core features are extremly stable http://westhoffswelt.de jakob@westhoffswelt.de slide: 32 / 36
  • 72. Unit testing with QUnit Unit testing? YES you want to! QUnit jQuerys unit testing framework http://docs.jquery.com/QUnit No stable release, yet However core features are extremly stable http://westhoffswelt.de jakob@westhoffswelt.de slide: 32 / 36
  • 73. Unit testing with QUnit Unit testing? YES you want to! QUnit jQuerys unit testing framework http://docs.jquery.com/QUnit No stable release, yet However core features are extremly stable http://westhoffswelt.de jakob@westhoffswelt.de slide: 32 / 36
  • 74. Unit testing with QUnit Unit testing? YES you want to! QUnit jQuerys unit testing framework http://docs.jquery.com/QUnit No stable release, yet However core features are extremly stable http://westhoffswelt.de jakob@westhoffswelt.de slide: 32 / 36
  • 75. Simple QUnit example Include js and css < s c r i p t s r c=” j q u e r y − l a t e s t . j s ”></ s c r i p t> < s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” q u n i t / t e s t r u n n e r . j s ”></ s c r i p t> < l i n k r e l=” s t y l e s h e e t ” h r e f=” q u n i t / t e s t s u i t e . c s s ” type=” t e x t / c s s ” media=” s c r e e n ” /> Create a simple html page to be filled with information <h1>QUnit e x a m p l e</h1> <h2 i d=” b a n n e r ”></h2> <h2 i d=” u s e r A g e n t ”></h2> <o l i d=” t e s t s ”></ o l> <d i v i d=” main ”></ d i v> http://westhoffswelt.de jakob@westhoffswelt.de slide: 33 / 36
  • 76. Simple QUnit example Include js and css < s c r i p t s r c=” j q u e r y − l a t e s t . j s ”></ s c r i p t> < s c r i p t type=” t e x t / j a v a s c r i p t ” s r c=” q u n i t / t e s t r u n n e r . j s ”></ s c r i p t> < l i n k r e l=” s t y l e s h e e t ” h r e f=” q u n i t / t e s t s u i t e . c s s ” type=” t e x t / c s s ” media=” s c r e e n ” /> Create a simple html page to be filled with information <h1>QUnit e x a m p l e</h1> <h2 i d=” b a n n e r ”></h2> <h2 i d=” u s e r A g e n t ”></h2> <o l i d=” t e s t s ”></ o l> <d i v i d=” main ”></ d i v> http://westhoffswelt.de jakob@westhoffswelt.de slide: 33 / 36
  • 77. Simple QUnit example Define a module (optional) module ( ”My s i m p l e e x a m p l e module ” ) ; Add a test t e s t ( ”My f i r s t t e s t ” , f u n c t i o n ( ) { ok ( t r u e , ” E v e r y t h i n g i s f i n e . ” ) ; }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 34 / 36
  • 78. Simple QUnit example Define a module (optional) module ( ”My s i m p l e e x a m p l e module ” ) ; Add a test t e s t ( ”My f i r s t t e s t ” , f u n c t i o n ( ) { ok ( t r u e , ” E v e r y t h i n g i s f i n e . ” ) ; }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 34 / 36
  • 79. Possible QUnit assertions ok(state, [message]) A boolean assertion, equivalent to JUnit’s assertTrue equals(actual, expected, [message]) A comparison assertion, equivalent to JUnit’s assertEquals same(actual, expected, [message]) A deep recursive comparison http://westhoffswelt.de jakob@westhoffswelt.de slide: 35 / 36
  • 80. Possible QUnit assertions ok(state, [message]) A boolean assertion, equivalent to JUnit’s assertTrue equals(actual, expected, [message]) A comparison assertion, equivalent to JUnit’s assertEquals same(actual, expected, [message]) A deep recursive comparison http://westhoffswelt.de jakob@westhoffswelt.de slide: 35 / 36
  • 81. Possible QUnit assertions ok(state, [message]) A boolean assertion, equivalent to JUnit’s assertTrue equals(actual, expected, [message]) A comparison assertion, equivalent to JUnit’s assertEquals same(actual, expected, [message]) A deep recursive comparison http://westhoffswelt.de jakob@westhoffswelt.de slide: 35 / 36
  • 82. Assyncronous assertions Use start() and stop() for asyncronous testing t e s t ( ”My a s y n c t e s t ” , f u n c t i o n ( ) { stop () ; setTimeout ( f u n t i o n () { ok ( t r u e , ” E v e r y t h i n g i s f i n e ” ) ; start () ; } , 1000) ; }) ; http://westhoffswelt.de jakob@westhoffswelt.de slide: 36 / 36