<?xml version="1.0" encoding="UTF-8" ?><rss version="2.0"><channel><title>Debuggable.com - Blog</title><link>http://www.debuggable.com/</link><description /><item><title>Releasing node-mysql 2.0.0-alpha</title><link>http://www.debuggable.com/posts/releasing-node-mysql-2-0-0-alpha:4fb21c18-7f84-4e8c-a1ef-599bcbdd56cb</link><guid>http://www.debuggable.com/posts/releasing-node-mysql-2-0-0-alpha:4fb21c18-7f84-4e8c-a1ef-599bcbdd56cb</guid><description>&lt;p&gt;Today I am releasing an alpha version of &lt;a href=&quot;https://github.com/felixge/node-mysql&quot;&gt;node-mysql v2.0&lt;/a&gt;. If you are using
v0.9.x at this point, I highly encourage you to try it out, as now is your best
chance to influence the API and features of the final release.&lt;/p&gt;

&lt;p&gt;To install the new version, do:&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;
npm install mysql@2.0.0-alpha
&lt;/pre&gt;

&lt;p&gt;Then check out the &lt;a href=&quot;https://github.com/felixge/node-mysql/blob/master/Changes.md#v200-alpha-2012-05-15&quot;&gt;Upgrading Guide&lt;/a&gt; and adjust your code as needed.&lt;/p&gt;

&lt;p&gt;After that make sure to join the new &lt;a href=&quot;https://groups.google.com/forum/?fromgroups#!forum/node-mysql&quot;&gt;mailing list&lt;/a&gt; or #node-mysql IRC
channel to provide any feedback you may have.&lt;/p&gt;

