SlideShare uma empresa Scribd logo
1 de 82
Baixar para ler offline
BEN ALMAN                                                                                  benalman.com
                                                                                              @cowboy




  JQUERY PLUGIN CREATION
 organization, generalization, minification, optimization, gratification




  'jquery plugin cre: organiz, generaliz, minific, optimiz, gratific'.replace( /([:,]|$)/g, 'ation$1' );
A FEW STYLE BASICS
WHITE SPACE
WHITE SPACE
  Tabs vs. Spaces
WHITE SPACE
  Tabs vs. Spaces
WHITE SPACE
  Tabs vs. Spaces
  Less Crowding
WHITE SPACE
  Tabs vs. Spaces
  Less Crowding
COMMENTS
Funny can be good, just
  don’t go overboard.
VARIABLES
Let them breathe!
VARIABLES
Let them breathe!
 Don’t Obfuscate
(not yet, at least)
A FEW STYLE BASICS
Step back and take a look. Is your code readable?
If it isn’t now, it certainly won’t be in six months.
ORGANIZATION
SINGLETON
Very basic implementation:
      Object Literal
SINGLETON
 Everything is public..
   Good or Bad?
SINGLETON
 Everything is public..
   Good or Bad?



                      Do we really want to expose the “pluralize” method?
                      Does the user want or need this?

                      Do we really want to expose the “things” property?
                      What if the user tries to set it to -100?
INTERRUPTION!
A brief explanation of Closures
CLOSURES
Remember this? Banging
your head on the table
  for like, two hours?
CLOSURES
Remember this? Banging
your head on the table   Why do they all alert 10?!
  for like, two hours?
CLOSURES
 Aha! A Closure.
 (thanks, Google)
CLOSURES             OMG!!
 Aha! A Closure.    Unicorns &
 (thanks, Google)   Rainbows!!
CLOSURES            Take
 Aha! A Closure.    your
 (thanks, Google)   pick
OK.
Back to the the Singleton...
SINGLETON
 Everything is public..
   Good or Bad?



                      Do we really want to expose the “pluralize” method?
                      Does the user want or need this?

                      Do we really want to expose the “things” property?
                      What if the user tries to set it to -100?
SINGLETON
  Object Literal
  (in a Closure)
JQUERY PLUGIN
    The basics
JQUERY PLUGIN
    Closure?
JQUERY PLUGIN
     Closure?
  Maybe, whatever.
JQUERY PLUGIN
    Closure?
JQUERY PLUGIN
    Closure?
      Yes!
JQUERY PLUGIN
         $.fn.extend
"Extends the jQuery element
set to provide new methods"
JQUERY PLUGIN
 Individual functions:
JQUERY PLUGIN
 Individual functions:
   Less indentation
JQUERY PLUGIN
  Individual functions:
    Less indentation
No pesky commas ( IE)
JQUERY PLUGIN
  Should “lengthen”
   even be public?
JQUERY PLUGIN
  Should “lengthen”
   even be public?
    Probably not.
JQUERY PLUGIN
  Should “lengthen”
   even be public?
    Probably not.
JQUERY PLUGIN
Great, we made a plugin!
JQUERY PLUGIN
 Great, we made a plugin!
But can we make it better?
GENERALIZATION
JQUERY PLUGIN
  Let’s generalize!
JQUERY PLUGIN
    Holy crap!
JQUERY PLUGIN
$.longUrl - more flexible
JQUERY PLUGIN
  $.longUrl - more flexible
$.fn.longUrl uses it internally
DON’T DUPLICATE CODE!
JQUERY PLUGIN
   Generalized!
GENERALIZATION
GENERALIZATION
GENERALIZATION
GENERALIZATION
GENERALIZATION
MINIFICATION
JQUERY PLUGIN
   Unminified
JQUERY PLUGIN
    Minified
JQUERY PLUGIN
Minified, approximately
(slightly more readable)
JQUERY PLUGIN
Helping the YUI Compressor


                   “bleh”
JQUERY PLUGIN
Helping the YUI Compressor
  Objects and references

                   “bleh”
JQUERY PLUGIN
Helping the YUI Compressor
  Objects and references

                   “bleh”
JQUERY PLUGIN
Helping the YUI Compressor
  Objects and references
 p_longUrl will be munged
right on.

JQUERY PLUGIN
Helping the YUI Compressor
  Objects and references
 p_longUrl will be munged
JQUERY PLUGIN
Helping the YUI Compressor
    Objects and Strings
neat.

JQUERY PLUGIN
Helping the YUI Compressor
    Objects and Strings
JQUERY PLUGIN
Helping the YUI Compressor
    Objects and Strings
  longUrl will be munged
JQUERY PLUGIN
Helping the YUI Compressor
    Objects and Strings
       Yes, I’m insane.
JQUERY PLUGIN
Helping the YUI Compressor
    Arrays and Strings
JQUERY PLUGIN
Helping the YUI Compressor
    Arrays and Strings
      33 chars saved
JQUERY PLUGIN
Helping the YUI Compressor
    Arrays and Strings
       33 chars saved
      (in this example)
OPTIMIZATION
JQUERY PLUGIN
Avoid unnecessary overhead!
JQUERY PLUGIN
Avoid unnecessary overhead!
       Save a kitten.
        Optimize.
JQUERY PLUGIN
Avoid unnecessary overhead!
       Save a kitten.
        Optimize.
AVOID UNNECESSARY OVERHEAD!




                    This stuff
                does NOT belong
                     in here!