&lt;p&gt;This new version comes with a few exciting improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~5x faster than v0.9.x for parsing query results&lt;/li&gt;
&lt;li&gt;Support for &lt;code&gt;pause()&lt;/code&gt; / &lt;code&gt;resume()&lt;/code&gt; (for streaming rows)&lt;/li&gt;
&lt;li&gt;Support for multiple statement queries&lt;/li&gt;
&lt;li&gt;Support for stored procedures&lt;/li&gt;
&lt;li&gt;Support for transactions&lt;/li&gt;
&lt;li&gt;Support for binary columns (as blobs)&lt;/li&gt;
&lt;li&gt;Consistent &amp;amp; well documented error handling&lt;/li&gt;
&lt;li&gt;A new Connection class that has well defined semantics (unlike the old Client class).&lt;/li&gt;
&lt;li&gt;Convenient escaping of objects / arrays that allows for simpler query construction&lt;/li&gt;
&lt;li&gt;A significantly simpler code base&lt;/li&gt;
&lt;li&gt;Many bug fixes &amp;amp; other small improvements (Closed 62 out of 66 GitHub issues)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have been working on this new version for quite some time, but only now was
able to complete the final work thanks to my amazing new sponsors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.holidayextras.co.uk/&quot;&gt;HolidayExtras&lt;/a&gt; (they are &lt;a href=&quot;http://join.holidayextras.co.uk/vacancy/senior-web-technologist/&quot;&gt;hiring&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://newscope.com/&quot;&gt;Newscope&lt;/a&gt; (they are &lt;a href=&quot;http://www.newscope.com/stellenangebote&quot;&gt;hiring&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For those of you interested in the future of v0.9.x:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There will be no v1.0 release, the way 0.9.x handles its queue and reconnect
mechanism are broken and not easily fixable without breaking BC.&lt;/li&gt;
&lt;li&gt;I will merge critical bug fixes that come with tests and don&#039;t break BC.&lt;/li&gt;
&lt;li&gt;There will be no major changes, especially features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Going forward, I also hope to find some time to write about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The new parser and what makes v2 so fast&lt;/li&gt;
&lt;li&gt;The choice of rewriting vs. refactoring (I tried both)&lt;/li&gt;
&lt;li&gt;My failed first attempt for a new parser design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;--fg&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4fb21c18-7f84-4e8c-a1ef-599bcbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Tue, 15 May 2012 09:04:24 +0000</pubDate><comments>http://www.debuggable.com/posts/releasing-node-mysql-2-0-0-alpha:4fb21c18-7f84-4e8c-a1ef-599bcbdd56cb</comments></item><item><title>How to write jQuery plugins</title><link>http://www.debuggable.com/posts/how-to-write-jquery-plugins:4f72ab2e-7310-4a74-817a-0a04cbdd56cb</link><guid>http://www.debuggable.com/posts/how-to-write-jquery-plugins:4f72ab2e-7310-4a74-817a-0a04cbdd56cb</guid><description>&lt;p&gt;&lt;a href=&quot;http://jquery.com&quot;&gt;jQuery&lt;/a&gt;, the most popular javascript library out there, is great for DOM abstraction. It allows you to encapsulate functionality into your own plugins, which
is a great way to write reusable code. However, jQuery&#039;s rules for writing plugins are very loose, which leads to different plugin development practices - some of which are pretty poor.&lt;/p&gt;

&lt;p&gt;With this article I want to provide a simple plugin development pattern that will work in many situations. If the functionality you would like to encapsulate is large and really complex, jQuery plugins are probably not what you should use in the first place.
You&#039;d rather use something like &lt;a href=&quot;http://documentcloud.github.com/backbone/&quot;&gt;BackboneJS&lt;/a&gt; or &lt;a href=&quot;http://javascriptmvc.com/docs.html#!jQuery.Controller&quot;&gt;jQuery.Controller&lt;/a&gt; in this case.&lt;/p&gt;

&lt;p&gt;If you can&#039;t or don&#039;t want to use Backbone, you might still get away with my solution ...&lt;/p&gt;

&lt;h2&gt;Starting off&lt;/h2&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$, doc, win&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;use strict&amp;quot;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// plugin code will come here&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;jQuery, document, window&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;The semi-colon before the function invocation keeps the plugin from breaking if our plugin is concatenated with other scripts that are not closed properly.&lt;/p&gt;

&lt;p&gt;&quot;use strict&quot;; puts our code into strict mode, which catches some common coding problems by throwing exceptions, prevents/throws errors when relatively &quot;unsafe&quot; actions are taken and disables Javascript features that are confusing or poorly thought out.
To read about this in detail, please check &lt;a href=&quot;http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/&quot;&gt;ECMAScript 5 Strict Mode, JSON, and More&lt;/a&gt; by John Resig.&lt;/p&gt;

&lt;p&gt;Wrapping the jQuery object into the dollar sign via a closure avoids conflicts with other libraries that also use the dollar sign as an abbreviation.
window and document are passed through as local variables rather than as globals, because this speeds up the resolution process and can be more efficiently minified.&lt;/p&gt;

&lt;h2&gt;Invoking our plugin&lt;/h2&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$, doc, win&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;use strict&amp;quot;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el &amp;nbsp;= $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;opts&lt;/span&gt; = opts;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Widget.&lt;span class=&quot;me1&quot;&gt;prototype&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;init&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; $.&lt;span class=&quot;me1&quot;&gt;fn&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;new&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;jQuery, document, window&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
$&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;#mywidget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;optionA: &lt;span class=&quot;st0&quot;&gt;&#039;a&#039;&lt;/span&gt;, optionB: &lt;span class=&quot;st0&quot;&gt;&#039;b&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;We invoke our plugin on a jQuery object or jQuery set by simply calling our widget() method on it and pass it some options.
Never forget about &quot;return this.each(function() { ... })&quot; in order to not break the chain-ability of jQuery objects.&lt;/p&gt;

&lt;p&gt;The main functionality of the plugin is encapsulated into a separate Widget class, which we instantiate for each member in our jQuery set. Now all functionality is encapsulated in these wrapper objects.
The constructor is designed to just keep track of the passed options and the DOM element that the widget was initialized on.&lt;/p&gt;

&lt;p&gt;You could also keep track of more sub-elements here to avoid having to always .find() them (think of performance) as you need them:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$, doc, win&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;use strict&amp;quot;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el &amp;nbsp; &amp;nbsp; = $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;opts&lt;/span&gt; &amp;nbsp; &amp;nbsp;= opts;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$header = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.header&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$body &amp;nbsp; = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.body&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;jQuery, document, window&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;h2&gt;Parsing options&lt;/h2&gt;

&lt;p&gt;When we invoked the plugin we passed it some options. Often you need default options that you want to extend. This is how we bring the two together in our object&#039;s init() method:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$, doc, win&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;use strict&amp;quot;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el &amp;nbsp;= $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt; = &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; optionA: &lt;span class=&quot;st0&quot;&gt;&#039;someOption&#039;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; optionB: &lt;span class=&quot;st0&quot;&gt;&#039;someOtherOption&#039;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; meta &amp;nbsp;= &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;widget-plugin-opts&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;opts&lt;/span&gt; = $.&lt;span class=&quot;me1&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt;, opts, meta&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;jQuery, document, window&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
$&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;#mywidget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;optionA: &lt;span class=&quot;st0&quot;&gt;&#039;a&#039;&lt;/span&gt;, optionB: &lt;span class=&quot;st0&quot;&gt;&#039;b&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;I like keeping the default options within the constructor of the wrapper class and not outside of it. This provides the flexibility to just take the whole wrapping class and copy it to somewhere else where you might not even have jQuery available.&lt;/p&gt;

&lt;p&gt;If the element has options for us saved within its data attributes, we also want to take them into account. This is handy for when you have plugins that auto-initialize themselves (which we will do later) so that you have no way
to pass options to them via their plugin invocation.&lt;/p&gt;

&lt;p&gt;Here is an example:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_html&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;&lt;span class=&quot;sc2&quot;&gt;&lt;a href=&quot;http://december.com/html/4/element/div.html&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;div&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;kw3&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;widget js-widget&amp;quot;&lt;/span&gt; data-widget-plugin-opts=&lt;span class=&quot;st0&quot;&gt;&amp;quot;{&amp;quot;&lt;/span&gt;optionA&lt;span class=&quot;st0&quot;&gt;&amp;quot;:&amp;quot;&lt;/span&gt;someCoolOptionString&lt;span class=&quot;st0&quot;&gt;&amp;quot;}&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;

&lt;h2&gt;Optional: Keeping a reference to our wrapper object in the element&lt;/h2&gt;

&lt;p&gt;It&#039;s a good idea to keep a reference to our plugin object on the DOM element, because that helps a lot with debugging using your browser&#039;s javascript console later.
I don&#039;t always do this because it may just be overkill for the situation at hand. But I want to show you how to do this regardless:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$, doc, win&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;use strict&amp;quot;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt; = &lt;span class=&quot;st0&quot;&gt;&#039;js-widget&#039;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el &amp;nbsp;= $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt; = &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; optionA: &lt;span class=&quot;st0&quot;&gt;&#039;someOption&#039;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; optionB: &lt;span class=&quot;st0&quot;&gt;&#039;someOtherOption&#039;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// let&#039;s use our name variable here as well for our meta options&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; meta &amp;nbsp;= &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt; + &lt;span class=&quot;st0&quot;&gt;&#039;-opts&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;opts&lt;/span&gt; = $.&lt;span class=&quot;me1&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt;, opts, meta&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;, &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;jQuery, document, window&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
$&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;#mywidget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;optionA: &lt;span class=&quot;st0&quot;&gt;&#039;a&#039;&lt;/span&gt;, optionB: &lt;span class=&quot;st0&quot;&gt;&#039;b&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
console.&lt;span class=&quot;me1&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;#mywidget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;js-widget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we just expose our wrapper object using jQuery&#039;s $.data function. Easy.&lt;/p&gt;

&lt;h2&gt;Binding some events&lt;/h2&gt;

&lt;p&gt;Let&#039;s use our wrapper object&#039;s init() function to bind some events and write some real plugin code:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$, doc, win&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;use strict&amp;quot;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt; = &lt;span class=&quot;st0&quot;&gt;&#039;js-widget&#039;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el &amp;nbsp; &amp;nbsp; &amp;nbsp;= $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt; = &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; optionA: &lt;span class=&quot;st0&quot;&gt;&#039;someOption&#039;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; optionB: &lt;span class=&quot;st0&quot;&gt;&#039;someOtherOption&#039;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; meta &amp;nbsp; &amp;nbsp; = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt; + &lt;span class=&quot;st0&quot;&gt;&#039;-opts&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;opts&lt;/span&gt; &amp;nbsp; &amp;nbsp;= $.&lt;span class=&quot;me1&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt;, opts, meta&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;, &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$header = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.header&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$body &amp;nbsp; = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.body&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Widget.&lt;span class=&quot;me1&quot;&gt;prototype&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;init&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; self = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$header.&lt;span class=&quot;me1&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;click.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&#039;.title&#039;&lt;/span&gt;, &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;e&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; e.&lt;span class=&quot;me1&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; self.&lt;span class=&quot;me1&quot;&gt;editTitle&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$header.&lt;span class=&quot;me1&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;change.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&#039;select&#039;&lt;/span&gt;, &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;e&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; e.&lt;span class=&quot;me1&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; self.&lt;span class=&quot;me1&quot;&gt;saveTitle&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Widget.&lt;span class=&quot;me1&quot;&gt;prototype&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;editTitle&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$header.&lt;span class=&quot;me1&quot;&gt;addClass&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;editing&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Widget.&lt;span class=&quot;me1&quot;&gt;prototype&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;saveTitle&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; val = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$header.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.title&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// save val to database&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$header.&lt;span class=&quot;me1&quot;&gt;removeClass&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;editing&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// ...&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;jQuery, document, window&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Notice that we have bound the events via .on() in delegation mode, which means that our .title element doesn&#039;t even have to be in the DOM yet when the events are bound.
It&#039;s generally good practice to use event delegation, as you do not have to constantly bind/unbind events as elements are added/removed to/from the DOM.&lt;/p&gt;

&lt;p&gt;We use our name variable as an event namespace here, which allows easy unbinding later without removing event listeners on the widget elements that were not bound using our plugin.&lt;/p&gt;

&lt;h2&gt;How to prevent designers from breaking your plugins&lt;/h2&gt;

&lt;p&gt;Something else that I like doing is attaching different classes to elements depending on if they are meant for css styling or for javascript functionality.&lt;/p&gt;

&lt;p&gt;The markup that we could use for the plugin above could be:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_html&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;&lt;span class=&quot;sc2&quot;&gt;&lt;a href=&quot;http://december.com/html/4/element/div.html&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;div&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;kw3&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;widget&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;sc2&quot;&gt;&lt;a href=&quot;http://december.com/html/4/element/div.html&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;div&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;kw3&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;header&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class=&quot;sc2&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;sc2&quot;&gt;&lt;a href=&quot;http://december.com/html/4/element/div.html&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;div&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;kw3&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;body&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class=&quot;sc2&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;sc2&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;And then we do:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
$&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.widget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;This is all fine and dandy, but now our designer comes along, changes the classes around, because he is not aware of our new plugin (or worse, he doesn&#039;t even care). This would break our client javascript functionality.
So what I often do is this instead:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_html&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;&lt;span class=&quot;sc2&quot;&gt;&lt;a href=&quot;http://december.com/html/4/element/div.html&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;div&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;kw3&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;widget js-widget&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;sc2&quot;&gt;&lt;a href=&quot;http://december.com/html/4/element/div.html&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;div&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;kw3&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;header js-header&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class=&quot;sc2&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;sc2&quot;&gt;&lt;a href=&quot;http://december.com/html/4/element/div.html&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;div&lt;/span&gt;&lt;/a&gt; &lt;span class=&quot;kw3&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;body js-body&amp;quot;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class=&quot;sc2&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;sc2&quot;&gt;&lt;span class=&quot;kw2&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Then in our plugin change how we find the body and header:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el &amp;nbsp; &amp;nbsp; = $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt; = &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; optionA: &lt;span class=&quot;st0&quot;&gt;&#039;someOption&#039;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; optionB: &lt;span class=&quot;st0&quot;&gt;&#039;someOtherOption&#039;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; meta &amp;nbsp; &amp;nbsp; = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt; + &lt;span class=&quot;st0&quot;&gt;&#039;-opts&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;opts&lt;/span&gt; &amp;nbsp; &amp;nbsp;= $.&lt;span class=&quot;me1&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt;, opts, meta&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$header = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.js-header&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$body &amp;nbsp; = &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.js-body&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;And change our invocation:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
$&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.js-widget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;I agree it&#039;s a little more markup to write and you might not need to use this. Also, since we manipulate the DOM with jQuery plugins we might depend on specific tag types anyway.
So if the designer changed all div&#039;s to be li&#039;s instead, it might still break our plugin. If you are in a situation where you have regressions due to frontend engineers and designers not communicating properly, using js- prefixed classes on all important elements might be a step in the right direction.&lt;/p&gt;

&lt;p&gt;Notice how this.$header and this.$body are also agnostic to the html tag of the element that they cover.&lt;/p&gt;

&lt;h2&gt;How to remove our plugin without removing the DOM element&lt;/h2&gt;

&lt;p&gt;For large applications it&#039;s important to allow multiple plugins to operate on the same elements.
For this to work, you need to be able to add and remove plugins on the same element without affecting the other plugins.&lt;/p&gt;

&lt;p&gt;Most jQuery plugins expect you to remove the element entirely to teardown the plugin. But what if you want to remove the plugin without removing the element?
We can do this using a destroy function:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
Widget.&lt;span class=&quot;me1&quot;&gt;prototype&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;destroy&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;*&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;removeData&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el = &lt;span class=&quot;kw2&quot;&gt;null&lt;/span&gt;;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;It takes our local name variable again and removes all events in that namespace. It also removes the reference to the wrapper object from the element.
Now we can easily remove the plugin from the outside:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
$&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.js-widget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;js-widget&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;By the way, if you remove the DOM element, jQuery will take care of removing all associated data and events by itself, so there is no need to worry about that case.&lt;/p&gt;

&lt;h2&gt;How to write self-initializing plugins&lt;/h2&gt;

&lt;p&gt;If you need to deal with a lot of Ajax requests in your app and then need to bind plugins on the DOM elements that were just loaded, this tip might be pretty useful for you.&lt;/p&gt;

&lt;p&gt;What I like doing is using a PubSub implementation to automatically invoke plugins:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
$&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; $document = $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;document&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; $document.&lt;span class=&quot;me1&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;dom&lt;em&gt;loaded&#039;&lt;/span&gt;, $document&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.some&lt;/em&gt;selector&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;/my/url&#039;&lt;/span&gt;, &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;nodes&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $document.&lt;span class=&quot;me1&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;ajax_loaded&#039;&lt;/span&gt;, nodes&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Now we can allow the plugin to bind itself to all elements that by class definition need to be bound to it:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$, doc, win&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;use strict&amp;quot;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt; = &lt;span class=&quot;st0&quot;&gt;&#039;js-widget&#039;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;co1&quot;&gt;// wrapper object implementation, etc.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;doc&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;dom&lt;em&gt;loaded ajax&lt;/em&gt;loaded&#039;&lt;/span&gt;, &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;nodes&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; $nodes = $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;nodes&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; $elements = $nodes.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $elements = $elements.&lt;span class=&quot;me1&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$nodes.&lt;span class=&quot;me1&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $elements.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;jQuery, document, window&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;You can also come up with your own very custom events and even namespaces to allow your plugins to talk to each other without having to know about each other.&lt;/p&gt;

&lt;p&gt;Advantages of this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;This removes a lot of boilerplate code from our app! Re-initializing plugins after an ajax request without extra codelines? No problem!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can simply remove functionality from our application by not loading a specific plugin&#039;s javascript file.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I can see two obvious disadvantages here, though:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;We cannot provide options to the plugin invocation via this. We&#039;d have to rely on options bound using the html5 data property &quot;data-js-widget-opts&quot; (read above).
In my experience this not as often needed as one would think, though.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you have a very complex app with a lot of plugins and code flying around, this PubSub mechanism might not be the most performant way of doing things.
Think of 20 plugins all doing some .find() and .filter() operation on a large piece of markup that was just loaded via ajax. Ugh. :)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;Wrapping usable code in a jQuery plugin is not always easy, but following a few guidelines makes it a much better experience.
The ultimate takeaway here is to always wrap the plugin functionality in a wrapper class, so that the elements in your jQuery set that you bind the plugin to do not interfer with each other.&lt;/p&gt;

&lt;p&gt;If your plugin is more complex, you could even use multiple wrapper classes and let their objects talk to each other. Or even cooler, try to move some of the functionality your plugin requires out into another, smaller plugin.
And let the both of them talk to each other via PubSub.&lt;/p&gt;

&lt;p&gt;The rest is a couple nice extras that made my live easier.&lt;/p&gt;

&lt;p&gt;Here is the full skeleton again that I use when I write new plugins (rename accordingly):&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$, doc, win&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;use strict&amp;quot;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt; = &lt;span class=&quot;st0&quot;&gt;&#039;js-widget&#039;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el &amp;nbsp; &amp;nbsp; &amp;nbsp;= $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;el&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;, &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt; = &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; meta &amp;nbsp; &amp;nbsp; &amp;nbsp;= &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt; + &lt;span class=&quot;st0&quot;&gt;&#039;-opts&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;opts&lt;/span&gt; &amp;nbsp; &amp;nbsp; = $.&lt;span class=&quot;me1&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;defaults&lt;/span&gt;, opts, meta&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Widget.&lt;span class=&quot;me1&quot;&gt;prototype&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;init&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; Widget.&lt;span class=&quot;me1&quot;&gt;prototype&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;destroy&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;*&#039;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el.&lt;span class=&quot;me1&quot;&gt;removeData&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.$el = &lt;span class=&quot;kw2&quot;&gt;null&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; $.&lt;span class=&quot;me1&quot;&gt;fn&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt; = &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;each&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;new&lt;/span&gt; Widget&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw1&quot;&gt;this&lt;/span&gt;, opts&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;doc&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;dom_loaded ajax_loaded&#039;&lt;/span&gt;, &lt;span class=&quot;kw2&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;e, nodes&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; $nodes = $&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;nodes&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;kw2&quot;&gt;var&lt;/span&gt; $elements = $nodes.&lt;span class=&quot;me1&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $elements = $elements.&lt;span class=&quot;me1&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;$nodes.&lt;span class=&quot;me1&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&#039;.&#039;&lt;/span&gt; + &lt;span class=&quot;kw3&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp; &amp;nbsp; $elements.&lt;span class=&quot;me1&quot;&gt;widget&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;jQuery, document, window&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Kind regards,
Tim&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://twitter.com/#!/tim_kos&quot;&gt;@tim_kos&lt;/a&gt;
&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4f72ab2e-7310-4a74-817a-0a04cbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>tim@debuggable.com</author><pubDate>Thu, 29 Mar 2012 06:41:34 +0000</pubDate><comments>http://www.debuggable.com/posts/how-to-write-jquery-plugins:4f72ab2e-7310-4a74-817a-0a04cbdd56cb</comments></item><item><title>Vim Workshop in Berlin (April 20)</title><link>http://www.debuggable.com/posts/vim-workshop-in-berlin-april-20:4f702b83-ce24-429c-9403-0e39cbdd56cb</link><guid>http://www.debuggable.com/posts/vim-workshop-in-berlin-april-20:4f702b83-ce24-429c-9403-0e39cbdd56cb</guid><description>&lt;p&gt;My friend &lt;a href=&quot;https://twitter.com/#!/nelstrom&quot;&gt;Drew&lt;/a&gt; of &lt;a href=&quot;http://vimcasts.org/&quot;&gt;Vimcast&lt;/a&gt; fame is organizing two half-day &lt;a href=&quot;http://vimcasts.eventbrite.com/&quot;&gt;vim workshops&lt;/a&gt; in Berlin on April 20.&lt;/p&gt;

&lt;p&gt;As a former Textmate user, I cannot overstate the productivity gains from mastering vim. With the early bird discount, the tickets sell at 75 GBP (~90 EUR), and there are only a few tickets left, so you should act quickly.&lt;/p&gt;

&lt;p&gt;The workshops are aimed at intermediate users, so if your vim skills are non-existing or very rusty, you should probably play with &lt;a href=&quot;http://vim.wikia.com/wiki/Tutorial#Vim_tutor&quot;&gt;vimtutor&lt;/a&gt; before showing up.&lt;/p&gt;

&lt;p&gt;I&#039;ll be attending the &lt;a href=&quot;http://berlin-vimcasts-pm-1-eorg.eventbrite.com/&quot;&gt;afternoon workshop&lt;/a&gt; along with &lt;a href=&quot;https://twitter.com/#!/tim_kos&quot;&gt;Tim&lt;/a&gt;, so hope to see you there!&lt;/p&gt;

&lt;p&gt;--fg&lt;/p&gt;

&lt;p&gt;Full Disclosure: I gain nothing by promoting this event other than the joy of seeing people boost their productivity.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4f702b83-ce24-429c-9403-0e39cbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Mon, 26 Mar 2012 08:56:21 +0000</pubDate><comments>http://www.debuggable.com/posts/vim-workshop-in-berlin-april-20:4f702b83-ce24-429c-9403-0e39cbdd56cb</comments></item><item><title>NPM - An intervention</title><link>http://www.debuggable.com/posts/npm-an-intervention:4f44dd25-a114-4361-ada1-6cefcbdd56cb</link><guid>http://www.debuggable.com/posts/npm-an-intervention:4f44dd25-a114-4361-ada1-6cefcbdd56cb</guid><description>&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Isaac &lt;a href=&quot;http://debuggable.com/posts/npm-an-intervention:4f44dd25-a114-4361-ada1-6cefcbdd56cb#comment-4f453c4b-7aac-4224-8c65-3f15cbdd56cb#comment-4f4533a2-f590-4b40-bde1-52eacbdd56cb&quot;&gt;commented&lt;/a&gt; and explained why fuzzy version specifiers are here to stay. I&#039;ll be ok with it and will adapt my workflow accordingly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 2:&lt;/strong&gt; I did not give up on the bug that is part of the story below, a test case and fix has been &lt;a href=&quot;https://github.com/nodejitsu/forever/pull/246&quot;&gt;submitted and merged&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update 3:&lt;/strong&gt; NPM Shrinkwrap is now a &lt;a href=&quot;http://blog.nodejs.org/2012/02/27/managing-node-js-dependencies-with-shrinkwrap/&quot;&gt;real thing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;NPM is the official node.js package manager. Unlike many package managers
that came before, it is actually incredibly awesome, and has helped to create
one of the most vibrant communities in the history of open source.&lt;/p&gt;

&lt;p&gt;However, today I want to talk about a few aspects of npm that concern me. In
particular I want to talk about stuff where I feel that NPM is making bad
things easy, and good things hard.&lt;/p&gt;

&lt;h2&gt;NPM module versions are broken&lt;/h2&gt;

&lt;p&gt;Today, I tried to contribute to the &lt;a href=&quot;https://github.com/nodejitsu/forever&quot;&gt;forever&lt;/a&gt; module. The company I am helping
had to patch their version of it because of a hard-to-reproduce bug in
production and asked me to help submitting their fix upstream. Being the
scientific type, I set out to write a test case against the forever version
their patch is based on:&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;
$ npm install forever@0.7.2
&lt;/pre&gt;

&lt;p&gt;Fantastic, NPM lets me specify which version of forever I want to install. Now
lets verify the installed version works:&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;
$ ./node_modules/forever/bin/forever

node.js:134
        throw e; // process.nextTick error, or &#039;error&#039; event on first tick
        ^
TypeError: undefined is not a function
    at CALL_NON_FUNCTION_AS_CONSTRUCTOR (native)
    at Object.&lt;anonymous&gt; (/Users/Felix/Desktop/foo/node_modules/forever/lib/forever.js:43:23)
    ...
&lt;/pre&gt;

&lt;p&gt;Oh no, what happened? Mind you, except for an unrelated patch, this version of
forever is running perfectly fine in production.&lt;/p&gt;

&lt;p&gt;Well, as it turns out, you have been lied to. There is no such thing as forever
v0.7.2. At least not a single one. It depends on an implicit and unchangable
second parameter: time.&lt;/p&gt;

&lt;p&gt;Why is that? Well, it is because forever v0.7.2 depends on this:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
&lt;span class=&quot;st0&quot;&gt;&amp;quot;nconf&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;0.x.x&amp;quot;&lt;/span&gt;,&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;And as it turns out, nconf has released newer versions matching this selector,
featuring a different API.&lt;/p&gt;

&lt;h2&gt;You are doing it wrong&lt;/h2&gt;

&lt;p&gt;&quot;Hah!&quot;, you might say. &quot;That&#039;s why you should
&lt;a href=&quot;http://www.mikealrogers.com/posts/nodemodules-in-git.html&quot;&gt;check your node&amp;#95;modules into git&lt;/a&gt;!&quot;.&lt;/p&gt;

&lt;p&gt;I am sorry, but that is not helpful. While this will allow me to pin down
the node modules used by my app exactly, it does not help me here. What I want to
do is to reproduce this bug in a standalone copy of forever v0.7.2, then
check if it exists in the latest version, and if so submit the test case and
fix for it upstream.&lt;/p&gt;

&lt;p&gt;However, I can&#039;t. Not without manually resolving all forever dependencies the
way NPM resolved them when v0.7.2 was released. (The fact that forever is a bit
of a &lt;a href=&quot;https://github.com/nodejitsu/forever/blob/382f8e7f2a1da99838615d8e462be6b964975de4/package.json#L24-40&quot;&gt;spaceship&lt;/a&gt; when it comes to dependencies does not help either).&lt;/p&gt;

&lt;h2&gt;Discouraging Open Source&lt;/h2&gt;

&lt;p&gt;Speaking about Mikeal&#039;s article. I felt that something was wrong about checking
your node&amp;#95;modules into git when reading it, but it is only now that I can
point out what:&lt;/p&gt;

&lt;p&gt;In the article, Mikeal argues that module authors should not try to exactly
reference their dependency versions, so this way users would get more frequent
updates of those dependencies and help test them.&lt;/p&gt;

&lt;p&gt;However, he says doing so for your app is a good thing.&lt;/p&gt;

&lt;p&gt;I disagree. To me, this approach discourages open source for two reasons:&lt;/p&gt;

&lt;h3&gt;a) Bug reports:&lt;/h3&gt;

&lt;p&gt;I currently maintain 44 NPM modules. It is very hard to keep
up with that.&lt;/p&gt;

&lt;p&gt;If you are asking me to support multiple versions of all my dependencies, I
will have to stop helping people with bug reports for my modules.&lt;/p&gt;

&lt;p&gt;When somebody reports a bug for a given version of my module, I want to know
&lt;strong&gt;exactly&lt;/strong&gt; what version he used. Figuring out when he installed my module to
rule out dependency issues for every bug report is not an option for me.&lt;/p&gt;

&lt;h3&gt;b) Contributions&lt;/h3&gt;

&lt;p&gt;Ask yourself what is easier. Adding a quick patch to a node module you already
track include in the git repo of your app, --or-- creating a fork of it, fixing the problem in the
fork, pushing that fork on GitHub, changing your package.json to point to your
fork, and submitting a pull request.&lt;/p&gt;

&lt;p&gt;I know people cannot be forced to contribute back, nor should they be. But
as things stand right now, checking in all node_modules of an app into git is
the &lt;strong&gt;only&lt;/strong&gt; sane option, as the version numbers in your package.json are
essentially meaningless.&lt;/p&gt;

&lt;p&gt;This means that contributing back to open source is made difficult by default,
while keeping your patches to yourself is made easy. I would like this to be
the other way arround.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;I propose to gradually drop all support for fuzzy version specifiers from NPM.&lt;/p&gt;

&lt;p&gt;To me, fuzzy version specifiers are entirely evil. They make things more
complex. They force me to manually snapshot the packages I depend on for my
apps. They prevent me from supporting and contributing to open source.&lt;/p&gt;

&lt;p&gt;So rather than throwing more complexity at this problem, lets just remove
this feature alltogether.&lt;/p&gt;

&lt;p&gt;If you agree, please &lt;a href=&quot;https://twitter.com/felixge/status/172366107469029376&quot;&gt;re-tweet this article&lt;/a&gt; or leave a comment.&lt;/p&gt;