ONE FINAL EXAMPLE
(function($) {
  '$:nomunge'; // Used by YUI compressor.

  var url_regexp,
    tag_attributes = {},

   // A few constants.
   undefined,
   window = this,
   TRUE = true,
   FALSE = false,
   has_onhashchange = 'onhashchange' in window,

   // Some convenient shortcuts.
   aps = Array.prototype.slice,
   loc = document.location,

   // Internal plugin method references.
   p_urlTagAttrList,
   p_urlInternalHost,
   p_urlInternalRegExp,
   p_isUrlInternal,
   p_isUrlExternal,
   p_urlFilter,
   p_urlFilterSelector,
   p_setFragment,

   // Reused internal strings.
   str_urlInternal     = 'urlInternal',
   str_urlExternal     = 'urlExternal',
   str_queryString     = 'queryString',
   str_fragment        = 'fragment',
   str_update          = 'update',
   str_passQueryString = 'passQueryString',
   str_passFragment    = 'passFragment',
   str_fragmentChange = 'fragmentChange',
   str_hashchange      = 'hashchange.' + str_fragmentChange,

   // fragmentChange event handler
   timeout_id,
   last_fragment;
ONE FINAL EXAMPLE
// A few commonly used bits, broken out to help reduce minified file size.

function is_string( arg ) {
   return typeof arg === 'string';
};

function is_object( arg ) {
   return typeof arg === 'object';
};

function curry() {
  var args = aps.call( arguments ),
    func = args.shift();

     return function() {
        return func.apply( this, args.concat( aps.call( arguments ) ) );
     };
};

// Work-around for an annoying Firefox bug where document.location.hash gets
// urldecoded by default.

function get_fragment() {
   return loc.href.replace( /^[^#]*#?/, '' );
};



//    Method: jQuery.urlTagAttrList
//
//    Get the internal "Default URL attribute per tag" list, or augment the list
//    with additional tag-attribute pairs, in case the defaults are insufficient.
//
//    This list contains the default attributes for the <jQuery.fn.urlInternal>
//    and <jQuery.fn.urlExternal> methods, as well as the <:urlInternal> and
//    <:urlExternal> selector filters, to determine which URL will be tested for
//    internal- or external-ness. In the <jQuery.fn.queryString>,
//    <jQuery.fn.fragment>, <jQuery.fn.passQueryString> and
//    <jQuery.fn.passFragment> methods, this list is used to determine which URL
//    will be modified.
//
//    Default List:
//
ONE FINAL EXAMPLE
function p_params( fragment_mode, arg0, arg1, arg2 ) {
  var params;

     if ( is_string(arg1) || is_object(arg1) ) {
       // Build URL.
       return build_url( arg0, arg1, arg2, fragment_mode );

     } else if ( is_object(arg0) ) {
       // Serialize.
       return $.param( arg0 );

     } else if ( is_string(arg0) ) {
       // Deserialize.
       return deserialize( arg0, arg1, fragment_mode );

     } else {
       // Deserialize document query string / fragment.
       params = fragment_mode
         ? get_fragment()
         : loc.search;

         return deserialize( params, arg0, fragment_mode );
     }
};

$[str_queryString] = curry( p_params, 0 );
$[str_fragment]    = curry( p_params, 1 );

function p_fn_params() {
  var attr,
    params,
    merge_mode,
    args = aps.call( arguments ),
    fragment_mode = args.shift();

     if ( is_string(args[1]) || is_object(args[1]) ) {
       attr = args.shift();
     }
     params = args.shift();
     merge_mode = args.shift();
ONE FINAL EXAMPLE
/*
 * URL Utils - v1.11 - 9/10/2009
 * http://benalman.com/
 *
 * Copyright (c) 2009 "Cowboy" Ben Alman
 * Licensed under the MIT license
 * http://benalman.com/about/license/
 */
(function($){var M,q={},z,i=this,u=true,J=false,F="onhashchange" in
i,a=Array.prototype.slice,j=document.location,E,d,b,x,v,e,C,I,p="urlInternal",L="urlExternal",y="queryString",G="fragment",H="update",f=
"passQueryString",w="passFragment",c="fragmentChange",o="hashchange."+c,h,g;function B(O){return typeof O==="string"}function l(O)
{return typeof O==="object"}function m(){var O=a.call(arguments),P=O.shift();return function(){return
P.apply(this,O.concat(a.call(arguments)))}}function k(){return j.href.replace(/^[^#]*#?/,"")}$.urlTagAttrList=E=function(O){return
$.extend(q,O)};E({a:"href",img:"src",form:"action",base:"href",script:"src",iframe:"src",link:"href"});function r(O){var
P=O.nodeName;return P?q[P.toLowerCase()]:""}$.urlInternalHost=d=function(Q){Q=Q?"(?:"+Q+".)?":"";var P=new RegExp("^"+Q
+"(.*)","i"),O="^"+j.protocol+"//"+j.hostname.replace(P,Q+"$1")+(j.port?":"+j.port:"")+"/";return b(O)};
$.urlInternalRegExp=b=function(O){if(O){M=B(O)?new RegExp(O,"i"):O}return M};d("www");$.isUrlInternal=x=function(O){if(!O){return
z}if(M.test(O)){return u}if(/^https?:///i.test(O)){return J}if(/^(?:#|[a-zd.-]+:)/i.test(O)){return z}return u};
$.isUrlExternal=v=function(O){var P=x(O);return typeof P==="boolean"?!P:P};e=function(P,O){return this.filter(":"+P+(O?"("+O+")":""))};
$.fn[p]=m(e,p);$.fn[L]=m(e,L);C=function(S,R,Q,P){var O=P[3]||r(R);return O?!!S($(R).attr(O)):J};$.expr[":"][p]=m(C,x);$.expr[":"]
[L]=m(C,v);function K(Q,R,P,O){var S;if(B(P)||l(P)){return n(R,P,O,Q)}else{if(l(R)){return $.param(R)}else{if(B(R)){return
D(R,P,Q)}else{S=Q?k():j.search;return D(S,R,Q)}}}}$[y]=m(K,0);$[G]=m(K,1);function N(){var
O,S,R,Q=a.call(arguments),P=Q.shift();if(B(Q[1])||l(Q[1])){O=Q.shift()}S=Q.shift();R=Q.shift();return this.each(function(){var V=$
(this),T=O||r(this),U=T&&V.attr(T)||"";U=K(P,U,S,R);V.attr(T,U)})}$.fn[y]=m(N,0);$.fn[G]=m(N,1);function A(){var
Q=a.call(arguments),P=Q.shift(),O=Q.shift(),R=K(P);if($.isFunction(Q[0])){R=Q.shift()(R)}else{if($.isArray(Q[0]))
{$.each(Q.shift(),function(T,S){delete R[S]})}}return K(P,O,R,Q.shift())}$[f]=m(A,0);$[w]=m(A,1);function t(){var
O,Q=a.call(arguments),P=Q.shift();if(B(Q[0])){O=Q.shift()}return this.each(function(){var T=$(this),R=O||
r(this),S=R&&T.attr(R)||"";S=A.apply(this,[P,S].concat(Q));T.attr(R,S)})}$.fn[f]=m(t,0);$.fn[w]=m(t,1);function D(U,T,Q){var
P,W,S,V={},R={"null":null,"true":u,"false":J},O=decodeURIComponent,X=Q?/^.*[#]/:/^.*[?]|#.*$/g;U=U.replace(X,"").replace(/+/g,"
").split("&");while(U.length){P=U.shift().split("=");W=O(P[0]);if(P.length===2){S=O(P[1]);if(T){if(S&&!isNaN(S))
{S=Number(S)}else{if(S==="undefined"){S=z}else{if(R[S]!==z){S=R[S]}}}}if($.isArray(V[W])){V[W].push(S)}else{if(V[W]!==z)
{V[W]=[V[W],S]}else{V[W]=S}}}else{if(W){V[W]=T?z:""}}}return V}function n(O,Q,T,P){var U,W=P?/^([^#]*)[#]?(.*)$/:/^([^#?]*)[?]?([^#]*)
(#?.*)/,S=O.match(W),V=D(S[2],0,P),R=S[3]||"";if(B(Q)){Q=D(Q,0,P)}if(T===2){U=Q}else{if(T===1){U=$.extend({},Q,V)}else{U=
$.extend({},V,Q)}}U=$.param(U);return S[1]+(P?"#":U||!S[1]?"?":"")+U+R}$.setFragment=I=function(P,O){var Q=l(P)?K(u,P):(P||"").replace(/
^#/,"");Q=P?n("#"+k(),"#"+Q,O,1):"#";j.href=j.href.replace(/#.*$/,"")+Q};$[c]=function(O){if(O===u){O=100}function P(){var R=
$.Event(c);R[G]=k();$(document).trigger(R)}F&&$(i).unbind(o);h&&clearTimeout(h);h=null;if(typeof O==="number"){if(F){$
(i).bind(o,P)}else{g=k();if($.isFunction(s)){s=s()}(function Q(){var S=k(),R=s[G](g);if(S!==g){s[H](S,R);g=S;P()}else{if(R!==g){I(R,
2)}}h=setTimeout(Q,O<0?0:O)})()}}};function s(){var O,P=$.browser,Q={};Q[H]=Q[G]=function(R){return R};if(P.msie&&P.version<8)
{Q[H]=function(T,R){var S=O.document;if(T!==R){S.open();S.close();S.location.hash="#"+T}};Q[G]=function(){return
O.document.location.hash.replace(/^#/,"")};O=$("<iframe/>").hide().appendTo("body").get(0).contentWindow;Q[H](k())}return Q}})(jQuery);
GRATIFICATION
GRATIFICATION
   Clean, simple API
GRATIFICATION
          Clean, simple API
Generalized code makes your life easier
GRATIFICATION
          Clean, simple API
Generalized code makes your life easier
   Minified code makes it smaller
GRATIFICATION
           Clean, simple API
Generalized code makes your life easier
    Minified code makes it smaller
  Efficient code makes it work faster
GRATIFICATION
           Clean, simple API
Generalized code makes your life easier
    Minified code makes it smaller
  Efficient code makes it work faster
      (and people complain less)
benalman.com
BEN ALMAN      @cowboy

Mais conteúdo relacionado

Mais procurados

Mojolicious: what works and what doesn't
Mojolicious: what works and what doesn'tMojolicious: what works and what doesn't
Mojolicious: what works and what doesn'tCosimo Streppone
 
Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Anatoly Sharifulin
 
Mojolicious, real-time web framework
Mojolicious, real-time web frameworkMojolicious, real-time web framework
Mojolicious, real-time web frameworktaggg
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkJeremy Kendall
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkJeremy Kendall
 
Drupal Best Practices
Drupal Best PracticesDrupal Best Practices
Drupal Best Practicesmanugoel2003
 
With a Mighty Hammer
With a Mighty HammerWith a Mighty Hammer
With a Mighty HammerBen Scofield
 
Inside Bokete: Web Application with Mojolicious and others
Inside Bokete:  Web Application with Mojolicious and othersInside Bokete:  Web Application with Mojolicious and others
Inside Bokete: Web Application with Mojolicious and othersYusuke Wada
 
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)Dotan Dimet
 
Djangocon 2014 angular + django
Djangocon 2014 angular + djangoDjangocon 2014 angular + django
Djangocon 2014 angular + djangoNina Zakharenko
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsMatt Follett
 
You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011andrewnacin
 
You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)andrewnacin
 
Drupal 7 module development
Drupal 7 module developmentDrupal 7 module development
Drupal 7 module developmentAdam Kalsey
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkJeremy Kendall
 

Mais procurados (20)

RESTful web services
RESTful web servicesRESTful web services
RESTful web services
 
Mojolicious: what works and what doesn't
Mojolicious: what works and what doesn'tMojolicious: what works and what doesn't
Mojolicious: what works and what doesn't
 
Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!Mojolicious. Веб в коробке!
Mojolicious. Веб в коробке!
 
Mojolicious, real-time web framework
Mojolicious, real-time web frameworkMojolicious, real-time web framework
Mojolicious, real-time web framework
 
Keeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro frameworkKeeping it small - Getting to know the Slim PHP micro framework
Keeping it small - Getting to know the Slim PHP micro framework
 
Keeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
 
Drupal Best Practices
Drupal Best PracticesDrupal Best Practices
Drupal Best Practices
 
With a Mighty Hammer
With a Mighty HammerWith a Mighty Hammer
With a Mighty Hammer
 
Inside Bokete: Web Application with Mojolicious and others
Inside Bokete:  Web Application with Mojolicious and othersInside Bokete:  Web Application with Mojolicious and others
Inside Bokete: Web Application with Mojolicious and others
 
Django Heresies
Django HeresiesDjango Heresies
Django Heresies
 
Developing apps using Perl
Developing apps using PerlDeveloping apps using Perl
Developing apps using Perl
 
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)
 
Djangocon 2014 angular + django
Djangocon 2014 angular + djangoDjangocon 2014 angular + django
Djangocon 2014 angular + django
 
Perl: Hate it for the Right Reasons
Perl: Hate it for the Right ReasonsPerl: Hate it for the Right Reasons
Perl: Hate it for the Right Reasons
 
You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011You Don't Know Query - WordCamp Portland 2011
You Don't Know Query - WordCamp Portland 2011
 
You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)You Don't Know Query (WordCamp Netherlands 2012)
You Don't Know Query (WordCamp Netherlands 2012)
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Drupal 7 module development
Drupal 7 module developmentDrupal 7 module development
Drupal 7 module development
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
Keeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
 

Destaque

Writing your Third Plugin
Writing your Third PluginWriting your Third Plugin
Writing your Third PluginJustin Ryan
 
So, you want to be a plugin developer?
So, you want to be a plugin developer?So, you want to be a plugin developer?
So, you want to be a plugin developer?ylefebvre
 
The Open-source Eclipse Plugin for Force.com Development, Summer ‘14
The Open-source Eclipse Plugin for Force.com Development, Summer ‘14The Open-source Eclipse Plugin for Force.com Development, Summer ‘14
The Open-source Eclipse Plugin for Force.com Development, Summer ‘14Salesforce Developers
 
A Simple Plugin Architecture for Wicket
A Simple Plugin Architecture for WicketA Simple Plugin Architecture for Wicket
A Simple Plugin Architecture for Wicketnielsvk
 
Building an Eclipse plugin to recommend changes to developers
Building an Eclipse plugin to recommend changes to developersBuilding an Eclipse plugin to recommend changes to developers
Building an Eclipse plugin to recommend changes to developerskim.mens
 
Jumping Into WordPress Plugin Programming
Jumping Into WordPress Plugin ProgrammingJumping Into WordPress Plugin Programming
Jumping Into WordPress Plugin ProgrammingDougal Campbell
 
An easy guide to Plugin Development
An easy guide to Plugin DevelopmentAn easy guide to Plugin Development
An easy guide to Plugin DevelopmentShinichi Nishikawa
 
Eclipse Overview
Eclipse Overview Eclipse Overview
Eclipse Overview Lars Vogel
 
Building GPE: What We Learned
Building GPE: What We LearnedBuilding GPE: What We Learned
Building GPE: What We Learnedrajeevdayal
 
Configuration as Code: The Job DSL Plugin
Configuration as Code: The Job DSL PluginConfiguration as Code: The Job DSL Plugin
Configuration as Code: The Job DSL PluginDaniel Spilker
 
Creating a Plug-In Architecture
Creating a Plug-In ArchitectureCreating a Plug-In Architecture
Creating a Plug-In Architectureondrejbalas
 

Destaque (11)

Writing your Third Plugin
Writing your Third PluginWriting your Third Plugin
Writing your Third Plugin
 
So, you want to be a plugin developer?
So, you want to be a plugin developer?So, you want to be a plugin developer?
So, you want to be a plugin developer?
 
The Open-source Eclipse Plugin for Force.com Development, Summer ‘14
The Open-source Eclipse Plugin for Force.com Development, Summer ‘14The Open-source Eclipse Plugin for Force.com Development, Summer ‘14
The Open-source Eclipse Plugin for Force.com Development, Summer ‘14
 
A Simple Plugin Architecture for Wicket
A Simple Plugin Architecture for WicketA Simple Plugin Architecture for Wicket
A Simple Plugin Architecture for Wicket
 
Building an Eclipse plugin to recommend changes to developers
Building an Eclipse plugin to recommend changes to developersBuilding an Eclipse plugin to recommend changes to developers
Building an Eclipse plugin to recommend changes to developers
 
Jumping Into WordPress Plugin Programming
Jumping Into WordPress Plugin ProgrammingJumping Into WordPress Plugin Programming
Jumping Into WordPress Plugin Programming
 
An easy guide to Plugin Development
An easy guide to Plugin DevelopmentAn easy guide to Plugin Development
An easy guide to Plugin Development
 
Eclipse Overview
Eclipse Overview Eclipse Overview
Eclipse Overview
 
Building GPE: What We Learned
Building GPE: What We LearnedBuilding GPE: What We Learned
Building GPE: What We Learned
 
Configuration as Code: The Job DSL Plugin
Configuration as Code: The Job DSL PluginConfiguration as Code: The Job DSL Plugin
Configuration as Code: The Job DSL Plugin
 
Creating a Plug-In Architecture
Creating a Plug-In ArchitectureCreating a Plug-In Architecture
Creating a Plug-In Architecture
 

Semelhante a jQuery Plugin Creation

Your Library Sucks, and why you should use it.
Your Library Sucks, and why you should use it.Your Library Sucks, and why you should use it.
Your Library Sucks, and why you should use it.Peter Higgins
 
10 Catalyst Tips
10 Catalyst Tips10 Catalyst Tips
10 Catalyst TipsJay Shirley
 
Javascript quiz. Questions to ask when recruiting developers.
Javascript quiz. Questions to ask when recruiting developers.Javascript quiz. Questions to ask when recruiting developers.
Javascript quiz. Questions to ask when recruiting developers.Alberto Naranjo
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?Christophe Porteneuve
 
Django’s nasal passage
Django’s nasal passageDjango’s nasal passage
Django’s nasal passageErik Rose
 
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for PerformancejQuery Anti-Patterns for Performance
jQuery Anti-Patterns for PerformanceAndrás Kovács
 
jQuery Internals + Cool Stuff
jQuery Internals + Cool StuffjQuery Internals + Cool Stuff
jQuery Internals + Cool Stuffjeresig
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript FunctionsColin DeCarlo
 
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesEffective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesNaresha K
 
Quality Use Of Plugin
Quality Use Of PluginQuality Use Of Plugin
Quality Use Of PluginYasuo Harada
 
Feature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterFeature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterStephen Young
 
JavaScript, React Native and Performance at react-europe 2016
JavaScript, React Native and Performance at react-europe 2016JavaScript, React Native and Performance at react-europe 2016
JavaScript, React Native and Performance at react-europe 2016Tadeu Zagallo
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptVisual Engineering
 
Perl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsanePerl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsaneRicardo Signes
 

Semelhante a jQuery Plugin Creation (20)

Your Library Sucks, and why you should use it.
Your Library Sucks, and why you should use it.Your Library Sucks, and why you should use it.
Your Library Sucks, and why you should use it.
 
Unit Testing Lots of Perl
Unit Testing Lots of PerlUnit Testing Lots of Perl
Unit Testing Lots of Perl
 
Introduction to Domain-Driven Design
Introduction to Domain-Driven DesignIntroduction to Domain-Driven Design
Introduction to Domain-Driven Design
 
SPL, not a bridge too far
SPL, not a bridge too farSPL, not a bridge too far
SPL, not a bridge too far
 
10 Catalyst Tips
10 Catalyst Tips10 Catalyst Tips
10 Catalyst Tips
 
Javascript quiz. Questions to ask when recruiting developers.
Javascript quiz. Questions to ask when recruiting developers.Javascript quiz. Questions to ask when recruiting developers.
Javascript quiz. Questions to ask when recruiting developers.
 
What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?What's up with Prototype and script.aculo.us?
What's up with Prototype and script.aculo.us?
 
Django’s nasal passage
Django’s nasal passageDjango’s nasal passage
Django’s nasal passage
 
Bioinformatica p4-io
Bioinformatica p4-ioBioinformatica p4-io
Bioinformatica p4-io
 
Goodparts
GoodpartsGoodparts
Goodparts
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 
jQuery Anti-Patterns for Performance
jQuery Anti-Patterns for PerformancejQuery Anti-Patterns for Performance
jQuery Anti-Patterns for Performance
 
jQuery Internals + Cool Stuff
jQuery Internals + Cool StuffjQuery Internals + Cool Stuff
jQuery Internals + Cool Stuff
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
 
Effective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good PracticesEffective Java with Groovy - How Language Influences Adoption of Good Practices
Effective Java with Groovy - How Language Influences Adoption of Good Practices
 
Quality Use Of Plugin
Quality Use Of PluginQuality Use Of Plugin
Quality Use Of Plugin
 
Feature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them BetterFeature Flags Are Flawed: Let's Make Them Better
Feature Flags Are Flawed: Let's Make Them Better
 
JavaScript, React Native and Performance at react-europe 2016
JavaScript, React Native and Performance at react-europe 2016JavaScript, React Native and Performance at react-europe 2016
JavaScript, React Native and Performance at react-europe 2016
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Perl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally InsanePerl 5.10 for People Who Aren't Totally Insane
Perl 5.10 for People Who Aren't Totally Insane
 

Último

Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1DianaGray10
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDELiveplex
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfDaniel Santiago Silva Capera
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxGDSC PJATK
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1DianaGray10
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopBachir Benyammi
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URLRuncy Oommen
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintMahmoud Rabie
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 

Último (20)

Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1Secure your environment with UiPath and CyberArk technologies - Session 1
Secure your environment with UiPath and CyberArk technologies - Session 1
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdfIaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
IaC & GitOps in a Nutshell - a FridayInANuthshell Episode.pdf
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptx
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 Workshop
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
Designing A Time bound resource download URL
Designing A Time bound resource download URLDesigning A Time bound resource download URL
Designing A Time bound resource download URL
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
201610817 - edge part1
201610817 - edge part1201610817 - edge part1
201610817 - edge part1
 
Empowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership BlueprintEmpowering Africa's Next Generation: The AI Leadership Blueprint
Empowering Africa's Next Generation: The AI Leadership Blueprint
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 

jQuery Plugin Creation

  • 1. BEN ALMAN benalman.com @cowboy JQUERY PLUGIN CREATION organization, generalization, minification, optimization, gratification 'jquery plugin cre: organiz, generaliz, minific, optimiz, gratific'.replace( /([:,]|$)/g, 'ation$1' );
  • 2. A FEW STYLE BASICS
  • 4. WHITE SPACE Tabs vs. Spaces
  • 5. WHITE SPACE Tabs vs. Spaces
  • 6. WHITE SPACE Tabs vs. Spaces Less Crowding
  • 7. WHITE SPACE Tabs vs. Spaces Less Crowding
  • 8. COMMENTS Funny can be good, just don’t go overboard.
  • 10. VARIABLES Let them breathe! Don’t Obfuscate (not yet, at least)
  • 11. A FEW STYLE BASICS Step back and take a look. Is your code readable? If it isn’t now, it certainly won’t be in six months.
  • 14. SINGLETON Everything is public.. Good or Bad?
  • 15. SINGLETON Everything is public.. Good or Bad? Do we really want to expose the “pluralize” method? Does the user want or need this? Do we really want to expose the “things” property? What if the user tries to set it to -100?
  • 17. CLOSURES Remember this? Banging your head on the table for like, two hours?
  • 18. CLOSURES Remember this? Banging your head on the table Why do they all alert 10?! for like, two hours?
  • 19. CLOSURES Aha! A Closure. (thanks, Google)
  • 20. CLOSURES OMG!! Aha! A Closure. Unicorns & (thanks, Google) Rainbows!!
  • 21. CLOSURES Take Aha! A Closure. your (thanks, Google) pick
  • 22. OK. Back to the the Singleton...
  • 23. SINGLETON Everything is public.. Good or Bad? Do we really want to expose the “pluralize” method? Does the user want or need this? Do we really want to expose the “things” property? What if the user tries to set it to -100?
  • 24. SINGLETON Object Literal (in a Closure)
  • 25. JQUERY PLUGIN The basics
  • 26. JQUERY PLUGIN Closure?
  • 27. JQUERY PLUGIN Closure? Maybe, whatever.
  • 28. JQUERY PLUGIN Closure?
  • 29. JQUERY PLUGIN Closure? Yes!
  • 30. JQUERY PLUGIN $.fn.extend "Extends the jQuery element set to provide new methods"
  • 32. JQUERY PLUGIN Individual functions: Less indentation
  • 33. JQUERY PLUGIN Individual functions: Less indentation No pesky commas ( IE)
  • 34. JQUERY PLUGIN Should “lengthen” even be public?
  • 35. JQUERY PLUGIN Should “lengthen” even be public? Probably not.
  • 36. JQUERY PLUGIN Should “lengthen” even be public? Probably not.
  • 37. JQUERY PLUGIN Great, we made a plugin!
  • 38. JQUERY PLUGIN Great, we made a plugin! But can we make it better?
  • 40. JQUERY PLUGIN Let’s generalize!
  • 41. JQUERY PLUGIN Holy crap!
  • 42. JQUERY PLUGIN $.longUrl - more flexible
  • 43. JQUERY PLUGIN $.longUrl - more flexible $.fn.longUrl uses it internally
  • 45. JQUERY PLUGIN Generalized!
  • 52. JQUERY PLUGIN Unminified
  • 53. JQUERY PLUGIN Minified
  • 55. JQUERY PLUGIN Helping the YUI Compressor “bleh”
  • 56. JQUERY PLUGIN Helping the YUI Compressor Objects and references “bleh”
  • 57. JQUERY PLUGIN Helping the YUI Compressor Objects and references “bleh”
  • 58. JQUERY PLUGIN Helping the YUI Compressor Objects and references p_longUrl will be munged
  • 59. right on. JQUERY PLUGIN Helping the YUI Compressor Objects and references p_longUrl will be munged
  • 60. JQUERY PLUGIN Helping the YUI Compressor Objects and Strings
  • 61. neat. JQUERY PLUGIN Helping the YUI Compressor Objects and Strings
  • 62. JQUERY PLUGIN Helping the YUI Compressor Objects and Strings longUrl will be munged
  • 63. JQUERY PLUGIN Helping the YUI Compressor Objects and Strings Yes, I’m insane.
  • 64. JQUERY PLUGIN Helping the YUI Compressor Arrays and Strings
  • 65. JQUERY PLUGIN Helping the YUI Compressor Arrays and Strings 33 chars saved
  • 66. JQUERY PLUGIN Helping the YUI Compressor Arrays and Strings 33 chars saved (in this example)
  • 69. JQUERY PLUGIN Avoid unnecessary overhead! Save a kitten. Optimize.
  • 70. JQUERY PLUGIN Avoid unnecessary overhead! Save a kitten. Optimize.
  • 71. AVOID UNNECESSARY OVERHEAD! This stuff does NOT belong in here!
  • 72. ONE FINAL EXAMPLE (function($) { '$:nomunge'; // Used by YUI compressor. var url_regexp, tag_attributes = {}, // A few constants. undefined, window = this, TRUE = true, FALSE = false, has_onhashchange = 'onhashchange' in window, // Some convenient shortcuts. aps = Array.prototype.slice, loc = document.location, // Internal plugin method references. p_urlTagAttrList, p_urlInternalHost, p_urlInternalRegExp, p_isUrlInternal, p_isUrlExternal, p_urlFilter, p_urlFilterSelector, p_setFragment, // Reused internal strings. str_urlInternal = 'urlInternal', str_urlExternal = 'urlExternal', str_queryString = 'queryString', str_fragment = 'fragment', str_update = 'update', str_passQueryString = 'passQueryString', str_passFragment = 'passFragment', str_fragmentChange = 'fragmentChange', str_hashchange = 'hashchange.' + str_fragmentChange, // fragmentChange event handler timeout_id, last_fragment;
  • 73. ONE FINAL EXAMPLE // A few commonly used bits, broken out to help reduce minified file size. function is_string( arg ) { return typeof arg === 'string'; }; function is_object( arg ) { return typeof arg === 'object'; }; function curry() { var args = aps.call( arguments ), func = args.shift(); return function() { return func.apply( this, args.concat( aps.call( arguments ) ) ); }; }; // Work-around for an annoying Firefox bug where document.location.hash gets // urldecoded by default. function get_fragment() { return loc.href.replace( /^[^#]*#?/, '' ); }; // Method: jQuery.urlTagAttrList // // Get the internal "Default URL attribute per tag" list, or augment the list // with additional tag-attribute pairs, in case the defaults are insufficient. // // This list contains the default attributes for the <jQuery.fn.urlInternal> // and <jQuery.fn.urlExternal> methods, as well as the <:urlInternal> and // <:urlExternal> selector filters, to determine which URL will be tested for // internal- or external-ness. In the <jQuery.fn.queryString>, // <jQuery.fn.fragment>, <jQuery.fn.passQueryString> and // <jQuery.fn.passFragment> methods, this list is used to determine which URL // will be modified. // // Default List: //
  • 74. ONE FINAL EXAMPLE function p_params( fragment_mode, arg0, arg1, arg2 ) { var params; if ( is_string(arg1) || is_object(arg1) ) { // Build URL. return build_url( arg0, arg1, arg2, fragment_mode ); } else if ( is_object(arg0) ) { // Serialize. return $.param( arg0 ); } else if ( is_string(arg0) ) { // Deserialize. return deserialize( arg0, arg1, fragment_mode ); } else { // Deserialize document query string / fragment. params = fragment_mode ? get_fragment() : loc.search; return deserialize( params, arg0, fragment_mode ); } }; $[str_queryString] = curry( p_params, 0 ); $[str_fragment] = curry( p_params, 1 ); function p_fn_params() { var attr, params, merge_mode, args = aps.call( arguments ), fragment_mode = args.shift(); if ( is_string(args[1]) || is_object(args[1]) ) { attr = args.shift(); } params = args.shift(); merge_mode = args.shift();
  • 75. ONE FINAL EXAMPLE /* * URL Utils - v1.11 - 9/10/2009 * http://benalman.com/ * * Copyright (c) 2009 "Cowboy" Ben Alman * Licensed under the MIT license * http://benalman.com/about/license/ */ (function($){var M,q={},z,i=this,u=true,J=false,F="onhashchange" in i,a=Array.prototype.slice,j=document.location,E,d,b,x,v,e,C,I,p="urlInternal",L="urlExternal",y="queryString",G="fragment",H="update",f= "passQueryString",w="passFragment",c="fragmentChange",o="hashchange."+c,h,g;function B(O){return typeof O==="string"}function l(O) {return typeof O==="object"}function m(){var O=a.call(arguments),P=O.shift();return function(){return P.apply(this,O.concat(a.call(arguments)))}}function k(){return j.href.replace(/^[^#]*#?/,"")}$.urlTagAttrList=E=function(O){return $.extend(q,O)};E({a:"href",img:"src",form:"action",base:"href",script:"src",iframe:"src",link:"href"});function r(O){var P=O.nodeName;return P?q[P.toLowerCase()]:""}$.urlInternalHost=d=function(Q){Q=Q?"(?:"+Q+".)?":"";var P=new RegExp("^"+Q +"(.*)","i"),O="^"+j.protocol+"//"+j.hostname.replace(P,Q+"$1")+(j.port?":"+j.port:"")+"/";return b(O)}; $.urlInternalRegExp=b=function(O){if(O){M=B(O)?new RegExp(O,"i"):O}return M};d("www");$.isUrlInternal=x=function(O){if(!O){return z}if(M.test(O)){return u}if(/^https?:///i.test(O)){return J}if(/^(?:#|[a-zd.-]+:)/i.test(O)){return z}return u}; $.isUrlExternal=v=function(O){var P=x(O);return typeof P==="boolean"?!P:P};e=function(P,O){return this.filter(":"+P+(O?"("+O+")":""))}; $.fn[p]=m(e,p);$.fn[L]=m(e,L);C=function(S,R,Q,P){var O=P[3]||r(R);return O?!!S($(R).attr(O)):J};$.expr[":"][p]=m(C,x);$.expr[":"] [L]=m(C,v);function K(Q,R,P,O){var S;if(B(P)||l(P)){return n(R,P,O,Q)}else{if(l(R)){return $.param(R)}else{if(B(R)){return D(R,P,Q)}else{S=Q?k():j.search;return D(S,R,Q)}}}}$[y]=m(K,0);$[G]=m(K,1);function N(){var O,S,R,Q=a.call(arguments),P=Q.shift();if(B(Q[1])||l(Q[1])){O=Q.shift()}S=Q.shift();R=Q.shift();return this.each(function(){var V=$ (this),T=O||r(this),U=T&&V.attr(T)||"";U=K(P,U,S,R);V.attr(T,U)})}$.fn[y]=m(N,0);$.fn[G]=m(N,1);function A(){var Q=a.call(arguments),P=Q.shift(),O=Q.shift(),R=K(P);if($.isFunction(Q[0])){R=Q.shift()(R)}else{if($.isArray(Q[0])) {$.each(Q.shift(),function(T,S){delete R[S]})}}return K(P,O,R,Q.shift())}$[f]=m(A,0);$[w]=m(A,1);function t(){var O,Q=a.call(arguments),P=Q.shift();if(B(Q[0])){O=Q.shift()}return this.each(function(){var T=$(this),R=O|| r(this),S=R&&T.attr(R)||"";S=A.apply(this,[P,S].concat(Q));T.attr(R,S)})}$.fn[f]=m(t,0);$.fn[w]=m(t,1);function D(U,T,Q){var P,W,S,V={},R={"null":null,"true":u,"false":J},O=decodeURIComponent,X=Q?/^.*[#]/:/^.*[?]|#.*$/g;U=U.replace(X,"").replace(/+/g," ").split("&");while(U.length){P=U.shift().split("=");W=O(P[0]);if(P.length===2){S=O(P[1]);if(T){if(S&&!isNaN(S)) {S=Number(S)}else{if(S==="undefined"){S=z}else{if(R[S]!==z){S=R[S]}}}}if($.isArray(V[W])){V[W].push(S)}else{if(V[W]!==z) {V[W]=[V[W],S]}else{V[W]=S}}}else{if(W){V[W]=T?z:""}}}return V}function n(O,Q,T,P){var U,W=P?/^([^#]*)[#]?(.*)$/:/^([^#?]*)[?]?([^#]*) (#?.*)/,S=O.match(W),V=D(S[2],0,P),R=S[3]||"";if(B(Q)){Q=D(Q,0,P)}if(T===2){U=Q}else{if(T===1){U=$.extend({},Q,V)}else{U= $.extend({},V,Q)}}U=$.param(U);return S[1]+(P?"#":U||!S[1]?"?":"")+U+R}$.setFragment=I=function(P,O){var Q=l(P)?K(u,P):(P||"").replace(/ ^#/,"");Q=P?n("#"+k(),"#"+Q,O,1):"#";j.href=j.href.replace(/#.*$/,"")+Q};$[c]=function(O){if(O===u){O=100}function P(){var R= $.Event(c);R[G]=k();$(document).trigger(R)}F&&$(i).unbind(o);h&&clearTimeout(h);h=null;if(typeof O==="number"){if(F){$ (i).bind(o,P)}else{g=k();if($.isFunction(s)){s=s()}(function Q(){var S=k(),R=s[G](g);if(S!==g){s[H](S,R);g=S;P()}else{if(R!==g){I(R, 2)}}h=setTimeout(Q,O<0?0:O)})()}}};function s(){var O,P=$.browser,Q={};Q[H]=Q[G]=function(R){return R};if(P.msie&&P.version<8) {Q[H]=function(T,R){var S=O.document;if(T!==R){S.open();S.close();S.location.hash="#"+T}};Q[G]=function(){return O.document.location.hash.replace(/^#/,"")};O=$("<iframe/>").hide().appendTo("body").get(0).contentWindow;Q[H](k())}return Q}})(jQuery);
  • 77. GRATIFICATION Clean, simple API
  • 78. GRATIFICATION Clean, simple API Generalized code makes your life easier
  • 79. GRATIFICATION Clean, simple API Generalized code makes your life easier Minified code makes it smaller
  • 80. GRATIFICATION Clean, simple API Generalized code makes your life easier Minified code makes it smaller Efficient code makes it work faster
  • 81. GRATIFICATION Clean, simple API Generalized code makes your life easier Minified code makes it smaller Efficient code makes it work faster (and people complain less)

Notas do Editor

  1. about me: * my name is ben alman * i work at a startup just down the road, in watertown, ma called pangea media. we do a lot of cool things in the online quiz space. i&amp;#x2019;ve developed a pretty cool flash quiz widget there, created a javascript myspace application framework, co-designed a highly generalized CMS, and am now working on some twitter stuff (among other things) * in my own time, i play the bass guitar, write and record music, i&amp;#x2019;m really into photography.. oh yeah, and i help out in the #jquery IRC channel and have written a lot of jquery plugins (feel free to check them out on my site, benalman.com, there&amp;#x2019;s something there for everyone, i think) i&amp;#x2019;ve looked at a lot of jquery code and plugins, between the noobs in IRC and the actual legitimate plugins being authored by jquery community members.. and while i see some great code out there, i see a lot of room for improvement. and a quick note, i might look like i&amp;#x2019;m reading a lot of this text off my screen. that&amp;#x2019;s because i AM. i&amp;#x2019;ve found that if i don&amp;#x2019;t have a script to read from, i tend to ramble. and you don&amp;#x2019;t want to be around me when i start rambling. seriously, once i get started, i&amp;#x2019;ll never stop.
  2. so i want to start off with a few style basics. first of all, style is personal. there is no right or wrong, really. - even though sometimes it feels like there is while i don&amp;#x2019;t expect anyone to just do everything i say, i really want to get you guys thinking about developing your own style if you haven&amp;#x2019;t already. you want to do what you&amp;#x2019;re doing for a reason, hopefully a good one. and above all, be consistent.
  3. so, white space. everyone seems to have a differing opinion of how to handle white space.
  4. crockford (and jslint of course) recommend 4 spaces. i see that a lot. most people use tabs. i use 2 spaces. why? well, i was forced to by a bunch of surly &amp;#x201C;code-in-emacs-in-a-shell&amp;#x201D; perl developers, but once i got used to it, i found that i really liked it.
  5. why? well, it keeps your code much more compact, and when someone previews that code in a browser (which is almost always how they look at it for the first time, anyways) it might actually fit in there without a horizontal scrollbar. if someone can find a way to configure firefox to display tabs at 2 characters wide, maybe i&amp;#x2019;ll reconsider. maybe. it&amp;#x2019;s not a big deal, it&amp;#x2019;s just personal preference. but all i can say is anything that increases readability is a good thing.
  6. another thing, don&apos;t crowd your arguments! sometimes less is more, but with whitespace, more is usually more (i mean, up to a limit of course). also, it&amp;#x2019;s really hard to read code when there are no linebreaks separating &amp;#x201C;chunks&amp;#x201D; of code.
  7. isn&amp;#x2019;t that better? readability is much improved.
  8. and write useful comments. you don&amp;#x2019;t have to write a book, just think about your target audience. the people who may be using your plugin, or who might want to learn from your plugin. many of them need all the help they can get.. so, help them.
  9. and when you define many vars in a single &amp;#x201C;var&amp;#x201D; statement (like yui compressor recommends), you gain nothing by putting them all on one line. give them some breathing room. comment them if you feel it&amp;#x2019;s helpful.
  10. and don&apos;t obfuscate vars. that, plus whitespace, and a few other things will all be taken care of when you minify your code.
  11. Step back and take a look. Is your code readable? cuz if it isn&amp;#x2019;t now, it certainly won&amp;#x2019;t be in six months. and what about when anyone else looks at it? there are a lot of other style things to keep in mind. like maybe don&amp;#x2019;t go totally overboard with ternary operators, and be sure to use curly braces around single-statement conditional blocks. well, unless you know what you&amp;#x2019;re doing. again, it&amp;#x2019;s a matter of personal style. start simple, make sure things work, and optimize (and micro-optimize) from there. optimize last.
  12. so i&amp;#x2019;ll start off with some basics. most of the next few minutes shouldn&amp;#x2019;t come as a surprise to anyone, but i&amp;#x2019;m going to cover a few things just to make sure people understand.
  13. this is a very simple singleton. a singleton is not something that you can have multiple instances of, there&amp;#x2019;s just one of them. and i&amp;#x2019;m only really showing this example to illustrate a point. you need to consider your code&amp;#x2019;s API. what methods and properties do you want exposed to the end-user? if the end-user is you, and you trust yourself, which hopefully you do, maybe it doesn&amp;#x2019;t matter but while we have two useful public methods, `setThings` and `getThings` here ...
  14. we also have a relatively useless public method `pluralize` as well as a potentially dangerous public property `things`.
  15. Do we really want to expose the &amp;#x201C;pluralize&amp;#x201D; method? Does the user want or need this? Do we really want to expose the &amp;#x201C;things&amp;#x201D; property? What if the user tries to set it to -100? while this is a very simple way to namespace a collection of methods (and properties), sometimes less isn&apos;t more.. for example, the uber-simplicity here results in a complete lack of privacy. again, if you&amp;#x2019;re very trusting, you don&apos;t necessarily need privacy.. but in this example, if a user were to set simpleSingleton.things directly, they would be able to set it to a negative value, which we expressly don&apos;t want! (that&amp;#x2019;s why we have the `setThings` setter method sanitizing the input) again, think about your code&amp;#x2019;s api. do you want users to use the `pluralize` method? probably not. and honestly, exposing it like this just gives you more to have to document.
  16. ok. many or most of you already know about closures, but i&amp;#x2019;m going to touch on them briefly to make sure everyone is familiar with their concept and implementation i don&amp;#x2019;t really want to spend much time on this part of the presentation, so if you don&amp;#x2019;t understand what a closure is after my explanation, pretend like you do understand for the time being, and we can talk about it afterwards
  17. where might you have encountered a closure before? well, every function, when invoked, creates a closure. but let&apos;s look at another example.
  18. alright. so in this example, all the links alert 10. why? because inside the onclick event handler function, i is a REFERENCE to the loop counter. and since it&apos;s just a reference to that variable, as the variable is incremented, `i` just references that changed value. after running the loop, if you were to set i = 100, they&apos;d all alert 100. this is no good!
  19. what&apos;s the fix? create a closure!
  20. hallelujah! the wrapper function expression is invoked immediately, and the current value of `i` is passed into the function as an argument, to be used internally. since there&apos;s now an `i` inside the function, the alert sees that `i` which is &amp;#x2018;locked in&amp;#x2019; at the value the function was invoked with, even though the external `i` value changes, and even though an internal function is returned. because any functions defined inside a closure have access to all variables defined in that closure, the onclick will alert the correct index.
  21. and an alternative take on the closure is to just wrap the entire onclick definition in a function, and invoke it immediately. this basically does the same thing as the previous example, but in my opinion is a little bit less confusing looking. `i` is still locked in, but in a slightly different way. so, a closure allows you to create a local scope in which private variables and functions can be defined, so that they don&amp;#x2019;t need to be publicly accessible (and can&amp;#x2019;t be.. unless you&amp;#x2019;re doing some crazy eval stuff .. we won&amp;#x2019;t get into that)
  22. ok, back to the singleton.
  23. so, let&amp;#x2019;s solve our little dilemma by using a closure
  24. alright. so, here&apos;s the basic singleton, but this time using a closure for privacy. the surrounding function expression is invoked immediately, creating a closure, and returns an object reference that contains 2 methods. just like in the previous closure examples, things and pluralize are private and available to all other functions that are defined inside the closure, namely the `setThings` and `getThings` methods. since things and pluralize are now private, they aren&apos;t exposed outside the scope of the closure and are thus inaccessible to the outside. also, a side benefit here is that because everything is inside a closure, private references can be minified + obfuscated, saving space (more about that later).
  25. so onto some more interesting stuff (maybe) here we see `unwrap`, a very simple jquery plugin i wrote (that actually looks like it will be included in 1.3.3, the patch is submitted, at least.. someone remind me to email resig about that). just be sure when writing a jQuery plugin without a closure that you use jQuery instead of $ to avoid global conflict issues, when jQuery is loaded via &amp;#x201C;noconflict&amp;#x201D;
  26. so, do we need a closure here?
  27. maybe. whatever. i mean, what&amp;#x2019;s the benefit? in this instance, well.. none, other than being able to use $ throughout your code instead of jQuery. with very simple code, you might not need a closure. i almost always use one, because I often don&apos;t know in advance when the plugin will need a closure or not, either way, less global pollution is never a bad thing.. and i like to use the $. it looks pretty.
  28. here&apos;s a slightly more complicated example. let&amp;#x2019;s say that we have this longUrl plugin. you call it on some number of &amp;#x2018;a&amp;#x2019; elements, and it iterates over them, passing any short urls to an external service that returns the long url that short url redirects to (which it then sets as that element&amp;#x2019;s title attribute). because we want to be &amp;#x201C;smart&amp;#x201D; about things, we store all urls returned in a local cache so that if we encounter them again, we don&amp;#x2019;t have to re-fetch that url! see the closure? it&amp;#x2019;s there.. but do we really want to use a closure here?
  29. the answer is yes! why? well, a closure is necessary here because an internal cache of urls is maintained. if you didn&apos;t have the closure, you&amp;#x2019;d have to either store the data in a global variable, or on jQuery somewhere, but then it might conflict with other things. unlikely, but possible. caching things in your plugin&apos;s closure will help avoid conflicts like these. and as i mentioned before, it will help in minification later on
  30. now, we&amp;#x2019;re working with a very similar organization to our singleton-in-a-closure from before. but what is $.fn? it&amp;#x2019;s an alias to jQuery.prototype. like any prototype, any method you attach to that prototype ($.fn) not only appears on every jQuery object, but inside those methods, `this` refers to that object. pretty cool. and what does $.fn.extend do? From the docs, &quot;Extends the jQuery element set to provide new methods&quot;, just pass in an object full-o-methods, and each method in that object is attached to $.fn - just like defining those methods individually, but all in one go.
  31. or you could do it this way, with individual method definitions instead of $.fn.extend. it&amp;#x2019;s not a big deal here. it&apos;s up to you how you decide to go about organizing your methods. that being said..
  32. one of the reasons i prefer individual function definitions on $.fn vs using $.fn.extend with an object is because it results in one less level of indentation, which i find lends itself to more readable code.
  33. another thing is those pesky trailing commas that ie loves so much. i mentioned this to someone recently and they told me to &quot;learn to code&quot;, but i beg to differ. when you define your functions individually, the commas become one less thing to worry about.. especially if you&apos;re really particular and are constantly reorganizing and refactoring code (cough). also, defining functions separately actually allows you to save some space when minifying, using private references (more on that in a moment)
  34. ok, so let&amp;#x2019;s think about the plugin api we&amp;#x2019;ve created for a second. we&amp;#x2019;ve got 2 public methods. $.fn.longUrl is useful.. but should $.fn.lengthen even be public?
  35. probably not. perhaps $.fn.lengthen isn&apos;t the most useful function to have public. You don&apos;t really want people calling it on any collection of elements, it&apos;s not going to help them. and you don&amp;#x2019;t want your `longUrl` plugin to conflict with someone else&amp;#x2019;s `lengthen` plugin if it&amp;#x2019;s not really necessary. you could call it `longUrlLengthen` if you wanted to.. but `lengthen` is really just a convenience method for this plugin and should really be private, like the url cache
  36. so, ok. just like the cache var, lengthen is now defined as private. and now our plugin api is super-simple, just one method, $.fn.longUrl.
  37. so, we now have a working plugin so, we&apos;re done, right? (keep in mind these examples are simplified way down from the actual plugin, and are untested in their current incarnation)
  38. well, we could be done. but why not put in just a little extra effort and make it even better? often, with that little extra effort, you can take code originally intended for one specific use and generalize it. by generalizing, you allow your method or methods to be used in a valid, yet different way than was originally intended. for example.. this plugin will only lengthen URLs in elements with an href attribute. which is pretty much just &quot;a&quot; tags. what if we wanted to lengthen a short url typed into a text field?
  39. so yeah, let&apos;s generalize a little.
  40. alright. how can we generalize this? well, why not make a more generic $.longUrl function that will operate on any short url string passed in and return the long url (via callback, of course, because the $.getJSON request it uses is asynchronous)
  41. so, take a look at this refactored code. here, much of the code that existed in $.fn.longUrl has been broken out into a completely separate $.longUrl method. this method is useful as a general public method for &quot;getting a long url from a short url&quot; so it isn&apos;t kept private. it could be private, but it&apos;s useful, so let&amp;#x2019;s keep it exposed!
  42. now, this new generic $.longUrl method can be used anytime, anywhere, by anyone. and since this more generalized method is called by $.fn.longUrl...
  43. ...that method can be made much simpler, reducing any possible redundant code. and it&apos;s not just our internal $.fn.longUrl method that can benefit from this - any other code can utilize $.longUrl now. also: notice that the private lengthen function has been removed. it was maybe questionable that it even existed as a separate function in the first place, since it was so simple.. but had it been more complex, of course you&apos;d want to break it out into its own function. since the generification of the plugin simplified $.fn.longUrl, this code only existed in one place, and having a separate private function became unnecessary. still, you don&amp;#x2019;t want to duplicate code.
  44. no, really. i mean it. if you do the same thing twice, break it out into a function. if you do very similar things in different areas, see if you can find a way to break them out into a single function that works contextually, or accepts an argument. this probably falls under &amp;#x201C;optimization&amp;#x201D; or &amp;#x201C;don&amp;#x2019;t be a dumbass&amp;#x201D; but since it came up, i had to talk about it
  45. ok, so we&amp;#x2019;ve got a generalized plugin. how does it feel? we&amp;#x2019;ve gone above and beyond the original &amp;#x201C;spec&amp;#x201D; for the plugin in a way that nobody can complain about, and we haven&amp;#x2019;t even really made it more complicated. well, you have slightly more documentation to write, but.. you know.
  46. and there&amp;#x2019;s a lot of ways to generalize your code. in the actual &amp;#x201C;non example&amp;#x201D; version of the plugin (that i have yet to fully generalize, actually - note the lack of a $.longUrl method) i&amp;#x2019;ve allowed the user to define an alternative callback not just for processing the `a` elements...
  47. but also an alternative callback for making the api call...
  48. as well as a few other parameters.
  49. and i&amp;#x2019;m using $.extend inside the function...
  50. to allow the user to override the default options with their own options (this is a very common way to handle options, we see it a lot) so now, let&amp;#x2019;s talk about..
  51. minification, finally. first, a word about yui compressor. like jslint, it gives you great suggestions, but it won&amp;#x2019;t tell you how to code.. so please don&amp;#x2019;t use it as a crutch. part of the style i&apos;ve developed has come from the fact that i know that i can minify my code using yui compressor to shrink it down in size. yui compressor will go beyond just removing unnecessary whitespace and semicolons, and actually &apos;munge&apos; local, private variables that it knows don&apos;t need to maintain their names, since they can only be used inside the closure in which they are defined. by &amp;#x2018;munge&amp;#x2019; i mean reduce all instances of a long variable name to something waaaaaay shorter. as long as they are ALL reduced, it all works. now, i don&amp;#x2019;t have time to cover every minification trick that i know, but that&amp;#x2019;s probably a good thing. a lot of these techniques get a bit over-the-top, and start to sacrifice readability for the few bytes they save, which isn&amp;#x2019;t a good thing. unless it is.. it all depends on your needs. in general though, readability is key.
  52. so, here&amp;#x2019;s our code, unminified
  53. aaaand.. this is what our code looks like when minified ok, that doesn&amp;#x2019;t help anyone. well, actually.. visually scanning through minified code can help you identify reused strings that are taking up a lot of space.. but still. ugleey.
  54. ok. slightly less unreadable you can see how all the private vars have been munged.
  55. but what about that $.longUrl call in the $.fn.longUrl method? in this plugin, maybe it doesn&amp;#x2019;t matter... but what about when you&amp;#x2019;re creating a much larger plugin, with many more internal but public method calls? let&amp;#x2019;s help the yui compressor make our plugin happier, without sacrificing readability too much
  56. because object properties and methods can be accessed via dot syntax or square-brackets-with-a-string syntax, it not possible for a minifier to actually munge them (like simple vars). so, if you have a lot of long object properties referenced in your code, you might end up with a lot of wasted bytes.
  57. in this example, $.longUrl is called internally just the once. where a private function would have its name munged, the `longUrl` in $.longUrl won&apos;t. now, say you had a larger plugin with a dozen internal methods that called $.longUrl many times. how can we get the file size down?
  58. ok, here&amp;#x2019;s one way..
  59. when you look at the code, you see that $.longUrl is still public, but now, there&apos;s an additional internal reference to this method that can be munged. and.. just imagine the minified file size savings if you could reduce 5 or 10 (or more) `$.whatever` calls to a single variable like `a`, `b`, or `c`. and after minification.. we saved 4 bytes! right, not really that impressive. but imagine a much larger plugin with lots of and lots of function references.
  60. and another approach...
  61. here, we&amp;#x2019;ve replaced all .longUrl with [longUrl], defining var longUrl = &apos;longUrl&apos;; in this example, we actually replace 3 .longUrl with a string reference, saving a whopping 3 bytes. but it could be more, oh yes, it could be more. it just depends on the size and scale of your plugin.
  62. and this is still pretty readable, and it can save you a not insignificant amount of space if your code reuses object properties or strings over and over (and over) again.
  63. ok, yeah, well you can do the math. i already did, but it&amp;#x2019;s clear that you don&amp;#x2019;t always want to use this technique. in the last example, we saved 3 bytes. big deal, probably not worth it. you can&amp;#x2019;t just &amp;#x201C;phone it in&amp;#x201D; here, you have to actually test and see if what you&amp;#x2019;re doing is making a difference, and determine if it&amp;#x2019;s worth it. make the change, minify, and see if the file is smaller. rinse and repeat. or you can figure it out in a generic way, and take notes like i&amp;#x2019;ve done.. but who has that kind of time?
  64. so, we&apos;re maybe getting further into the realm of &quot;is this really necessary&quot; here, but this is an example taken from modernizr, which is not a jquery plugin, but something that i worked on recently with paul irish. i took the 0.9 codebase and restructured it, getting the code down, when minified, to about 60% of the previous minified size. it was a gigantic savings.
  65. now, if you were to define this long, space-delimited string as an array (bottom), it would take up 190 chars when minified. here, as a split string, it only takes up 157 chars. not a huge savings (33 characters), but these kinds of things all add up, and since this really doesn&amp;#x2019;t make the code harder to read, it can be helpful. in fact, honestly, it&amp;#x2019;s probably easier to read as the string.
  66. again, i&amp;#x2019;m not telling you to just DO these things.. but you should consider them, because they might get you thinking about new and creative ways to code, and they might help you define your &amp;#x201C;style&amp;#x201D; sure, there&amp;#x2019;s a space savings in THIS example, but not every example will yield these benefits. a split string with any less than 6 items will cost you bytes over an array, due to the length of the method name, dot, split, parens, quotes, space, versus all the quotes and commas in the array
  67. ok. i&amp;#x2019;ve just shown an example where saving a few bytes when minified actually comes at a slight performance cost..
  68. beware: .split() will take a not-insignificant amount of time if you call it a lot, so you might not want to call this function repeatedly. in modernizr, it&amp;#x2019;s called just once, but if you needed to call a function like this multiple times, you&apos;d want to perform the `split` in your plugin&apos;s top-level closure, storing the result there, and not in the actual function you&apos;re calling multiple times. if you find that you&apos;re processing `constant` values by splitting strings or building regexes, you can save a huge amount of execution time by doing them in your plugin&apos;s top-level closure, and not in the individual methods, every time plus, then every method would have access to them!
  69. and besides, you don&amp;#x2019;t want to be responsible for all those kittens.
  70. i&amp;#x2019;m serious. Non-performant code makes Domo hungry. i have a real world example though..
  71. i recently developed the simplified message style for the os 10 IRC app, linkinus, and one of the things i needed to do was write some kind of linkification script (well, and the longUrl script), since the app doesn&amp;#x2019;t handle that. i needed a LOT of regular expressions (and i still haven&amp;#x2019;t got it completely right, but it&amp;#x2019;s pretty damn close) yeah, so, originally, these two gigantic regexps (which only really need to be built once) were getting built every time linkify was being called, on every new line of chat, because i had them in the returned function.. but when i moved them into the top-level closure, they only got built just the once. this made the code run about a billion times faster. well, no, more like 60 times faster or something. it was huge. this is what john was talking about yesterday, they just did this same thing in jquery 1.3.3 and it gave them a noticeable performance boost.
  72. here&amp;#x2019;s some code from my url utils plugin. it might look gigantic, but it provides a ton of functionality in only 4kb minified. and it can be so small because it&amp;#x2019;s very well organized internally, with lots of internal method references instead of `$.whatever` calls.
  73. i found that i was testing typeof arg === &amp;#x2018;string&amp;#x2019; or &amp;#x2018;object&amp;#x2019; enough to warrant breaking it into a separate internal, private function. and i actually defined `curry` locally because pretty much all of the functionality in the plugin is exactly the same, with very slightly different behavior between fragment and query string handling. why duplicate code unnecessarily? (if you don&amp;#x2019;t know what curry does, you can look it up)
  74. here&amp;#x2019;s an example of square-bracket-string instead of dot-methodname as well as curry. note, for the sake of the example, i&amp;#x2019;ve stripped out a lot of the comments. the full code and documentation is available online on my site. and btw, a plug, this &amp;#x201C;url utils&amp;#x201D; plugin does querystring and fragment parsing, cross-browser fragment page history, url internal / external selectors, etc..
  75. and again, the whole thing weighs in at under 4kb minified.
  76. v