&lt;p&gt;--fg&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4f44dd25-a114-4361-ada1-6cefcbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Wed, 22 Feb 2012 17:03:00 +0000</pubDate><comments>http://www.debuggable.com/posts/npm-an-intervention:4f44dd25-a114-4361-ada1-6cefcbdd56cb</comments></item><item><title>Testing node.js modules with Travis CI</title><link>http://www.debuggable.com/posts/testing-node-js-modules-with-travis-ci:4ec62298-aec4-4ee3-8b5a-2c96cbdd56cb</link><guid>http://www.debuggable.com/posts/testing-node-js-modules-with-travis-ci:4ec62298-aec4-4ee3-8b5a-2c96cbdd56cb</guid><description>&lt;p&gt;You have written a node.js module lately? It has a test suite? &lt;a href=&quot;http://www.youtube.com/watch?v=2Z4m4lnjxkY&quot;&gt;Awesome&lt;/a&gt;! Time
to get yourself a nerd badge of honor:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://debuggable.com.s3.amazonaws.com/blog/2011/build-passing.png&quot; alt=&quot;build passing&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But hang on nerdy warrior, this precious award has to be earned. So go ahead and
check out the sweetness that is &lt;a href=&quot;http://travis-ci.org&quot;&gt;Travis CI&lt;/a&gt;. Travis is an open
source, free to use, continuous integration server. Initially it was just
building ruby stuff, but these days it supports a ton of other languages,
including node.js.&lt;/p&gt;

&lt;p&gt;And luckily, getting travis to run your tests on every GitHub push is really
easy as well:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Go to &lt;a href=&quot;http://travis-ci.org&quot;&gt;Travis&lt;/a&gt; and login/connect with your GitHub account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Hover over your name on the top right, and select &quot;Profile&quot; from the
dropdown.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; You should see all your GitHub projects. Flip the &quot;Off&quot; switch to
&quot;On&quot; for a node.js project you want to use with travis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Add a .travis.yml file to your project with the following:&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;
language: node_js
node_js:
  - 0.4
  - 0.6
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Make sure your package.json has something like this:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
&lt;span class=&quot;st0&quot;&gt;&amp;quot;scripts&amp;quot;&lt;/span&gt;: &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;test&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;make test&amp;quot;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; Git push, and watch travis building your project on the home screen!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7:&lt;/strong&gt; Assuming your tests are passing, it is time to get your badge of
honor. Adding it to your GitHub Readme.md is as simple as:&lt;/p&gt;

&lt;pre class=&quot;terminal&quot;&gt;
[![Build Status](https://secure.travis-ci.org/&amp;lt;GITHUB_USER&amp;gt;/&amp;lt;REPO_NAME&amp;gt;.png)](http://travis-ci.org/&amp;lt;GITHUB_USER&amp;gt;/&amp;lt;REPO_NAME&amp;gt;)
&lt;/pre&gt;

&lt;p&gt;If you want to see an example of what this looks like, and you also happen to
be in the market for some no-bullshit testing tools, check out my new libs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/felixge/node-utest&quot;&gt;utest&lt;/a&gt;: The minimal unit testing library.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/felixge/node-urun&quot;&gt;urun&lt;/a&gt;: The minimal test runner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That&#039;s it. And in case you are not excited enough yet, go and check out the
&lt;a href=&quot;http://about.travis-ci.org/docs/&quot;&gt;Travis Docs&lt;/a&gt; to discover additional goodies like how to work with
databases, etc.&lt;/p&gt;

&lt;p&gt;--fg&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4ec62298-aec4-4ee3-8b5a-2c96cbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Fri, 18 Nov 2011 09:17:12 +0000</pubDate><comments>http://www.debuggable.com/posts/testing-node-js-modules-with-travis-ci:4ec62298-aec4-4ee3-8b5a-2c96cbdd56cb</comments></item><item><title>Private npm modules</title><link>http://www.debuggable.com/posts/private-npm-modules:4e68cc7d-1ac4-42d9-995a-343dcbdd56cb</link><guid>http://www.debuggable.com/posts/private-npm-modules:4e68cc7d-1ac4-42d9-995a-343dcbdd56cb</guid><description>&lt;p&gt;Thanks to &lt;a href=&quot;http://twitter.com/#!/izs&quot;&gt;Isaac&lt;/a&gt;, npm is getting more and more awesome by the hour. One of the
coolest &lt;a href=&quot;https://github.com/isaacs/npm/issues/1272&quot;&gt;recent additions&lt;/a&gt; (you need at least v1.0.26) is the ability to specify
private git repositories urls as a dependency in your package.json files.&lt;/p&gt;

&lt;p&gt;At transloadit, we are currently using the feature to move some of our
infrastructure code into separate packages, allowing for those to be tested
and developed in isolation making our core application easier to maintain and
work on.&lt;/p&gt;

&lt;p&gt;The syntax for referencing a git repository (and commit) is as follows:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;my-app&amp;quot;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;dependencies&amp;quot;&lt;/span&gt;: &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;private-repo&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;git+ssh://git@github.com:my-account/node-private-repo.git#v0.0.1&amp;quot;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br /&gt;
&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;This will include a private npm module called &lt;code&gt;&quot;private-repo&quot;&lt;/code&gt; from GitHub. The
url also contains an optional refspec (&lt;code&gt;#v0.0.1&lt;/code&gt;) that tells npm which branch,
commit, or in this case tag you want to have checked out.&lt;/p&gt;

&lt;p&gt;Now of course this is not the only way to do private npm repositories, but it
is much simpler than running your &lt;a href=&quot;https://github.com/isaacs/npm/blob/master/doc/registry.md&quot;&gt;own registry&lt;/a&gt;, so I would recommend it to
most people.&lt;/p&gt;

&lt;p&gt;Before you head of to play with this, here is a final tip that may safe you
some headaches. In all your private npm modules, add &lt;code&gt;&quot;private&quot;: true&lt;/code&gt; to your
package.json. This will make sure npm will never let you accidentally publish
your secret sauce to the official npm registry.&lt;/p&gt;

&lt;p&gt;Happy hacking,
--fg&lt;/p&gt;

&lt;p&gt;PS: When deploying, don&#039;t forget that you need to authorize the servers ssh key for the GitHub repository you are depending on.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4e68cc7d-1ac4-42d9-995a-343dcbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Thu, 08 Sep 2011 14:18:26 +0000</pubDate><comments>http://www.debuggable.com/posts/private-npm-modules:4e68cc7d-1ac4-42d9-995a-343dcbdd56cb</comments></item><item><title>How to fork &amp; patch npm modules</title><link>http://www.debuggable.com/posts/how-to-fork-patch-npm-modules:4e2eb9f3-e584-44be-b1a9-3db7cbdd56cb</link><guid>http://www.debuggable.com/posts/how-to-fork-patch-npm-modules:4e2eb9f3-e584-44be-b1a9-3db7cbdd56cb</guid><description>&lt;p&gt;With now more than &lt;a href=&quot;http://twitter.com/#!/npmjs/status/95573155099324416&quot;&gt;3000 modules&lt;/a&gt;, there are huge gaps in the quality of things you find in the &lt;a href=&quot;http://search.npmjs.org/&quot;&gt;npm registry&lt;/a&gt;. But more often than not, it&#039;s easy to find a module that is really close to what you need, except if it wasn&#039;t for that one bug or missing feature.&lt;/p&gt;

&lt;p&gt;Now depending on who is maintaining this module, you may get the problem resolved by simply opening a GitHub issue and waiting for a few days. However, open source doesn&#039;t really work without community, nor do you always want to be at the mercy of someone else. So a much better approach is to actually roll up your sleeves, and fix the problem yourself.&lt;/p&gt;

&lt;p&gt;Here is the proper way to do this while using npm to manage your forked version of the module:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fork the project on GitHub&lt;/li&gt;
&lt;li&gt;Clone the fork to your machine&lt;/li&gt;
&lt;li&gt;Fix the bug or add the feature you want&lt;/li&gt;
&lt;li&gt;Push your commits up to your fork on GitHub&lt;/li&gt;
&lt;li&gt;Open your fork on GitHub, and click on the latest commit you made&lt;/li&gt;
&lt;li&gt;On the page of that commit, click on the &quot;Downloads&quot; button&lt;/li&gt;
&lt;li&gt;Right click on the &quot;Download .tar.gz&quot; button inside the popup, and copy the link (&quot;Copy Link Address&quot; in Chrome)&lt;/li&gt;
&lt;li&gt;Open up your package.json file, and replace the version number of the module with the url you just copied&lt;/li&gt;
&lt;li&gt;Send a pull request upstream (Optional, but this way you will avoid having to maintain that patch of yours against newer versions of the module you forked)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example: My new &lt;a href=&quot;https://github.com/felixge/node-airbrake&quot;&gt;airbrake module&lt;/a&gt; uses a forked version of  &lt;a href=&quot;https://github.com/oozcitak/xmlbuilder-js&quot;&gt;xmlbuilder&lt;/a&gt;. I submited my fix as a &lt;a href=&quot;https://github.com/oozcitak/xmlbuilder-js/pull/11&quot;&gt;pull request&lt;/a&gt;, but it has not been merged yet. In order to pull in my changes via npm anyway, I simply pointed my &lt;a href=&quot;https://github.com/felixge/node-airbrake/blob/master/package.json&quot;&gt;package.json&lt;/a&gt; to the download url of my fork on GitHub like so:&lt;/p&gt;

&lt;p&gt;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;&lt;div class=&quot;code debuggable_sh_js&quot; style=&quot;white-space: wrap;white-space: nowrap;&quot;&gt;
&lt;span class=&quot;st0&quot;&gt;&amp;quot;dependencies&amp;quot;&lt;/span&gt;: &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;request&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;1.9.8&amp;quot;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;xmlbuilder&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;https://github.com/felixge/xmlbuilder-js/tarball/4303eb2650a4b819a980b1dc9d2965862a1e9faf&amp;quot;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;stack-trace&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;0.0.5&amp;quot;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;traverse&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;0.4.4&amp;quot;&lt;/span&gt;,&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &lt;span class=&quot;st0&quot;&gt;&amp;quot;hashish&amp;quot;&lt;/span&gt;: &lt;span class=&quot;st0&quot;&gt;&amp;quot;0.0.4&amp;quot;&lt;/span&gt;&lt;br /&gt;
&amp;nbsp; &lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;,&lt;/div&gt;&lt;/p&gt;

&lt;p&gt;Alright, let me know if this is helping your node.js adventures, or if you have an alternative workflow you are using. Otherwise, happy hacking!&lt;/p&gt;

&lt;p&gt;--fg&lt;/p&gt;

&lt;p&gt;PS: You should upgrade to the latest npm version first, some older versions had problems with handling url dependencies properly.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4e2eb9f3-e584-44be-b1a9-3db7cbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Tue, 26 Jul 2011 13:15:03 +0000</pubDate><comments>http://www.debuggable.com/posts/how-to-fork-patch-npm-modules:4e2eb9f3-e584-44be-b1a9-3db7cbdd56cb</comments></item><item><title>Node.js Workshop in Cologne, June 10th</title><link>http://www.debuggable.com/posts/node-js-workshop-in-cologne-june-10th:4dd66beb-ff04-4de9-a490-7c09cbdd56cb</link><guid>http://www.debuggable.com/posts/node-js-workshop-in-cologne-june-10th:4dd66beb-ff04-4de9-a490-7c09cbdd56cb</guid><description>&lt;p&gt;We apologize for the short notice, but if you are looking to put node.js in production, this full day &lt;a href=&quot;http://nodecologne.eventbrite.com/&quot;&gt;node.js workshop&lt;/a&gt; we are organizing is where it&#039;s at!&lt;/p&gt;

&lt;p&gt;The workshop is happening on Friday June 10, one day before &lt;a href=&quot;http://nodecamp.eu/&quot;&gt;nodecamp.eu&lt;/a&gt;. Space is limited to 15 people and expected to sell out quickly.&lt;/p&gt;

&lt;p&gt;As a reader of our blog, you can get a 15% discount on the regular ticket by using the code &lt;code&gt;&#039;debuggable&#039;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should you attend?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This workshop will teach you everything you need in order to write and deploy powerful node.js applications. We&#039;ll try to cover a lot of ground, so if you are interested in any of the following, you should definitly attend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up node.js on your local machine&lt;/li&gt;
&lt;li&gt;Understanding the module system&lt;/li&gt;
&lt;li&gt;Using npm for installing and upgrading modules&lt;/li&gt;
&lt;li&gt;Publishing your own npm modules&lt;/li&gt;
&lt;li&gt;Everything you need to know about http.Server&lt;/li&gt;
&lt;li&gt;Structuring your code using OOP in JavaScript&lt;/li&gt;
&lt;li&gt;Dealing with all the callbacks in a sane fashion&lt;/li&gt;
&lt;li&gt;Using the same code in node.js and the browser&lt;/li&gt;
&lt;li&gt;Building realtime apps with Socket.IO&lt;/li&gt;
&lt;li&gt;Using the express framework&lt;/li&gt;
&lt;li&gt;An overview over testing tools available for node.js&lt;/li&gt;
&lt;li&gt;Deploying node.js to Ec2 / Joyent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first half of the day will be guided by slides (which will be made available afterwards), with the second half being a hands-on session where we will build a small node app from scratch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;About the instructor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This workshop will be led by &lt;a href=&quot;http://twitter.com/#!/felixge&quot;&gt;Felix Geisendörfer&lt;/a&gt; (that&#039;s me). He is one of the earliest and most active contributors to node.js, author of over 20 npm modules and also running one of the biggest node.js applications in production over at &lt;a href=&quot;http://transloadit.com/&quot;&gt;transloadit.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In addition, &lt;a href=&quot;http://twitter.com/#!/tim_kos&quot;&gt;Tim Koschützki&lt;/a&gt; who is also a co-founder at transloadit, will be available all day to help with individual questions and trouble shooting. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questions &amp;amp; More Workshop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have additional questions or can&#039;t make it to this workshop, please head over to the &lt;a href=&quot;http://nodecologne.eventbrite.com/&quot;&gt;workshop page&lt;/a&gt; which has information on other upcoming workshops and questions.&lt;/p&gt;

&lt;p&gt;--fg
&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4dd66beb-ff04-4de9-a490-7c09cbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Fri, 20 May 2011 13:26:03 +0000</pubDate><comments>http://www.debuggable.com/posts/node-js-workshop-in-cologne-june-10th:4dd66beb-ff04-4de9-a490-7c09cbdd56cb</comments></item><item><title>Why are you not using a SSD yet?</title><link>http://www.debuggable.com/posts/why-are-you-not-using-a-ssd-yet:4d64ad6f-22d8-4eca-99e8-765acbdd56cb</link><guid>http://www.debuggable.com/posts/why-are-you-not-using-a-ssd-yet:4d64ad6f-22d8-4eca-99e8-765acbdd56cb</guid><description>&lt;p&gt;If you are a developer, and you have not switched to a SSD yet, what is your excuse?&lt;/p&gt;

&lt;p&gt;Let me explain. I&#039;ve switched to an SSD a little over a week ago, and it&#039;s a different world. You know that feeling of having just bought &amp;amp; setup a new machine and everything still runs very fast? Well, a SSD will make every single day feel just like that, except much faster.&lt;/p&gt;

&lt;p&gt;But I already knew that, so why has it taken me, and apparently you who is reading this, so long?&lt;/p&gt;

&lt;p&gt;Well, my main problem was that I have a few big things on my hard disk, namely music, photos and virtual machine images. This means that I need a hard disk of ~300 GB to work comfortably. However, the SSD I was &lt;a href=&quot;http://eshop.macsales.com/shop/internal_storage/Mercury_Extreme_SSD_Sandforce/Solid_State_Pro&quot;&gt;interested in&lt;/a&gt; only comes in 40, 60, 120, 240 and 480 GB. The 480 GB costs ~$1.580 right now.&lt;/p&gt;

&lt;p&gt;A 240 GB SSD costs ~$520 which seems much less outrageous, but unfortunately that&#039;s still too small if it was my only disk.&lt;/p&gt;

&lt;p&gt;So for a while, I thought I&#039;d have to wait another 1 - 2 years before enjoying the SSD experience. That was until I came across &lt;a href=&quot;http://duncandavidson.com/blog/2010/10/upgraded-laptop&quot;&gt;this article&lt;/a&gt; which explained that you could replace your MacBook Pro&#039;s optical drive with an SSD. This means I could add an SSD to my machine without giving up the luxury of cheap mass storage.&lt;/p&gt;

&lt;p&gt;With this in mind, I decided to get a 120 GB SSD, which is plenty of space for my core system and applications. I followed a few youtube videos for swapping out the disks, and I also placed my previous hdd in the optical bay slot since I&#039;ve heard reports of hibernation problems if you put your primary disk there.&lt;/p&gt;

&lt;p&gt;Making the new SSD my primary hard disk was easy as well. My initial attempt using time machine failed, so I simply booted up my system from the old primary hdd, and used &lt;a href=&quot;http://www.bombich.com&quot;&gt;carbon copy cloner&lt;/a&gt; to copy all data (excluding my music, images and vms) to my new SSD. After that I made the SSD my primary boot disk using the &quot;Startup Disk Preference Pane&quot; and rebooted. The whole operation took about 1-2 hours.&lt;/p&gt;

&lt;p&gt;So how has this changed my life? First of all, boot time is incredible. Compared to Tim&#039;s mac (which is now scheduled for an upgrade ASAP as well), my machine goes from 0 to starting Photoshop in 48 seconds. Tim&#039;s machine takes 2 minutes and 50 seconds. Note: It takes about the same time for both machines to boot the kernel, but my machine is instantly ready at that point now.&lt;/p&gt;

&lt;p&gt;Starting programs is either instant or 2-3 times faster than before. Recursive grep (using &lt;a href=&quot;http://betterthangrep.com/&quot;&gt;ack&lt;/a&gt;) is insanely fast / instant, even on big project. And git - it&#039;s a different world. If you&#039;ve ever waited for minutes while running &#039;git gc&#039; on a big project, an SSD turns this to seconds. Everything feels just incredibly fast.&lt;/p&gt;

&lt;p&gt;With this in mind, what&#039;s your excuse for not treating yourself to a SSD now?&lt;/p&gt;

&lt;p&gt;--fg&lt;/p&gt;

&lt;p&gt;PS: If you think you would miss your optical drive: You can get an external USB one for ~$40 on Amazon. If you really need the internal one back, I guess it would take you about ~10-15 minutes to put it back in once you know the procedure.&lt;/p&gt;

&lt;p&gt;PPS: If you&#039;re worried about the difficulty of replacing the disk: It&#039;s very easy, all you need to know is how to operate a screw driver. However, make sure you&#039;ve got the right tools. The &lt;a href=&quot;http://eshop.macsales.com/shop/internal_storage/Mercury_Extreme_SSD_Sandforce/Solid_State_Pro&quot;&gt;OWC disk&lt;/a&gt; I&#039;m recommending comes with a set of tools if you order it with the data doubler for the optical bay.&lt;/p&gt;

&lt;p&gt;PPPS: My friend Joel &lt;a href=&quot;https://twitter.com/jperras/status/40536250049888257&quot;&gt;pointed out&lt;/a&gt; the lack of &lt;a href=&quot;http://en.wikipedia.org/wiki/TRIM&quot;&gt;TRIM&lt;/a&gt; support in OSX as a reason for not getting an SSD yet. That&#039;s a valid argument, but the OWC discs &lt;a href=&quot;http://macperformanceguide.com/SSD-RealWorld-SevereDuty.html&quot;&gt;do not suffer&lt;/a&gt; from the lack of TRIM.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4d64ad6f-22d8-4eca-99e8-765acbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Wed, 23 Feb 2011 22:15:01 +0000</pubDate><comments>http://www.debuggable.com/posts/why-are-you-not-using-a-ssd-yet:4d64ad6f-22d8-4eca-99e8-765acbdd56cb</comments></item><item><title>Talks, talks, talks</title><link>http://www.debuggable.com/posts/talks-talks-talks:4d5e9729-27b0-435c-952a-41decbdd56cb</link><guid>http://www.debuggable.com/posts/talks-talks-talks:4d5e9729-27b0-435c-952a-41decbdd56cb</guid><description>&lt;p&gt;I&#039;ve been in Atlanta for the past two weeks, and thanks to the kind help of a few folks, I was able to present at 2 meetups, as well as &lt;a href=&quot;http://startupriot.com/&quot;&gt;Startup Riot 2011&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First up was a new talk at the &lt;a href=&quot;http://www.meetup.com/atlantaruby/&quot;&gt;Atlanta Ruby Meetup&lt;/a&gt;:&lt;/p&gt;

&lt;div style=&quot;width:425px&quot; id=&quot;__ss_6974464&quot;&gt;&lt;strong style=&quot;display:block;margin:12px 0 4px&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/the_undefined/nodejs-should-ruby-developers-care&quot; title=&quot;Nodejs - Should Ruby Developers Care?&quot;&gt;Nodejs - Should Ruby Developers Care?&lt;/a&gt;&lt;/strong&gt;&lt;object id=&quot;__sse6974464&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=nodejs-should-ruby-developers-care-110218095101-phpapp02&amp;stripped_title=nodejs-should-ruby-developers-care&amp;userName=the_undefined&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed name=&quot;__sse6974464&quot; src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=nodejs-should-ruby-developers-care-110218095101-phpapp02&amp;stripped_title=nodejs-should-ruby-developers-care&amp;userName=the_undefined&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
The talk was an attempt of taking out all the cool-aid and hype and focusing on node&#039;s true strength as well as weaknesses. I think the whole thing was very well-received, but I certainly could have done a little better on the delivery.&lt;/p&gt;

&lt;p&gt;Download: &lt;a href=&quot;http://felixge.s3.amazonaws.com/11/nodejs-should-ruby-developers-care.pdf&quot;&gt;nodejs-should-ruby-developers-care.pdf (733 KB)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next up was the 4th edition of my general introduction talk to node.js:&lt;/p&gt;

&lt;div style=&quot;width:425px&quot; id=&quot;__ss_6974385&quot;&gt;&lt;strong style=&quot;display:block;margin:12px 0 4px&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/the_undefined/nodejs-a-quick-tour-v4&quot; title=&quot;Nodejs - A quick tour (v4)&quot;&gt;Nodejs - A quick tour (v4)&lt;/a&gt;&lt;/strong&gt;&lt;object id=&quot;__sse6974385&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=nodejs-a-quick-tour-v4-110218094606-phpapp01&amp;stripped_title=nodejs-a-quick-tour-v4&amp;userName=the_undefined&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed name=&quot;__sse6974385&quot; src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=nodejs-a-quick-tour-v4-110218094606-phpapp01&amp;stripped_title=nodejs-a-quick-tour-v4&amp;userName=the_undefined&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
This version of the talk was updated for the freshly released v0.4, and I&#039;ve also tweaked some other slides to the point where I&#039;m very happy with it. It seems to do a great job getting people excited about node, as well as highlighting sensible use cases.&lt;/p&gt;

&lt;p&gt;Download: &lt;a href=&quot;http://felixge.s3.amazonaws.com/11/nodejs-a-quick-tour-v4.pdf&quot;&gt;nodejs-a-quick-tour-v4.pdf (610 KB)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And last but not least, I had the chance to do a 3 minute pitch for &lt;a href=&quot;http://transloadit.com/&quot;&gt;Transloadit&lt;/a&gt; at &lt;a href=&quot;http://startupriot.com/&quot;&gt;Startup Riot&lt;/a&gt;:&lt;/p&gt;

&lt;div style=&quot;width:425px&quot; id=&quot;__ss_6974507&quot;&gt;&lt;strong style=&quot;display:block;margin:12px 0 4px&quot;&gt;&lt;a href=&quot;http://www.slideshare.net/the_undefined/transloadit-at-startupriot&quot; title=&quot;Transloadit at Startupriot&quot;&gt;Transloadit at Startupriot&lt;/a&gt;&lt;/strong&gt;&lt;object id=&quot;__sse6974507&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=transloadit-startupriot-110218095404-phpapp02&amp;stripped_title=transloadit-at-startupriot&amp;userName=the_undefined&quot; /&gt;&lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot;/&gt;&lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot;/&gt;&lt;embed name=&quot;__sse6974507&quot; src=&quot;http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=transloadit-startupriot-110218095404-phpapp02&amp;stripped_title=transloadit-at-startupriot&amp;userName=the_undefined&quot; type=&quot;application/x-shockwave-flash&quot; allowscriptaccess=&quot;always&quot; allowfullscreen=&quot;true&quot; width=&quot;425&quot; height=&quot;355&quot;&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
Download: &lt;a href=&quot;http://felixge.s3.amazonaws.com/11/transloadit-startupriot.pdf&quot;&gt;transloadit-startupriot.pdf (640 KB)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Doing the actual presentation was quite scary. I have never given a talk this short, you basically don&#039;t get any time to warm up and get into things. You got to go out, and give your best right away. Having an audience of ~500 people didn&#039;t help either.&lt;/p&gt;

&lt;p&gt;However, I think I pulled it of fairly well. My main message was: &quot;Save the time, save the money, save the shrink - use transloadit&quot;, and I highlighted some of the cooler aspects of our service such as the &lt;a href=&quot;http://transloadit.com/blog/2010/12/realtime-encoding-over-150x-faster&quot;&gt;realtime encoding&lt;/a&gt;. Lots of people came by to our table afterwards to find out more about the service, including a few VCs and angels (we&#039;re not looking for investment right now, but seeing their interest feels good regardless : ).&lt;/p&gt;

&lt;p&gt;There are a few more talks coming up in the next couple of months, but I also hope to find some more time for actual blogging again. I certainly want to start writing a few articles about testing JavaScript.&lt;/p&gt;

&lt;p&gt;--fg&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;display: none;&quot; src=&quot;http://www.debuggable.com/posts/tick/4d5e9729-27b0-435c-952a-41decbdd56cb&quot;&gt;&lt;/p&gt;
</description><author>felix@debuggable.com</author><pubDate>Fri, 18 Feb 2011 15:58:33 +0000</pubDate><comments>http://www.debuggable.com/posts/talks-talks-talks:4d5e9729-27b0-435c-952a-41decbdd56cb</comments></item></channel></rss>