<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2908475840373457869</id><updated>2011-12-16T04:17:49.638-08:00</updated><category term='jquery'/><category term='ui'/><category term='css'/><category term='javascript'/><category term='unix'/><category term='html'/><category term='photoshop'/><category term='development'/><category term='perl'/><category term='freebsd'/><category term='fedora'/><category term='subversion'/><category term='system administration'/><title type='text'>Milan Adamovsky's Blog</title><subtitle type='html'>Interesting tidbits on various front and back-end technologies.
&lt;br&gt;
Focus: &lt;a href="/search/label/freebsd"&gt;FreeBSD&lt;/a&gt;, &lt;a href="/search/label/perl"&gt;Perl&lt;/a&gt;, &lt;a href="/search/label/javascript"&gt;Javascript&lt;/a&gt;, &lt;a href="/search/label/jquery"&gt;jQuery&lt;/a&gt;, &lt;a href="/search/label/web20"&gt;Web 2.0&lt;/a&gt;, &lt;a href="/search/label/css"&gt;CSS&lt;/a&gt;, &lt;a href="/search/label/photoshop"&gt;Photoshop&lt;/a&gt;, &lt;a href="/search/label/ui"&gt;UI&lt;/a&gt;</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-5419688244480390329</id><published>2011-12-15T14:40:00.000-08:00</published><updated>2011-12-16T04:17:49.648-08:00</updated><title type='text'>Fastest Loop in JavaScript</title><content type='html'>&lt;p&gt;UPDATE: Turns out that the benchmark yielded skewed results.  The quest goes on for the holy grail of fastest loops.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;See my &lt;a href="http://www.jsperf.com/for-vs-while/11"&gt;benchmark here&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-5419688244480390329?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/5419688244480390329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2011/12/fastest-loop-in-javascript.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/5419688244480390329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/5419688244480390329'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2011/12/fastest-loop-in-javascript.html' title='Fastest Loop in JavaScript'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-6115557512402832893</id><published>2011-08-12T20:37:00.000-07:00</published><updated>2011-08-12T20:37:44.870-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><category scheme='http://www.blogger.com/atom/ns#' term='html'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Leverage CSS when resizing HTML elements using JavaScript</title><content type='html'>&lt;p&gt;The inspiration for this article comes from me seeing, to this day, major frameworks like &lt;a href="http://www.sencha.com/products/js/"&gt;ExtJS&lt;/a&gt; using JavaScript as a shortcut to re-size HTML elements on a page - a task that CSS is much better suited for.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You may now be asking yourself: &lt;i&gt;What exactly is the problem?&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The problem is that when JavaScript is used to manipulate elements on the page, it will give a slower performance than if we leave it up to CSS.  This means a deteriorated user experience. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Many web developers resort to JavaScript to allow a user to re-size a column, row, content area, or any other element on a page.  This is usually done by assigning a calculated value to the &lt;i&gt;width&lt;/i&gt; or &lt;i&gt;height&lt;/i&gt; of the element via JavaScript.  This works.  It gets the job done.  It's just not as responsive to the end user.  Until now most developers have settled for this behavior under the premise there is no alternative.  But there is.  Read on.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;A basic understanding of how a browser renders a page will help appreciate the solution to the problem, while at the same time gain a better understanding for what the problem is.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Web Page Load Sequence&lt;/h4&gt;&lt;p&gt;This is an extremely high-level overview of the way a web page gets rendered on the screen:&lt;br /&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt; DOM&lt;br /&gt;&lt;/li&gt;&lt;li&gt; CSS&lt;br /&gt;&lt;/li&gt;&lt;li&gt; JavaScript&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The reason this is a high-level overview is because technically all of these steps happen sequentially in the order they appear on the page.  This means that the DOM is being parsed by the browser, so it starts reading the HTML tag, then it hits the &amp;lt;head&amp;gt; tag where it then downloads the CSS, then JavaScript, then it executes the JavaScript as it continues loading the DOM, where it can again find more JavaScript before the DOM is fully loaded.  Going into further detail is beyond the scope of this article.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Evidently the load order cannot be put into words as easily as we may want it to be, but one thing that is clear is that the &lt;i&gt;CSS&lt;/i&gt; is applied faster than JavaScript - and this is key.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;By simplifying the understanding of the load order to the aforementioned sequence it becomes easier to understand that we should try to leverage CSS wherever possible.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;JavaScript Re-Sizing&lt;/h4&gt;&lt;p&gt;A simple example of re-sizing would be a two column layout where we want the left column to be re-sizable.&lt;br /&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_7MiP2bsKJ-Y/THiYhCxZNfI/AAAAAAAAACg/I093k29joNk/s1600/resize.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_7MiP2bsKJ-Y/THiYhCxZNfI/AAAAAAAAACg/I093k29joNk/s320/resize.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;Needless to say when we re-size &lt;i&gt;Column 1&lt;/i&gt; the second column's width must be adjusted accordingly.  This is where the faux-pas occurs in today's web development:  Both of the columns' widths are calculated and adjusted accordingly.&lt;br /&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_7MiP2bsKJ-Y/THiqJ0nom8I/AAAAAAAAACo/-C-mre09z7k/s1600/resize2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_7MiP2bsKJ-Y/THiqJ0nom8I/AAAAAAAAACo/-C-mre09z7k/s320/resize2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;For simplicity's sake I'm keeping the example down to two columns, but in real life applications these will be all sorts of elements that will be re-sized depending on something else being dragged, re-sized, or slid.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Simply put, today, if we adjust &lt;i&gt;A&lt;/i&gt;, we need to calculate its new width or height, and substract or add the difference between the old width/height and the new width/height accordingly to &lt;i&gt;B&lt;/i&gt;, &lt;i&gt;C&lt;/i&gt;, &lt;i&gt;D&lt;/i&gt;, etc... on the page.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;CSS Re-Sizing&lt;/h4&gt;&lt;p&gt;Whenever I lead front-end development teams or conduct workshops there is a simple rule to developing websites that I promote: &lt;i&gt;"Develop for fluidity or elasticity and then fix it (if necessary)."&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In other words, I encourage my teams to develop markup in such a way that the layout is elastic (or fluid) so that if requirements ever change in regards to dimensions, the effort won't require any markup, CSS, or JavaScript adjustments.  Another benefit is that developing for elasticity requires a higher order of discipline and knowledge, so it inherently enforces adherence to cross-browser compatibility development and web standards.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Once the web-page is set for elasticity (or fluidity), it can then be set to whatever fixed dimensions without compromising the page's integrity.  This is not the case inversely.  Another side-effect becomes that swapping elements in and out of the markup becomes more flexible, and most of the times the elements around the altered element will automagically fall into place - because we coded it to be fluid.  As a result, this flexibility has prompted me to name this layout coding style a &lt;i&gt;flexible&lt;/i&gt; layout.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;I like disciplined development.  This is the difference between coding and &lt;i&gt;engineering&lt;/i&gt; a solution.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Engineering websites for elasticity requires the markup to be coded in such a way to maximize the use of CSS for all internal calculations and relying less on JavaScript where not necessary.  This means we can completely by-pass the JavaScript engine for layout - &lt;i&gt;as we should&lt;/i&gt;.  CSS works so intimately with the browser, any changes to the styling of an element has a virtually immediate visual effect.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Normally however, elastic or fluid layout are usually reserved for the anticipation of a browser re-size (e.g. &lt;i&gt;if we re-size the entire browser, we don't want the website to break.&lt;/i&gt;). &lt;br /&gt;&lt;/p&gt;&lt;p&gt;This is a great idea, but why limit ourselves to a browser re-size?  We can apply this same concept to every element on the page; but how do we do that if CSS doesn't support JavaScript-like calculations?  After all, we &lt;i&gt;need&lt;/i&gt; to &lt;i&gt;calculate&lt;/i&gt; the new width according to user's interaction. &lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;The proposed solution does not rely purely on CSS as this would usually be impossible since the re-sizing of an element occurs upon a user's interaction.  This means that we &lt;i&gt;need&lt;/i&gt; to still rely on JavaScript for some of the calculations, but as I mentioned above we should try to limit this to a minimum.  This is exactly what we will do.&lt;/p&gt;&lt;p&gt;The idea is very simple.  We will calculate only one of the columns via JavaScript and let the other columns follow blindly via CSS.  In other words: We will only explicitly calculate &lt;i&gt;one&lt;/i&gt; value as opposed to however many values there are columns.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;p&gt;The way we accomplish the above is by letting the JavaScript give an explicit value of one of the re-sized elements.  The other elements that are dependent on those dimensions to figure out how wide or tall it should be (such as a sibling column or row) will then simply have a respective width or height value of &lt;i&gt;auto&lt;/i&gt;.  This is where the magic happens.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Now because we leave the width or height value to &lt;i&gt;auto&lt;/i&gt; we can now leverage the CSS engine to calculate the values for us - rather than have JavaScript do it. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;This will give us something similar to this:&lt;/p&gt;&lt;style&gt;.demo_container {  overflow: hidden; }.down {  bottom: 0; }.demo_container .drag_content {  background-color: #5a5a5a; }.horizontally:hover {  cursor: e-resize; }.horizontally {  height: 100%;  position: absolute;    top: 0;  width: 5px; }.left {  left: 0; }.right {  right: 0; }.up {  top: 0; }.vertically {  position: absolute;    left: 0;  height: 5px;  width: 100%; }.vertically:hover {  cursor: s-resize; }.demo_container #ad_container {  background-color: #a7a7a7;  height: 100%;  position: absolute;  right: 0px;   width: 100px; }.demo_container #body_content {  background-color: #fff;  border: 1px solid #000;  height: auto;  position: absolute;  left: 10px;  right: 10px;  top: 10px;  bottom: 10px;  width: auto; }.demo_container #header_container {  top: 0px;  background-color: #848484;  height: 100px;  position: absolute;   width: 100%; }.demo_container #content_container {  background-color: #d6d6d6;  height: 100%;  left: 100px;  position: absolute;  width: auto; }.demo_container #footer_container {  bottom: 0px;  background-color: #bbb;  height: 100px;  position: absolute;   width: 100%; }.demo_container #main_content {  background-color: #e0e0e0;  width: 100%;  top: 100px;  position: absolute;  bottom: 100px;  height: auto; }.demo_container #sub_main_content {  background-color: #e0e0e0;  width: 100%;  top: 100px;  position: absolute;  bottom: 0px;  height: auto; }.demo_container #sub_nav_container {  top: 0px;  background-color: #bbb;  height: 100px;  position: absolute;   width: 100%; }.first.demo_container #content_container {  right: 0px; }.second.demo_container #content_container {  right: 100px; }&lt;/style&gt;&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"&gt;&lt;/script&gt;&lt;script&gt;$(document).ready(function() {  var resizeModel = {};  resizeModel = {                 direction : {                              axis : '',                              name : '',                              sizing : '',                              padding : ''                                                           },                 elements : {                             a : '',                             b : ''                            },                 namespace : 'resizer',                 initiatedBy : null,                 mouseState : 'idle'                };  $(this).bind(['mouseup', resizeModel.namespace].join('.'),                function (eventObject)                 {                 resizeModel.mouseState = 'up';                })         .bind(['mousemove', resizeModel.namespace].join('.'),                function (eventObject)                {                 if (resizeModel.mouseState == 'down')                  {                   var viewportSize = $(window)[resizeModel.direction.sizing]();                       clientAxis = resizeModel.direction.axis,                       paddingCSS = {},                       offSet = resizeModel.direction.offset,                       elementSize = resizeModel.direction.name == 'left' || resizeModel.direction.name == 'up'                                       ? viewportSize - eventObject[clientAxis] + 2                                      : eventObject[clientAxis] - offSet + 2;                   paddingCSS[resizeModel.direction.padding] = [elementSize,'px'].join('');                   resizeModel.elements.a[resizeModel.direction.sizing](elementSize);                   resizeModel.elements.b.css(paddingCSS);                  }                })         .delegate(".drag_content",                   ['mousedown', resizeModel.namespace].join('.'),                   function ()                     {                     resizeModel.initiatedBy = $(this);                                         var resizeParent = resizeModel.initiatedBy.parent();                                       resizeModel.elements = {                                             a : resizeParent,                                             b : resizeModel.initiatedBy.hasClass("right") || resizeModel.initiatedBy.hasClass("down")                                                   ? resizeParent.next()                                                  : resizeParent.prev()                                            };                     resizeModel.direction = resizeModel.initiatedBy.hasClass("down")                                              ? {                                                 axis : 'clientY',                                                 name : 'down',                                                 offset : resizeModel.elements.a.offset().top,                                                                                                  sizing : 'height',                                                 padding : 'top'                                                }                                              : resizeModel.initiatedBy.hasClass("left")                                                 ? {                                                    axis : 'clientX',                                                    name : 'left',                                                    offset : resizeModel.elements.a.offset().left,                                                                                                        sizing : 'width',                                                    padding : 'right'                                                   }                                                 : resizeModel.initiatedBy.hasClass("right")                                                    ? {                                                       axis : 'clientX',                                                       name : 'right',                                                       offset : resizeModel.elements.a.offset().left,                                                                                                              sizing : 'width',                                                       padding : 'left'                                                      }                                                    : resizeModel.initiatedBy.hasClass("up")                                                       ? {                                                          axis : 'clientY',                                                          name : 'up',                                                          offset : resizeModel.elements.a.offset().top,                                                                                                                    sizing : 'height',                                                          padding : 'bottom'                                                         }                                                       : 0;                                     resizeModel.mouseState = "down";                    });});     &lt;/script&gt;&lt;div class="first demo_container" style="border: 1px solid black; width: 99%; min-height: 120px; position: relative"&gt;&lt;div style="background-color: #a7a7a7; height: 100%; position: absolute; width: 100px"&gt;&lt;div class="drag_content horizontally right"&gt;&lt;/div&gt;&lt;/div&gt;&lt;div id="content_container"&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In the above example simply move the mouse on top of the &lt;i&gt;drag bar&lt;/i&gt; (the dark gray bar), and you will notice your mouse pointer change to let the bar be dragged left or right.  Doing so we can see how at any given time only one of the sides is being calculated by JavaScript while having the other side handled by the CSS engine. &lt;/p&gt;&lt;p&gt;For the sake of being able to show this example inline in this page I had to make some minor adjustments to the code, so follow the code examples rather than trying to view the source of the live example within this page.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We can then use this same principle recursively, and at any given time have JavaScript (the slower of the two) perform only one calculation while letting the CSS engine (the faster of the two) handle all others.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Had we not done this we would have to set the explicit value to the one element, and then set another explicit value on &lt;i&gt;all&lt;/i&gt; elements that are dependent on this value.  As you can imagine, this could easily turn to many many many calculations, with each slowing down the performance of the web application or website.&lt;br /&gt;&lt;/p&gt;&lt;h5&gt;Step 1&lt;/h5&gt;&lt;p&gt;The first thing we want to do is take care of our markup.  As a good front-end developer we will usually work on our markup first, followed by the CSS, followed by JavaScript, and finally followed by fine-tuning where all three technologies will be juggled to get the desired result.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The markup is pretty straight forward.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The above example can be implemented with something simple as:&lt;br /&gt;&lt;/p&gt;&lt;pre name="code" class="js"&gt; &amp;lt;body id="index_container"&gt;&lt;br /&gt;   &amp;lt;div id="menu_container"&gt;&lt;br /&gt;     &amp;lt;div class="drag_content horizontally right"&gt;&lt;br /&gt;     &amp;lt;/div&gt;&lt;br /&gt;   &amp;lt;/div&gt;&lt;br /&gt;   &amp;lt;div id="content_container"&gt;&lt;br /&gt;   &amp;lt;/div&gt;&lt;br /&gt; &amp;lt;/body&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above example is simple enough to understand the needed moving parts to get the above implementation going.  Below we will make a full fledged multi-frame layout to show how easy it is to extend the layout.&lt;br /&gt;&lt;/p&gt;&lt;pre name="code" class="js"&gt; &amp;lt;body id="index_container"&gt;&lt;br /&gt;   &amp;lt;div id="menu_container"&gt;&lt;br /&gt;     &amp;lt;div class="drag_content horizontally right"&gt;&lt;br /&gt;     &amp;lt;/div&gt;&lt;br /&gt;   &amp;lt;/div&gt;&lt;br /&gt;   &amp;lt;div id="content_container"&gt;&lt;br /&gt;     &amp;lt;div id="header_container"&gt;&lt;br /&gt;       &amp;lt;div class="drag_content vertically down"&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;     &amp;lt;/div&gt;&lt;br /&gt;     &amp;lt;div id="main_content"&gt;&lt;br /&gt;       &amp;lt;div id="sub_nav_container"&gt;&lt;br /&gt;         &amp;lt;div class="drag_content vertically down"&gt;&lt;br /&gt;         &amp;lt;/div&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;       &amp;lt;div id="sub_main_content"&gt;&lt;br /&gt;         &amp;lt;div id="body_content"&gt;&lt;br /&gt;           &amp;lt;div id="navigation_content"&gt;&lt;br /&gt;           &amp;lt;/div&gt;&lt;br /&gt;           &amp;lt;p&gt;&lt;br /&gt;             &lt;i&gt;Here goes some content&lt;/i&gt;&lt;br /&gt;           &amp;lt;/p&gt;&lt;br /&gt;         &amp;lt;/div&gt; &lt;br /&gt;       &amp;lt;/div&gt;       &lt;br /&gt;     &amp;lt;/div&gt;&lt;br /&gt;     &amp;lt;div id="footer_container"&gt;&lt;br /&gt;       &amp;lt;div class="drag_content vertically up"&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;     &amp;lt;/div&gt;&lt;br /&gt;   &amp;lt;/div&gt;&lt;br /&gt;   &amp;lt;div id="ad_container"&gt;&lt;br /&gt;     &amp;lt;div class="drag_content horizontally left"&gt;&lt;br /&gt;     &amp;lt;/div&gt;&lt;br /&gt;   &amp;lt;/div&gt;&lt;br /&gt; &amp;lt;/body&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Copy and paste this into an HTML file alongside the given CSS at the bottom of this article to see the output.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The naming convention is pretty self-explanatory of the roles of the various elements - with a few exceptions.  Don't let this be confusing.  Feel free to begin with the simple example and gradually move your way up.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You will notice a few elements that have the class &lt;i&gt;drag_content&lt;/i&gt;.  These elements are the "drag bars" that allow a user to hold and drag them to re-size the element.  In other words this is a simulated &lt;i&gt;control&lt;/i&gt; just like a button, drop-down, or scroll-bar would be.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We further enhance the drag bar by giving it some intelligence on what it is allow to do.  The one piece of information we give it is the &lt;i&gt;direction&lt;/i&gt; a user can re-size it.  This is helpful to give the user a visual cue by changing the mouse pointer to the respective image so the user knows which way to drag.  A class value of &lt;i&gt;horizontally&lt;/i&gt; means the user can drag left to right, and a value of &lt;i&gt;vertically&lt;/i&gt; will let the user know to drag top to bottom.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The last piece to the puzzle is to understand what the &lt;i&gt;up&lt;/i&gt;, &lt;i&gt;down&lt;/i&gt;, &lt;i&gt;left&lt;/i&gt;, and &lt;i&gt;right&lt;/i&gt; mean.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Each of these drag bars are actually inside the containers.  This means that you have to decide &lt;i&gt;in which&lt;/i&gt; container the drag bar will actually be.  Once that is decided you have to decide on which of the walls the drag bar should be.&lt;br /&gt;&lt;/p&gt;&lt;h5&gt;Step 2&lt;/h5&gt;&lt;p&gt;Naturally the next step becomes the actual definition of the various classes and ids.  This means CSS is our next technology of concern.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Take a minute to go through the CSS below.&lt;br /&gt;&lt;/p&gt;&lt;pre name="code" class="js"&gt;*&lt;br /&gt; {&lt;br /&gt;  margin: 0;&lt;br /&gt;  padding: 0;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;body&lt;br /&gt; {&lt;br /&gt;  background-color: #bcbcbc;&lt;br /&gt;  height: 100%;&lt;br /&gt;  width: 100%;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;p &lt;br /&gt; {&lt;br /&gt;  background-color: #fff;&lt;br /&gt;  border: 1px solid #000;&lt;br /&gt;  left: 10px;&lt;br /&gt;  padding: 12px;&lt;br /&gt;  position: absolute;&lt;br /&gt;  right: 10px;&lt;br /&gt;  top: 50px;&lt;br /&gt;  width: auto;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;.down&lt;br /&gt; {&lt;br /&gt;  bottom: 0;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;.drag_content&lt;br /&gt; {&lt;br /&gt;  background-color: #5a5a5a;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;.horizontally:hover&lt;br /&gt; {&lt;br /&gt;  cursor: e-resize;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;.horizontally&lt;br /&gt; {&lt;br /&gt;  height: 100%;&lt;br /&gt;  position: absolute;  &lt;br /&gt;  top: 0;&lt;br /&gt;  width: 5px;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;.left&lt;br /&gt; {&lt;br /&gt;  left: 0;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;.right&lt;br /&gt; {&lt;br /&gt;  right: 0;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;.up&lt;br /&gt; {&lt;br /&gt;  top: 0;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;.vertically&lt;br /&gt; {&lt;br /&gt;  position: absolute;  &lt;br /&gt;  left: 0;&lt;br /&gt;  height: 5px;&lt;br /&gt;  width: 100%;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;.vertically:hover&lt;br /&gt; {&lt;br /&gt;  cursor: s-resize;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#ad_container&lt;br /&gt; {&lt;br /&gt;  background-color: #a7a7a7;&lt;br /&gt;  height: 100%;&lt;br /&gt;  position: absolute;&lt;br /&gt;  right: 0px; &lt;br /&gt;  width: 100px;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#body_content&lt;br /&gt; {&lt;br /&gt;  background-color: #fff;&lt;br /&gt;  border: 1px solid #000;&lt;br /&gt;  height: auto;&lt;br /&gt;  position: absolute;&lt;br /&gt;  left: 10px;&lt;br /&gt;  right: 10px;&lt;br /&gt;  top: 10px;&lt;br /&gt;  bottom: 10px;&lt;br /&gt;  width: auto;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#content_container&lt;br /&gt; {&lt;br /&gt;  background-color: #d6d6d6;&lt;br /&gt;  height: 100%;&lt;br /&gt;  left: 100px;&lt;br /&gt;  position: absolute;&lt;br /&gt;  right: 100px;&lt;br /&gt;  width: auto;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#footer_container&lt;br /&gt; {&lt;br /&gt;  bottom: 0px;&lt;br /&gt;  background-color: #bbb;&lt;br /&gt;  height: 100px;&lt;br /&gt;  position: absolute; &lt;br /&gt;  width: 100%;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#header_container&lt;br /&gt; {&lt;br /&gt;  top: 0px;&lt;br /&gt;  background-color: #848484;&lt;br /&gt;  height: 100px;&lt;br /&gt;  position: absolute; &lt;br /&gt;  width: 100%;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#main_content&lt;br /&gt; {&lt;br /&gt;  background-color: #e0e0e0;&lt;br /&gt;  width: 100%;&lt;br /&gt;  top: 100px;&lt;br /&gt;  position: absolute;&lt;br /&gt;  bottom: 100px;&lt;br /&gt;  height: auto;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#menu_container&lt;br /&gt; {&lt;br /&gt;  background-color: #a7a7a7;&lt;br /&gt;  height: 100%;&lt;br /&gt;  position: absolute; &lt;br /&gt;  width: 100px;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#navigation_content&lt;br /&gt; {&lt;br /&gt;  background-color: #fff;&lt;br /&gt;  border: 1px solid #000;&lt;br /&gt;  height: 20px;&lt;br /&gt;  left: 10px;&lt;br /&gt;  position: absolute;&lt;br /&gt;  right: 10px;&lt;br /&gt;  top: 10px;&lt;br /&gt;  width: auto;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#sub_main_content&lt;br /&gt; {&lt;br /&gt;  background-color: #e0e0e0;&lt;br /&gt;  width: 100%;&lt;br /&gt;  top: 100px;&lt;br /&gt;  position: absolute;&lt;br /&gt;  bottom: 0px;&lt;br /&gt;  height: auto;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#sub_nav_container&lt;br /&gt; {&lt;br /&gt;  top: 0px;&lt;br /&gt;  background-color: #bbb;&lt;br /&gt;  height: 100px;&lt;br /&gt;  position: absolute; &lt;br /&gt;  width: 100%;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The first thing that can be observed is the &lt;a href="http://milan.adamovsky.com/2010/04/advanced-css-style-order.html"&gt;clean organization of the CSS&lt;/a&gt;.  This is always good housekeeping that I cannot stress enough.  In my workshops I always take a minute to remind developers to take time to follow the intuitive way of organizing that I describe in &lt;a href="http://milan.adamovsky.com/2010/04/advanced-css-style-order.html"&gt;this post&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;We are not going to explore &lt;i&gt;why&lt;/i&gt; we use all of the various CSS properties as that is out of scope for this post.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The main point to understand on the CSS is that with respect to sizing, it defines the &lt;i&gt;default&lt;/i&gt; - or starting dimensions - of the various containers.  Remember: the goal of this type of coding is to minimize the use of JavaScript and maximize the use of CSS.  In this case all definitions are handled by CSS, so no worries here - with one caveat: only size one side and leave the other side's dimension set to &lt;i&gt;auto&lt;/i&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Let's break it down.&lt;br /&gt;&lt;/p&gt;&lt;pre name="code" class="js"&gt;#content_container&lt;br /&gt; {&lt;br /&gt;  background-color: #d6d6d6;&lt;br /&gt;  height: 100%;&lt;br /&gt;  left: 100px;&lt;br /&gt;  position: absolute;&lt;br /&gt;  right: 100px;&lt;br /&gt;  width: auto;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#menu_container&lt;br /&gt; {&lt;br /&gt;  background-color: #a7a7a7;&lt;br /&gt;  height: 100%;&lt;br /&gt;  position: absolute; &lt;br /&gt;  width: 100px;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The first thing to observe is the &lt;i&gt;position&lt;/i&gt;.  Notice that in this type of setup all of the containers need to be absolutely positioned.  The reason for this is because we want them to conveniently cover all available space within their respective areas.  If this doesn't make sense, don't worry about it, just know to &lt;i&gt;position: absolute&lt;/i&gt; the containers that you are interested in be re-sizable.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The second thing to notice is that in our simple example above, our left container is the &lt;i&gt;menu_container&lt;/i&gt; with a default width of &lt;i&gt;100px&lt;/i&gt; (which can be any value you desire) and our right container is the &lt;i&gt;content_container&lt;/i&gt; that has a width set to &lt;i&gt;auto&lt;/i&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Now this is the interesting part:  We have one of the containers' width set to a numeric value and the other container's width set to &lt;i&gt;auto&lt;/i&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The container that gets the numeric value is the container whose width will be changed via JavaScript upon a user's interaction (e.g. dragging).  The JavaScript code responsible for this can be found below in &lt;a href="#step3"&gt;Step 3&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Assuming a user drags the bar to the right 80 pixels; this would cause JavaScript to take the existing width (100px as defined by CSS above) and adds 80 pixels (had the user dragged it to the left, it would &lt;i&gt;subtract&lt;/i&gt; 80 pixels).  In this case it would result at a final width of &lt;i&gt;180px&lt;/i&gt; - and we only did this one addition, no subtraction (or vice-versa).  Neat. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;The next step is to take that number (180px) and apply it to the other container (whose width is set to &lt;i&gt;auto&lt;/i&gt;) but not to the width but rather to its &lt;i&gt;left&lt;/i&gt; in this case (but it could be &lt;i&gt;right&lt;/i&gt;, &lt;i&gt;top&lt;/i&gt;, &lt;i&gt;bottom&lt;/i&gt; depending on the direction of the drag bar).  The reason we need to do this is to allow the &lt;i&gt;width: auto&lt;/i&gt; to know the area it needs to cover.  Keep in mind that this is a calculation that is done by the CSS engine so it's okay.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;You will notice that any container that has a width of &lt;i&gt;auto&lt;/i&gt; has both a &lt;i&gt;left&lt;/i&gt; and &lt;i&gt;right&lt;/i&gt; value.  This is necessary for &lt;i&gt;width: auto&lt;/i&gt; to work as we would expect it to.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The final thing to notice from the more complex example is that these same principles apply respectively for any direction the containers can be re-sized to.  This means we can apply everything we've learned up to this point and make the necessary adjustments for it to make relative sense.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;At this point as a quick recap:  Copy the markup and the CSS of the complex example above to see how it all falls together.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;A great exercise is to try to add a new row or column that can be re-sized following the aforementioned principles.&lt;br /&gt;&lt;/p&gt;&lt;a name="step3"&gt;&lt;/a&gt;&lt;h5&gt;Step 3&lt;/h5&gt;&lt;p&gt;Here is an example of how the code could work using jQuery.  Keep in mind that though I use jQuery in this example, but the logic would work the same with any library, framework, and/or core JavaScript.&lt;/p&gt;&lt;pre name="code" class="js"&gt;$(document).ready(function() {&lt;br /&gt;&lt;br /&gt;  var resizeModel = {};&lt;br /&gt;  resizeModel = {&lt;br /&gt;                 direction : {&lt;br /&gt;                              axis : '',&lt;br /&gt;                              name : '',&lt;br /&gt;                              sizing : '',&lt;br /&gt;                              padding : ''                              &lt;br /&gt;                             },&lt;br /&gt;                 elements : {&lt;br /&gt;                             a : '',&lt;br /&gt;                             b : ''&lt;br /&gt;                            },&lt;br /&gt;                 namespace : 'resizer',&lt;br /&gt;                 initiatedBy : null,&lt;br /&gt;                 mouseState : 'idle'&lt;br /&gt;                };&lt;br /&gt; &lt;br /&gt;  $(this).bind(['mouseup', resizeModel.namespace].join('.'), &lt;br /&gt;               function (eventObject) &lt;br /&gt;                {&lt;br /&gt;                 resizeModel.mouseState = 'up';&lt;br /&gt;                })&lt;br /&gt;         .bind(['mousemove', resizeModel.namespace].join('.'), &lt;br /&gt;               function (eventObject)&lt;br /&gt;                {&lt;br /&gt;                 if (resizeModel.mouseState == 'down')&lt;br /&gt;                  {&lt;br /&gt;                   var viewportSize = $(window)[resizeModel.direction.sizing]();&lt;br /&gt;                       clientAxis = resizeModel.direction.axis,&lt;br /&gt;                       paddingCSS = {},&lt;br /&gt;                       offSet = resizeModel.direction.offset,&lt;br /&gt;                       elementSize = resizeModel.direction.name == 'left' || resizeModel.direction.name == 'up' &lt;br /&gt;                                      ? viewportSize - eventObject[clientAxis] + 2&lt;br /&gt;                                      : eventObject[clientAxis] - offSet + 2;&lt;br /&gt;&lt;br /&gt;                   paddingCSS[resizeModel.direction.padding] = [elementSize,'px'].join('');&lt;br /&gt;                   resizeModel.elements.a[resizeModel.direction.sizing](elementSize);&lt;br /&gt;                   resizeModel.elements.b.css(paddingCSS);&lt;br /&gt;                  }&lt;br /&gt;                })&lt;br /&gt;         .delegate(".drag_content",&lt;br /&gt;                   ['mousedown', resizeModel.namespace].join('.'),&lt;br /&gt;                   function () &lt;br /&gt;                    {&lt;br /&gt;                     resizeModel.initiatedBy = $(this);&lt;br /&gt;                     &lt;br /&gt;                     var resizeParent = resizeModel.initiatedBy.parent();&lt;br /&gt;                     &lt;br /&gt;                     resizeModel.elements = {&lt;br /&gt;                                             a : resizeParent,&lt;br /&gt;                                             b : resizeModel.initiatedBy.hasClass("right") || resizeModel.initiatedBy.hasClass("down") &lt;br /&gt;                                                  ? resizeParent.next()&lt;br /&gt;                                                  : resizeParent.prev()&lt;br /&gt;                                            };&lt;br /&gt;                     resizeModel.direction = resizeModel.initiatedBy.hasClass("down")&lt;br /&gt;                                              ? {&lt;br /&gt;                                                 axis : 'clientY',&lt;br /&gt;                                                 name : 'down',&lt;br /&gt;                                                 offset : resizeModel.elements.a.offset().top,                                                 &lt;br /&gt;                                                 sizing : 'height',&lt;br /&gt;                                                 padding : 'top'&lt;br /&gt;                                                }&lt;br /&gt;                                              : resizeModel.initiatedBy.hasClass("left")&lt;br /&gt;                                                 ? {&lt;br /&gt;                                                    axis : 'clientX',&lt;br /&gt;                                                    name : 'left',&lt;br /&gt;                                                    offset : resizeModel.elements.a.offset().left,                                                    &lt;br /&gt;                                                    sizing : 'width',&lt;br /&gt;                                                    padding : 'right'&lt;br /&gt;                                                   }&lt;br /&gt;                                                 : resizeModel.initiatedBy.hasClass("right")&lt;br /&gt;                                                    ? {&lt;br /&gt;                                                       axis : 'clientX',&lt;br /&gt;                                                       name : 'right',&lt;br /&gt;                                                       offset : resizeModel.elements.a.offset().left,                                                       &lt;br /&gt;                                                       sizing : 'width',&lt;br /&gt;                                                       padding : 'left'&lt;br /&gt;                                                      }&lt;br /&gt;                                                    : resizeModel.initiatedBy.hasClass("up")&lt;br /&gt;                                                       ? {&lt;br /&gt;                                                          axis : 'clientY',&lt;br /&gt;                                                          name : 'up',&lt;br /&gt;                                                          offset : resizeModel.elements.a.offset().top,                                                          &lt;br /&gt;                                                          sizing : 'height',&lt;br /&gt;                                                          padding : 'bottom'&lt;br /&gt;                                                         }&lt;br /&gt;                                                       : 0;&lt;br /&gt;                &lt;br /&gt;                     resizeModel.mouseState = "down";&lt;br /&gt;                    });&lt;br /&gt;          &lt;br /&gt;});     &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The one point worth mentioning is that all these events are bound to the document's events since the events we are interested in are global events.  This is why you will see the events bound to &lt;i&gt;$(this)&lt;/i&gt;.  The rest of the code is self-explanatory.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;At this point simply combine the markup, CSS, and JavaScript to see it all come together.  Don't forget to use FireBug or a comparable tool to observe everything in real-time we covered.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-6115557512402832893?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/6115557512402832893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2011/08/leverage-css-when-resizing-html.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/6115557512402832893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/6115557512402832893'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2011/08/leverage-css-when-resizing-html.html' title='Leverage CSS when resizing HTML elements using JavaScript'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_7MiP2bsKJ-Y/THiYhCxZNfI/AAAAAAAAACg/I093k29joNk/s72-c/resize.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-5698576329823094356</id><published>2011-01-16T12:04:00.000-08:00</published><updated>2011-01-16T13:56:53.395-08:00</updated><title type='text'>Internet Explorer 6's 1px Gap Bug Solution</title><content type='html'>&lt;p&gt;If you are still coding for Internet Explorer 6 ("IE6") cross-browser compatibility, you may have encountered the &lt;i&gt;&lt;a href="http://www.pmob.co.uk/temp/onepxgap.htm"&gt;1px gap bug&lt;/a&gt;&lt;/i&gt;.  In brief, this bug adds a gap on absolutely positioned elements when the parent container's width is an odd number.&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;Problem&lt;/h3&gt;&lt;div class="separator" style="float: right;"&gt;&lt;a href="http://4.bp.blogspot.com/_7MiP2bsKJ-Y/TTMfY0sjdRI/AAAAAAAAAC0/YfqbQY2Hjes/s1600/ie6pixel.png" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="212" width="259" src="http://4.bp.blogspot.com/_7MiP2bsKJ-Y/TTMfY0sjdRI/AAAAAAAAAC0/YfqbQY2Hjes/s320/ie6pixel.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;It took me a while before I had a real-life encounter with this bug.  On the right is an illustration of what the bug looks like in IE6.  If you want to see the HTML in IE6, visit &lt;a href="http://www.pmob.co.uk/temp/onepxgap.htm"&gt;this link&lt;/a&gt; by Paul O'Brien where he has a good write-up of the problem.  Again, you will only see the problem when you visit the link using Internet Explorer 6.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In my case I wanted to create tabs that have a little 1x1 pixel &lt;i&gt;div&lt;/i&gt; in the upper left and upper right corners of the tabs to give the illusion of a very subtle "rounded" corner.  Obviously, this is a scenario where one pixel make and breaks the illusion.  Consider the magnified illustration to the right as a depiction of the tab where the two squares are 1 pixel in height and 1 pixel in width.  &lt;br /&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_7MiP2bsKJ-Y/TTMjfk6ZW1I/AAAAAAAAAC8/dPuLkpzOXUo/s1600/ie6round.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="138" width="259" src="http://1.bp.blogspot.com/_7MiP2bsKJ-Y/TTMjfk6ZW1I/AAAAAAAAAC8/dPuLkpzOXUo/s320/ie6round.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;The illustration to the left shows the intended illusion.  The image is magnified 20x to give a clear visual of the effect.  It becomes clear that we need the right div to be flush with the container to achieve the desired result, and that being one pixel off would ruin it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;As a reminder, this &lt;i&gt;only&lt;/i&gt; happens in Internet Explorer 6 when the width of the container is an odd number (e.g. &lt;i&gt;155&lt;/i&gt; pixels).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;My initial code looked something similar to this:&lt;br /&gt;&lt;/p&gt;&lt;pre name="code" class="js"&gt;&amp;lt;div id="tab_container"&gt;&lt;br /&gt;   &amp;lt;ol&gt;&lt;br /&gt;     &amp;lt;li style="width: 155px"&gt;&lt;br /&gt;       &amp;lt;div style="left: 0px; position: absolute; height: 1px; width: 1px"&gt;&lt;br /&gt;         &amp;lt;!-- comment needed for 1x1px div in ie6 --&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;       &amp;lt;div style="right: 0px; position: absolute; height: 1px; width: 1px"&gt;&lt;br /&gt;         &amp;lt;!-- comment needed for 1x1px div in ie6 --&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;       &amp;lt;a href=""&gt;&lt;br /&gt;         Some random tab text&lt;br /&gt;       &amp;lt;/a&gt;&lt;br /&gt;    &amp;lt;/ol&gt;&lt;br /&gt; &amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The idea was to have the two 1 pixel divs absolutely positioned in the upper corners without floating (though I did try with &lt;i&gt;float: left&lt;/i&gt; and &lt;i&gt;float: right&lt;/i&gt; just the same) - to no avail.  The 1 pixel gap bug kicked in.&lt;/p&gt;&lt;p&gt;In the above I use inline styling for illustration purposes only.  The width of 155 pixels is also hard-coded just for illustrative purposes - this width would usually be dynamically calculated via the CSS engine depending on the content of the tab.  Furthermore, there are some CSS styling on the &lt;i&gt;ol&lt;/i&gt; and &lt;i&gt;li&lt;/i&gt; elements to get them to show as inline tabs.  I do not include these style properties in this blog as not to clutter the topic at hand.  You can find the complete code in the attached zip file (coming soon).&lt;/p&gt;&lt;h3 style="clear: both; display: block"&gt;Solution&lt;/h3&gt;&lt;p&gt;Upon scouring the Internet, you will quickly see that there is no practical solution.  The solution presented by Paul O'Brien works well with defined widths, but if we have the luxury of hard-coding dimensions, we may as well just nudge the dimensions for IE6 in our stylesheet and keep our markup clean from clutter markup.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The goal of good web development is to keep your markup as lean as possible, meaning keeping various helper wrappers to a minimum.  Keep this in mind.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Having said that, what do we do in fluid layouts where widths can change dynamically?  Simple.  We stop and think. &lt;/p&gt;&lt;h4&gt;Thought Process&lt;/h4&gt;&lt;p&gt;To many programmers CSS is a step away from black magic.  We tend to want to solve problems &lt;i&gt;programmatically&lt;/i&gt; and when that fails we just keep throwing more and more patchwork to the mess until something sticks.  Some will actually &lt;i&gt;stop&lt;/i&gt; and &lt;i&gt;think&lt;/i&gt;, and &lt;i&gt;solve&lt;/i&gt; the &lt;i&gt;logical&lt;/i&gt; problem almost to the effect of a riddle (as opposed to attempt to calculate a solution to a math-like problem).  In other words, CSS is &lt;i&gt;not&lt;/i&gt; black magic - we can still apply logic to solving the problem rather than just pure trial and error (or just giving up and resorting to JavaScript as a last resort.)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;So let's break down the issue.&lt;/p&gt;&lt;ol&gt;&lt;li&gt; We know the problem only happens in Internet Explorer 6.&lt;br /&gt;&lt;li&gt; We know the problem only happens when the width of the container is an odd number.&lt;br /&gt;&lt;li&gt; We know the problem only happens on elements within the container that have an absolute position.&lt;br /&gt;&lt;li&gt; We know of the solution presented by Paul O'Brien where we statically position the element within a container of a &lt;i&gt;fixed&lt;/i&gt; width.&lt;br /&gt;&lt;li&gt; We know there is no known solution to the problem.&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;What was the last point on the list?!  No solution!?  Yes, it's true.  There is no known solution that tackles the problem perfectly - but here I will present how I overcame the problem.&lt;/p&gt;&lt;p&gt;Let's break down what we are going to try to achieve for a solution.&lt;/p&gt;&lt;ol&gt;&lt;li&gt; The one technical cause to the effect we know that we cannot rely on is &lt;i&gt;position: absolute&lt;/i&gt;.  This CSS attribute is off the table.&lt;br /&gt;&lt;li&gt; We want to be able to keep our elements flush with the container even in a dynamically changing width of the container.  In other words, fixed values are off the table.&lt;br /&gt;&lt;li&gt; Do not use JavaScript for a CSS problem!!  JavaScript is off the table.&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;We have pretty much cornered ourselves into a seemingly impossible dilemma:  &lt;i&gt;solve a seemingly unsolvable problem&lt;/i&gt;.  So as I said, our solution may or may not be perfect for every situation, but it may lend itself to many scenarios similar to mine.  So this is where we &lt;i&gt;stop&lt;/i&gt; and &lt;i&gt;think&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;What we &lt;i&gt;have&lt;/i&gt; to do is see what other alternatives we have to absolute positioning, and that would be &lt;i&gt;static&lt;/i&gt; and &lt;i&gt;relative&lt;/i&gt; positioning.  We know that the solution by Paul O'Brien relies on the &lt;i&gt;static&lt;/i&gt; positioning - and we also know that for it to work we need to specify a fixed width container, so it will not lend itself to our fluid layout requirements.  This leaves us with getting creative with seeing how we can use the last option: &lt;i&gt;relative&lt;/i&gt; positioning. &lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_7MiP2bsKJ-Y/TTM5Krh7P5I/AAAAAAAAADE/fApmQc1xxQc/s1600/ie6-1pxlogical.png" imageanchor="1" style="clear:right; float:right; margin-left:1em; margin-bottom:1em"&gt;&lt;img border="0" height="212" width="259" src="http://3.bp.blogspot.com/_7MiP2bsKJ-Y/TTM5Krh7P5I/AAAAAAAAADE/fApmQc1xxQc/s320/ie6-1pxlogical.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;We know that when we float divs in any browser, including IE6, they can grow the container relatively well - without rendering the 1 pixel gap.  This means all we have to do is just split the divs in two logical areas:  &lt;/p&gt;&lt;ol&gt;&lt;li&gt; Fixed width content - content whose width will never change&lt;br /&gt;&lt;li&gt; Dynamic width content - content whose width may change based on content&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;The rectangles in the image illustrate a mental picture of how we cut up the content of the elements.  These areas in turn simply need to be floated left, and they will then fill out the container to the respective width - perfectly. &lt;/p&gt;&lt;p&gt;The new code will then simply look something like this:&lt;/p&gt;&lt;pre name="code" class="js"&gt;&amp;lt;div id="tab_container"&gt;&lt;br /&gt;   &amp;lt;ol&gt;&lt;br /&gt;     &amp;lt;li&gt;&lt;br /&gt;       &amp;lt;div style="float: left; height: 1px; width: 1px"&gt;&lt;br /&gt;         &amp;lt;!-- comment needed for 1x1px div in ie6 --&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;       &amp;lt;div style="float: left"&gt;&lt;br /&gt;         &amp;lt;a href=""&gt;&lt;br /&gt;           Some random tab text&lt;br /&gt;         &amp;lt;/a&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;       &amp;lt;div style="float: left; height: 1px; width: 1px"&gt;&lt;br /&gt;         &amp;lt;!-- comment needed for 1x1px div in ie6 --&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;    &amp;lt;/ol&gt;&lt;br /&gt; &amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_7MiP2bsKJ-Y/TTM-qkLF6KI/AAAAAAAAADM/vCFgWfTl8w4/s1600/ie6-randomfloat.png" imageanchor="1" style="clear:right; float:right; margin-left:1em; margin-bottom:1em"&gt;&lt;img border="0" height="117" width="259" src="http://1.bp.blogspot.com/_7MiP2bsKJ-Y/TTM-qkLF6KI/AAAAAAAAADM/vCFgWfTl8w4/s320/ie6-randomfloat.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;There is one small problem remaining though:  If we float the elements, they will simply be rendered side by side, as shown on the image to the right - but we want the content to take up the full width of the container, as we would if the corner divs were absolutely positioned.&lt;/p&gt;&lt;p&gt;This is where the beauty of negative margins come in.&lt;/p&gt;&lt;p&gt;Normally if we deal with scenarios as mine, where we only deal with one pixel widths, we can get away with having the divs floated side-by-side.  This is because we may actually want some padding around the content to separate it from the edges of the container.  If this is not the case, we can simply compensate for the fixed content widths with negative margins. &lt;/p&gt;&lt;pre name="code" class="js"&gt;&amp;lt;div id="tab_container"&gt;&lt;br /&gt;   &amp;lt;ol&gt;&lt;br /&gt;     &amp;lt;li&gt;&lt;br /&gt;       &amp;lt;div style="float: left; height: 1px; width: 1px"&gt;&lt;br /&gt;         &amp;lt;!-- comment needed for 1x1px div in ie6 --&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;       &amp;lt;div style="float: left: margin-left: -1px; margin-right: -1px"&gt;&lt;br /&gt;         &amp;lt;a href=""&gt;&lt;br /&gt;           Some random tab text&lt;br /&gt;         &amp;lt;/a&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;       &amp;lt;div style="float: left; height: 1px; width: 1px"&gt;&lt;br /&gt;         &amp;lt;!-- comment needed for 1x1px div in ie6 --&gt;&lt;br /&gt;       &amp;lt;/div&gt;&lt;br /&gt;    &amp;lt;/ol&gt;&lt;br /&gt; &amp;lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Notice in the above code that all we do is just tack on a negative margin that equals the width of the fixed content.  This means that in my case since the corner divs are &lt;i&gt;1 pixel&lt;/i&gt; wide, my dynamic content div's margin will take a &lt;i&gt;negative 1 pixel&lt;/i&gt; width on the left and right.  This will yield the result as shown to the left. &lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_7MiP2bsKJ-Y/TTNAQCEoKjI/AAAAAAAAADU/Y5dUt6kWMlY/s1600/ie6-randomabs.png" imageanchor="1" style="clear:left; float:left;margin-right:1em; margin-bottom:1em"&gt;&lt;img border="0" height="117" width="176" src="http://2.bp.blogspot.com/_7MiP2bsKJ-Y/TTNAQCEoKjI/AAAAAAAAADU/Y5dUt6kWMlY/s320/ie6-randomabs.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;We have effectively mimicked the effect of &lt;i&gt;position: absolute&lt;/i&gt; by using &lt;i&gt;position: relative&lt;/i&gt;.  Furthermore we have a relatively unobtrusive cross-browser solution where we do not need to have extra markup, and most importantly this solution works as well in a fixed width as it does in a fluid width! &lt;/p&gt;&lt;p&gt;I hope you enjoy it, and feel free to leave your questions in the comments section below. &lt;/p&gt;&lt;p&gt;You can see a demo page by clicking &lt;a href="https://docs.google.com/uc?id=0B7CcFqmwQIvyYjE1MzA3YTQtZjY4Mi00YTI3LTkxMTktMzQxNDAyOTVhOTc5&amp;hl=en_US"&gt;here&lt;/a&gt;. You can download a copy of the demo page by clicking &lt;a href="https://docs.google.com/uc?id=0B7CcFqmwQIvyYjE1MzA3YTQtZjY4Mi00YTI3LTkxMTktMzQxNDAyOTVhOTc5&amp;export=download&amp;hl=en"&gt;here&lt;/a&gt;. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-5698576329823094356?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/5698576329823094356/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2011/01/internet-explorer-6s-1px-gap-bug.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/5698576329823094356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/5698576329823094356'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2011/01/internet-explorer-6s-1px-gap-bug.html' title='Internet Explorer 6&apos;s 1px Gap Bug Solution'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_7MiP2bsKJ-Y/TTMfY0sjdRI/AAAAAAAAAC0/YfqbQY2Hjes/s72-c/ie6pixel.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-4589827329150815700</id><published>2010-11-16T07:06:00.000-08:00</published><updated>2010-11-29T06:05:16.389-08:00</updated><title type='text'>jQuery Plugin Pattern 2.1</title><content type='html'>&lt;p&gt;After having release the &lt;a href="http://milan.adamovsky.com/2010/09/jquery-plugin-pattern-20.html"&gt;jQuery Plugin Pattern 2.0&lt;/a&gt; I encountered a few situations where the pattern would cause for my plugins to crash and burn - not a good thing to happen with a pattern you are trying to advocate.  These were mere failures of that version that paved the way for the improved pattern.  Behold version 2.1!&lt;/p&gt;&lt;h3&gt;Goals&lt;/h3&gt;&lt;p&gt;This pattern tackles a few wish-list items of mine that I could not find an easy solution to using the official jQuery plugin pattern.  In this post I'm going to list all the goals I'm trying to achieve with this pattern so you can decide if this pattern is for you.&lt;/p&gt;&lt;ol&gt;&lt;li&gt; Backward compatible with jQuery standard plugin authoring method&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Syntax would be &lt;i&gt;$(selector).plugin(args)&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Make plugin chainable&lt;br /&gt;&lt;li&gt; Allow &lt;i&gt;this&lt;/i&gt; to refer to the selected element&lt;br /&gt;&lt;li&gt; Allow methods to be called the jQuery way (as parameters to the plugin)&lt;br /&gt;&lt;/ol&gt;&lt;li&gt; Allow Object Oriented Programming inside plugin&lt;br /&gt;&lt;li&gt; Allow to expose the OOP object instead of the jQuery object&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Allow classical OOP concepts such as inheritance&lt;br /&gt;&lt;/ol&gt;&lt;li&gt; Allow &lt;i&gt;n-depth&lt;/i&gt; levels of methods a la OOP&lt;br /&gt;&lt;li&gt; Allow plugin to act as a namespace&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Syntax would be &lt;i&gt;$(selector).plugin.method()&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Make namespace easily changeable in the event of a naming conflict&lt;br /&gt;&lt;/ol&gt;&lt;li&gt; Allow plugin to be called as a hybrid of standard jQuery mixed with OOP&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Syntax would be &lt;i&gt;$(selector).plugin(args).method()&lt;/i&gt;&lt;br /&gt;&lt;/ol&gt;&lt;li&gt; Make &lt;i&gt;version&lt;/i&gt; a publicly exposed attribute as a standard&lt;br /&gt;&lt;li&gt; Allow for an easy way to expose public interface&lt;br /&gt;&lt;li&gt; Allow for a plugin initializer&lt;br /&gt;&lt;li&gt; Encourage use of closure based getters and setters&lt;br /&gt;&lt;li&gt; Promote a standardized persistent config accessor&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;If you have experience writing plugins you will quickly observe some of the above items would be difficult to achieve using the official pattern.  I am not saying mine is better or worse, but my goal is to marry Object Oriented Programming with jQuery.  That's right: I want to be able the pattern to be a mere wrapper around my Object Oriented code to allow it to be connected to other plugins &lt;i&gt;and&lt;/i&gt; to be able to internally take advantage of jQuery's magic - such as its selectors.&lt;/p&gt;&lt;h3&gt;Barebone Pattern&lt;/h3&gt;&lt;p&gt;Below is a barebone version of the pattern that would usually be copy/pasted into your plugins and then filled in with your own code between the &lt;i&gt;[BEGIN YOUR CODE]&lt;/i&gt; and &lt;i&gt;[END YOUR CODE]&lt;/i&gt;.  Take a time to study the code below and then we will examine a real-life example.&lt;/p&gt;&lt;pre name="code" class="js"&gt;/* jQuery Plugin Pattern 2.1&lt;br /&gt; * Author: Milan Adamovsky&lt;br /&gt; *&lt;br /&gt; * This pattern allows you to write jQuery plugins a lot faster, more consistently,&lt;br /&gt; * and less error prone.  Furthermore it allows namespacing, OOP integration, along&lt;br /&gt; * with other technical benefits.  &lt;br /&gt; *&lt;br /&gt; * There are two "global" (but local) helper methods available throughout each plugin&lt;br /&gt; * and they are:&lt;br /&gt; *&lt;br /&gt; *   getPluginClass() &lt;br /&gt; *   getPluginName()&lt;br /&gt; *&lt;br /&gt; * The getPluginClass() returns the definition of the entire plugin code.  Usually &lt;br /&gt; * this is not needed by the plugin author (you), but in the rare event you would&lt;br /&gt; * need it, here it is.  It is used internally by the plugin pattern.&lt;br /&gt; *&lt;br /&gt; * The getPluginName() returns the name of the plugin's jQuery namespace as defined&lt;br /&gt; * by the initPlugin() method (which is something you, the author, defines).&lt;br /&gt; *&lt;br /&gt; * Attention to JSLint users: this code will not pass due to some advanced paradigms&lt;br /&gt; * in use, though efforts have been taken to minimize these.  Priority was given to&lt;br /&gt; * functionality and syntax correctness so that YUI Compressor can properly minify&lt;br /&gt; * the code.&lt;br /&gt; */ &lt;br /&gt;&lt;br /&gt;(function($)&lt;br /&gt;  {&lt;br /&gt;   initPlugin({&lt;br /&gt;               name : 'asyncLoader'  // plugin name &lt;br /&gt;              });&lt;br /&gt;   &lt;br /&gt;   //----plugin class -- BEGIN--------&lt;br /&gt;   function getPluginClass()&lt;br /&gt;    {&lt;br /&gt;     return function (args)&lt;br /&gt;      {&lt;br /&gt;       // Version - directly exposed to be access via $(...).plugin.version&lt;br /&gt;       this.version = '1.0';&lt;br /&gt;      &lt;br /&gt;       // Public Methods - wrappers containing a reference to the actual function &lt;br /&gt;       this.someMethodA = someMethodA;   // non-chainable method&lt;br /&gt;       this.someMethodB = _(someMethodB);    // chainable method&lt;br /&gt;       &lt;br /&gt;       this.rc = jQuerify;       // required plugin pattern code&lt;br /&gt;&lt;br /&gt;       // getConfig - always used to contain class/plugin arguments&lt;br /&gt;       function getConfig()&lt;br /&gt;        {&lt;br /&gt;         return undefined;       // we define this via setConfig()&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;       // setConfig - always used to set class/plugin arguments, usually used indirectly via initConfig&lt;br /&gt;       function setConfig(args)&lt;br /&gt;        {&lt;br /&gt;         getConfig = function()&lt;br /&gt;                      {&lt;br /&gt;                       return (args);&lt;br /&gt;                      };&lt;br /&gt;        }      &lt;br /&gt;  &lt;br /&gt;       // initConfig - sets default values via jQuery's extend()&lt;br /&gt;       function initConfig(args)&lt;br /&gt;        { &lt;br /&gt;         setConfig($.extend({&lt;br /&gt;                             chainable : true,     // false - this allows us to do something like $(...).plugin(args).method()&lt;br /&gt;                                                   //         this returns the object as the output&lt;br /&gt;                                                   // true  - otherwise, by default, it will assume jQuery native functionality of chainability&lt;br /&gt;                                                   //         this returns what jQuery expects for chaining&lt;br /&gt;                             properties : {}       // any properties that you want to be passed to the plugin.&lt;br /&gt;                            }, args));&lt;br /&gt;         return (this);&lt;br /&gt;        }&lt;br /&gt;  &lt;br /&gt;       //---[BEGIN YOUR CODE below]-------&lt;br /&gt;       //   [Class methods / properties]&lt;br /&gt;&lt;br /&gt;       function someMethodA(args)&lt;br /&gt;        {&lt;br /&gt;         alert('This is our non-chainable method!');&lt;br /&gt;&lt;br /&gt;         return (this);    // we return this to allow classic OOP&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;       function someMethodB(args)&lt;br /&gt;        {&lt;br /&gt;         alert('This is our chainable method!');&lt;br /&gt;&lt;br /&gt;         // we don't have to return anything since the _() takes&lt;br /&gt;         // care of chainability. &lt;br /&gt;        }&lt;br /&gt;     &lt;br /&gt;                &lt;br /&gt;       // initConfig - gets called to set defaults for plugin&lt;br /&gt;       initConfig(args);   // Pattern code - usually just copy/paste&lt;br /&gt;       &lt;br /&gt;       // we put our logic after the method definitions to keep JSLint a&lt;br /&gt;       // little happier.&lt;br /&gt;        &lt;br /&gt;       //---[END YOUR CODE above]----&lt;br /&gt;&lt;br /&gt;       function _ (fn)      // local function that facilitates chainability&lt;br /&gt;        {&lt;br /&gt;         return function (args)&lt;br /&gt;                 {&lt;br /&gt;                  return this.prototype.rc(function () &lt;br /&gt;                                            { &lt;br /&gt;                                             fn.call(this, args); &lt;br /&gt;                                            }); &lt;br /&gt;                 };&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;       function jQuerify(args)  &lt;br /&gt;        {&lt;br /&gt;         if (typeof args == 'function')&lt;br /&gt;          {&lt;br /&gt;           return $.fn.curReturn.each(args);  // handles chaining of method&lt;br /&gt;          }&lt;br /&gt;         else&lt;br /&gt;          {&lt;br /&gt;           initConfig(args);&lt;br /&gt;           &lt;br /&gt;           return getConfig().chainable       // checks for chaining in main plugin&lt;br /&gt;                   ? $.fn.curReturn           // returns chainability hook&lt;br /&gt;                   : $.fn[getPluginName()];   // returns OOP object hook&lt;br /&gt;                                              // getPluginName() is defined in initPlugin()&lt;br /&gt;          }&lt;br /&gt;        };&lt;br /&gt;      };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   if ($.fn.curReturn === undefined)          // checks if a plugin has already loaded environment&lt;br /&gt;    {&lt;br /&gt;     $.fn.extend({                            // if not then it extends jQuery object.&lt;br /&gt;                  curReturn: null,            // declares placeholder&lt;br /&gt;                  jQueryInit: jQuery.fn.init  // saves original jQuery init method&lt;br /&gt;                 });&lt;br /&gt;      &lt;br /&gt;     $.fn.extend({                            // now we overwrite jQuery's internal init() so we&lt;br /&gt;                                              // can intercept the selector and context.&lt;br /&gt;                  init: function( selector, context ) &lt;br /&gt;                         {&lt;br /&gt;                          return jQuery.fn.curReturn = new jQuery.fn.jQueryInit(selector, context);&lt;br /&gt;                         }&lt;br /&gt;                 });&lt;br /&gt;    }&lt;br /&gt;        &lt;br /&gt;   function initPlugin(args)&lt;br /&gt;    {  &lt;br /&gt;     getPluginName = function()&lt;br /&gt;                       {&lt;br /&gt;                        return args.name;    // sets getPluginName() to return jQuery plugin name&lt;br /&gt;                       };&lt;br /&gt;                       &lt;br /&gt;//     console &amp;&amp; console.log(["Initialize", args.name, "plugin."].join(' '));                    &lt;br /&gt;&lt;br /&gt;     try                                       // meat &lt;br /&gt;      {&lt;br /&gt;       var classCode = getPluginClass(),       // get a reference to the plugin OOP code&lt;br /&gt;       _p = new classCode({});                 // instantiate plugin Class (which is OOP)&lt;br /&gt;       $.fn[getPluginName()] = _p.rc;          // insert instantiated plugin into jQuery namespace&lt;br /&gt;       $.extend($.fn[getPluginName()].prototype,_p);  // augment jQuery internals&lt;br /&gt;       $.extend($.fn[getPluginName()],_p);            // same here.&lt;br /&gt;      }&lt;br /&gt;     catch (error)&lt;br /&gt;      {&lt;br /&gt;       alert(error);                           // in case something breaks let us know.&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;   &lt;br /&gt;  })(jQuery);&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-4589827329150815700?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/4589827329150815700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/11/jquery-plugin-pattern-21.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/4589827329150815700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/4589827329150815700'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/11/jquery-plugin-pattern-21.html' title='jQuery Plugin Pattern 2.1'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-4698434565494790047</id><published>2010-11-13T18:20:00.000-08:00</published><updated>2010-11-25T21:37:04.609-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><title type='text'>Pros &amp; Cons of JSLint</title><content type='html'>&lt;p&gt;Douglas Crockford is unquestionably a well respected figure in the JavaScript world, with many contributions for all of us to use, re-use and build on.  &lt;a href="http://www.jslint.com"&gt;JSLint&lt;/a&gt; is one such contribution and this article will explore it very briefly.&lt;/p&gt;&lt;h3&gt;JSLint&lt;/h3&gt;&lt;p&gt;As a JavaScript developer striving for quality code you may already have run your code through JSLint.  This nifty tool is what is called a &lt;a href="http://en.wikipedia.org/wiki/Static_code_analysis"&gt;static code analysis&lt;/a&gt; tool which basically means that it does &lt;b&gt;not&lt;/b&gt; &lt;i&gt;execute&lt;/i&gt; the code but rather &lt;i&gt;analyzes&lt;/i&gt; it &lt;b&gt;without&lt;/b&gt; actually running it for any potential problems.  This is good and bad.&lt;/p&gt;&lt;p&gt;To put it in plain English, JSLint is not a pre-compiler.  It will not try to run the code to see if there are any syntax errors that will prevent the code from running.  As a matter of fact, syntactically the code may be flawless, but what JSLint does is points out areas of the code that may lead to unpredictable or unintended results.&lt;/p&gt;&lt;p&gt;A simple example would be writing code that inadvertently creates an infinite loop.  Syntactically this is bug-free code, but an analysis could identify this potential problem as something you did not intend to do.&lt;/p&gt;&lt;/p&gt;&lt;p&gt;This tool, meant to help at identifying potential issues with the code, has made it into build systems where a build will break in the event of an unsuccessful JSLint pass.  In other words, if JSLint isn't happy with the front-end code, it will prevent back-end code from building.  You may agree this is somewhat extreme to have an entire build be dependent on JSLint - but alas, this is what is happening out there, and I will show how this is a horrible idea.&lt;/p&gt;&lt;h4&gt;Pros&lt;/h4&gt;&lt;p&gt;The benefits of incorporating JSLint into the arsenal of tools for a front-end developer are numerous.  It effectively identifies various areas of potential problems and brings them to light in need of attention.  This could be anything from a missing semi-colon, to a duplicate variable definition, highlights reserved keywords that may be used, and other common coding mishaps.&lt;/p&gt;&lt;p&gt;The tool comes with various switches that allows for fine-tuning to achieve a tailored level of restriction.&lt;/p&gt;&lt;p&gt;Another indirect non-technical benefit is that we can use Douglas Crockford's extensive experience to find issues with our code that our lesser trained eye could not detect as easily, if at all.  On the flip-side, this can also work to our detriment.&lt;/p&gt;&lt;h4&gt;Cons&lt;/h4&gt;&lt;p&gt;As stated above JSLint is sometimes part of a build system that causes a build to fail based on a failed JSLint pass.  It is almost too easy to sell this idea to management for the following reasons:&lt;/p&gt;&lt;ol&gt;&lt;li&gt; Douglas Crockford&lt;br /&gt;&lt;ol&gt;&lt;li&gt; The Good Parts&lt;br /&gt;&lt;li&gt; JSON&lt;br /&gt;&lt;/ol&gt;&lt;li&gt; Code Quality&lt;br /&gt;&lt;li&gt; and the list goes on...&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;Essentially what it boils down to is &lt;i&gt;follow the leader&lt;/i&gt;.  History has shown us a few times what happens when we follow the leader without putting some thought into it, and this is exactly what I am trying to encourage for you to do.&lt;/p&gt;&lt;p&gt;Needless to say, this is not what the tool is meant for as a static code analysis tool.  It's like using Windows' Notepad to write Visual Basic applications - it's possible, but not what it's intended for.  It's the wrong tool for the wrong job.&lt;/p&gt;&lt;p&gt;To me this tool is a great utility to help identify potential issues to give the web developer another pair of eyes, but ultimately it rests on the developer's competency and expertise to make the call of whether or not to follow JSLint's suggestions.  Keep in mind JSLint takes a somewhat heuristic approach to the analysis, so it will not always &lt;i&gt;guess&lt;/i&gt; your intentions correctly.&lt;/p&gt;&lt;p&gt;So let's just run down a few issues with this tool that I've encountered and why I would not make the recommendation to use this as anything more than a suggestive tool in your arsenal - but definitely not as a pre-requisite to a successful build.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Problem at line &lt;i&gt;xx&lt;/i&gt; character &lt;i&gt;xx&lt;/i&gt;: '&lt;i&gt;xxxxx&lt;/i&gt;' is a function.&lt;/b&gt;&lt;br /&gt;&lt;p&gt;This happens commonly in closures where a function wants to overwrite itself.  This is not an error but JSLint would break a build - even with quite lenient switches turned on.&lt;/p&gt;&lt;li&gt;&lt;b&gt;Problem at line &lt;i&gt;xx&lt;/i&gt; character &lt;i&gt;xx&lt;/i&gt;: '&lt;i&gt;xxxxx&lt;/i&gt;' was used before it was defined.&lt;/b&gt;&lt;br /&gt;&lt;p&gt;This happens when you try to call a function before you defined it.  In other words JSLint expects your main code after all function definitions.  This is not always preferred since it requires for you to always scroll down past all your functions risking tripping something along the way - not to mention slow down your productivity.  This is debatable of course.&lt;/p&gt;&lt;li&gt;&lt;b&gt;Problem at line &lt;i&gt;xx&lt;/i&gt; character &lt;i&gt;xx&lt;/i&gt;: Expected an identifier and instead saw 'package' (a reserved word).&lt;/b&gt;&lt;br /&gt;&lt;p&gt;JavaScript has many &lt;a href="https://developer.mozilla.org/en/JavaScript/Reference/Reserved_Words"&gt;reserved words&lt;/a&gt; and amongst them is the word &lt;i&gt;package&lt;/i&gt;.  So while you should refrain from using reserved words, this error even pops up in a hash key being a reserved word.&lt;/p&gt;&lt;pre name="code" class="js"&gt; var myPackage = args.package;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;It is clear to us that this can never be in conflict with the reserved keyword since it will &lt;i&gt;never&lt;/i&gt; occupy the same namespace.&lt;/p&gt;&lt;li&gt;&lt;b&gt;Problem at line &lt;i&gt;xx&lt;/i&gt; character &lt;i&gt;xx&lt;/i&gt;: '&lt;i&gt;xxxxx&lt;/i&gt;' used out of scope.&lt;/b&gt;&lt;br /&gt;&lt;p&gt;This is an example where JSLint fails to identify proper scoping of a variable.  If you declare a variable inside an &lt;i&gt;if&lt;/i&gt; statement, followed by a condition that checks against that variable, this error emerges.&lt;/p&gt;&lt;pre name="code" class="js"&gt;if (1)&lt;br /&gt; {&lt;br /&gt;  var x = 1;&lt;br /&gt; }&lt;br /&gt;if (x)&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;As we can see the variable is not scoped (since &lt;i&gt;if&lt;/i&gt; statements don't scope a variable in JavaScript), so the above code should not throw an error.&lt;br /&gt;&lt;/p&gt;&lt;/ol&gt;&lt;p&gt;I could continue the list but the point is not to break apart JSLint but merely to show that there are some common practices that could incomprehensibly break a build, and why it should not be relied upon as a &lt;i&gt;one size fits all&lt;/i&gt; solution. &lt;/p&gt;&lt;h3&gt;Finally The Big Bang&lt;/h3&gt;&lt;p&gt;I want to make sure it is understood that I don't discredit the utility of JSLint, but to the contrary: we have to credit the tool for what it is and not go crazy using it for something that it is not.  I think Douglas Crockford would himself be astounded of how much faith some companies or individuals put into this tool.&lt;/p&gt;&lt;p&gt;If you are still a proponent of using JSLint for all your code quality needs, run the source code of JSLint through JSLint itself to see for yourself that it itself does not pass JSLint.  Here is &lt;a href="http://www.jslint.com/webjslint.js"&gt;the code&lt;/a&gt; (minified), jQuery &lt;a href="http://code.jquery.com/jquery-1.4.4.js"&gt;uncompressed&lt;/a&gt;, YUI &lt;a href="https://ajax.googleapis.com/ajax/libs/yui/2.8.2/build/yuiloader/yuiloader.js"&gt;uncompressed&lt;/a&gt;, and feel free to continue checking other well respected source codes to see how big of a chunk  of the Internet would go dark if their builds relied on JSLint.  Enjoy.&lt;/p&gt;&lt;h4&gt;Points of Argument&lt;/h4&gt;&lt;p&gt;Here are a few issues brought up by readers of this post that I feel are good to add as part of the post for you to be able to make a more sound decision on how you will choose to use JSLint in your workflow.&lt;/p&gt;&lt;b&gt;JSLint isn't intended for minified code&lt;/b&gt; &lt;p&gt;Minifying code yields valid JavaScript just as same as an experienced JavaScript developer might.  In other words, a minifier may do things that an experienced JavaScript developer might intentionally do as well, that JSLint would flag as an error - as it does with minified (and possibly optimized) code.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-4698434565494790047?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/4698434565494790047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/11/pros-cons-of-jslint.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/4698434565494790047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/4698434565494790047'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/11/pros-cons-of-jslint.html' title='Pros &amp; Cons of JSLint'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-6847319503453075643</id><published>2010-11-12T06:48:00.000-08:00</published><updated>2010-11-22T14:37:37.891-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><title type='text'>Closure based Getters &amp; Setters in jQuery</title><content type='html'>&lt;p&gt;Recently I wrote an article about how to effectively privatize your getters and setters by using closures.  In this article I want to quickly show how you can use this in a practical sense when you develop in jQuery.&lt;/p&gt;&lt;h3&gt;Problem&lt;/h3&gt;&lt;p&gt;One of the most common pitfalls of a jQuery developer in my experience has been the lack of focusing on performance.  The focus has generally been on task completion.  This means the job will get done, but it won't be done with performance efficiency in mind.&lt;/p&gt;&lt;p&gt;One of the most abused features of jQuery in this domain, is coincidentally the most used feature of jQuery: selectors (e.g. &lt;i&gt;$(element)&lt;/i&gt;).  Let's take a look at a silly example.&lt;/p&gt;&lt;pre name="code" class="js"&gt;$(function() &lt;br /&gt;   {&lt;br /&gt;    for (var x = 10; x &gt; 0; x--)&lt;br /&gt;     {&lt;br /&gt;      x % 2 &lt;br /&gt;       ? $('#someDivId').hide() &lt;br /&gt;       : $('div#someDivId').show();&lt;br /&gt;     }&lt;br /&gt;   });&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;In the above example we can see that we select the same div (assuming we follow the &lt;a href="http://www.w3schools.com/tags/att_standard_id.asp"&gt;W3C standard&lt;/a&gt; of assigning unique ids).&lt;/p&gt;&lt;p&gt;We are somewhat inefficient in that we use the jQuery selector each time to access the same element, forcing jQuery to crawl through the DOM each time.  This is inefficient, and a solution is available.&lt;/p&gt;&lt;h4&gt;Best Practices&lt;/h4&gt;&lt;p&gt;Before I dive into how a closure based solution could help, I will illustrate the commonly used solution as a best practice.&lt;/p&gt;&lt;pre name="code" class="js"&gt;$(function() &lt;br /&gt;   {&lt;br /&gt;    var divSelector = $('#someDivId');&lt;br /&gt;    for (var x = 10; x &gt; 0; x--)&lt;br /&gt;     {&lt;br /&gt;      x % 2 &lt;br /&gt;       ? divSelector.hide() &lt;br /&gt;       : divSelector.show();&lt;br /&gt;     }&lt;br /&gt;   });&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;What is happening here is that we capture the element in a variable that we then re-use.  This way we tap into jQuery's magic only once to find the element and leverage that spent effort in all subsequent references to that same element.&lt;/p&gt;&lt;p&gt;This is going in the right direction since our goal is to try to be as efficient as possible.  However there is a drawback to the above good practice.  Can you guess?&lt;/p&gt;&lt;p&gt;Let's take the next example.&lt;/p&gt;&lt;pre name="code" class="js"&gt;$(function() &lt;br /&gt;   {&lt;br /&gt;    var divSelector = $('#someDivId');&lt;br /&gt;&lt;br /&gt;    aFunction(divSelector);&lt;br /&gt;    bFunction(divSelector);&lt;br /&gt;&lt;br /&gt;    function aFunction(args)&lt;br /&gt;     {&lt;br /&gt;      for (var x = 10; x &gt; 0; x--)&lt;br /&gt;       {&lt;br /&gt;        x % 2 &lt;br /&gt;         ? args.hide() &lt;br /&gt;         : args.show();&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function bFunction(args)&lt;br /&gt;     {&lt;br /&gt;      for (var x = 20; x &gt; 0; x--)&lt;br /&gt;       {&lt;br /&gt;        x % 3 &lt;br /&gt;         ? args.hide() &lt;br /&gt;         : args.show();&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;   });&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above example is extremely silly in its functionality, but we merely want to illustrate a concept.&lt;/p&gt;&lt;p&gt;What do we see happening above?  The good practice of capturing the element in a variable and re-using the variable.  This is great but it pollutes the lexically scoped global namespace.  This means we have &lt;i&gt;divSelector&lt;/i&gt; available to &lt;i&gt;aFunction&lt;/i&gt; and &lt;b&gt;bFunction&lt;/b&gt; globally if we wanted to completely ignore the passed in argument to each function respectively.  In other words, we could directly access &lt;i&gt;divSelector&lt;/i&gt; from within either of these functions instead of reading &lt;i&gt;args&lt;/i&gt;.  What is the problem you might ask?  &lt;/p&gt;&lt;p&gt;There are a few.  One of them is a polluted namespace, but the second one is that of guaranteeing data integrity.  Since it is in the scoped global namespace any function can directly access it and &lt;i&gt;modify&lt;/i&gt; it - circumventing any error handling logic that may have been defined either in a getter or setter.&lt;/p&gt;&lt;h3&gt;Solution&lt;/h3&gt;&lt;p&gt;This is where we use a closure based getter and setter as described in my earlier blog post.&lt;/p&gt;&lt;pre name="code" class="js"&gt;$(function() &lt;br /&gt;   {&lt;br /&gt;    function getDiv()&lt;br /&gt;     {&lt;br /&gt;      var divSelector = $('#someDivId');&lt;br /&gt;&lt;br /&gt;      getDiv = function()&lt;br /&gt;                {&lt;br /&gt;                 return (divSelector);&lt;br /&gt;                };&lt;br /&gt;&lt;br /&gt;      return getDiv();&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function setDiv(args)&lt;br /&gt;     {&lt;br /&gt;      getDiv = function()&lt;br /&gt;                {&lt;br /&gt;                 return (args);&lt;br /&gt;                };&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    aFunction();&lt;br /&gt;    bFunction();&lt;br /&gt;&lt;br /&gt;    function aFunction()&lt;br /&gt;     {&lt;br /&gt;      var args = getDiv();&lt;br /&gt;&lt;br /&gt;      for (var x = 10; x &gt; 0; x--)&lt;br /&gt;       {&lt;br /&gt;        x % 2 &lt;br /&gt;         ? args.hide() &lt;br /&gt;         : args.show();&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function bFunction()&lt;br /&gt;     {&lt;br /&gt;      var args = getDiv();&lt;br /&gt;&lt;br /&gt;      for (var x = 20; x &gt; 0; x--)&lt;br /&gt;       {&lt;br /&gt;        x % 3 &lt;br /&gt;         ? args.hide() &lt;br /&gt;         : args.show();&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;   });&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I haven't followed the good practice of alphabetizing my functions to make it clearer.  I've kept the getter and setter at the top so you can clearly see the &lt;i&gt;new&lt;/i&gt; code.  Take a minute to understand it.&lt;/p&gt;&lt;p&gt;Good.  What is happening here is that the getter assumes the default value of the intended div.  The getter captures it on first iteration, then the getter overwrites itself by re-defining its own code (yes, it's able to do it), self-executes its new self, and returns the new function definition that then gets executed by the caller's parenthesis.  This is a closure based getter.&lt;/p&gt;&lt;p&gt;The benefit of using this solution is that you don't pollute the scoped global namespace, you ensure data integrity, you properly encapsulate the information to ensure security, and it is available just the same as a global variable would be - except with all these great extra benefits.&lt;/p&gt;&lt;p&gt;The one drawback is the code gets a little bigger, but that is the cost of having more reliable code.  Once we minify the code, it will be virtually indifferent.&lt;/p&gt;&lt;p&gt;Finally I will leave you with a clean version of the code as I would implement it.&lt;/p&gt;&lt;pre name="code" class="js"&gt;$(function() &lt;br /&gt;   {&lt;br /&gt;    aFunction();&lt;br /&gt;    bFunction();&lt;br /&gt;&lt;br /&gt;    function aFunction()&lt;br /&gt;     {&lt;br /&gt;      var div = getDiv();&lt;br /&gt;&lt;br /&gt;      for (var x = 10; x &gt; 0; x--)&lt;br /&gt;       {&lt;br /&gt;        x % 2 &lt;br /&gt;         ? div.hide() &lt;br /&gt;         : div.show();&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function bFunction()&lt;br /&gt;     {&lt;br /&gt;      var div = getDiv();&lt;br /&gt;&lt;br /&gt;      for (var x = 20; x &gt; 0; x--)&lt;br /&gt;       {&lt;br /&gt;        x % 3 &lt;br /&gt;         ? div.hide() &lt;br /&gt;         : div.show();&lt;br /&gt;       }&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function getDiv()&lt;br /&gt;     {&lt;br /&gt;      var div = $('#someDivId');&lt;br /&gt;&lt;br /&gt;      getDiv = function()&lt;br /&gt;                {&lt;br /&gt;                 return (div);&lt;br /&gt;                };&lt;br /&gt;&lt;br /&gt;      return get();&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function setDiv(args)&lt;br /&gt;     {&lt;br /&gt;      getDiv = function()&lt;br /&gt;                {&lt;br /&gt;                 return (args);&lt;br /&gt;                };&lt;br /&gt;     }&lt;br /&gt;   });&lt;br /&gt;&lt;/pre&gt;&lt;h3&gt;Pitfall&lt;/h3&gt;&lt;p&gt;There is one pitfall when using this with jQuery: The selected jQuery object gets frozen in time.&lt;/p&gt;&lt;p&gt;This means that if you use the above, you will be able to edit the contents just fine of the selected jQuery object, but it may not necessarily reflect in the browser.&lt;/p&gt;&lt;p&gt;Let's look at an example.&lt;/p&gt;&lt;pre name="code" class="js"&gt;$(function() &lt;br /&gt;   {&lt;br /&gt;    function getDiv()&lt;br /&gt;     {&lt;br /&gt;      var divSelector = $('#someDivId');&lt;br /&gt;      divSelector.html('Hi');&lt;br /&gt;&lt;br /&gt;      getDiv = function()&lt;br /&gt;                {&lt;br /&gt;                 return (divSelector);&lt;br /&gt;                };&lt;br /&gt;&lt;br /&gt;      return getDiv();&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function setDiv(args)&lt;br /&gt;     {&lt;br /&gt;      getDiv = function()&lt;br /&gt;                {&lt;br /&gt;                 return (args);&lt;br /&gt;                };&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    aFunction();&lt;br /&gt;    bFunction();&lt;br /&gt;&lt;br /&gt;    function aFunction()&lt;br /&gt;     {&lt;br /&gt;      var args = getDiv();&lt;br /&gt;&lt;br /&gt;      args.html('Hello');&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function bFunction()&lt;br /&gt;     {&lt;br /&gt;      var args = getDiv();&lt;br /&gt;&lt;br /&gt;      alert(args.html());  // this will say 'Hello' but the element on the page&lt;br /&gt;                           // will still say 'Hi'.&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;   });&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-6847319503453075643?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/6847319503453075643/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/11/closure-based-getters-setters-in-jquery.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/6847319503453075643'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/6847319503453075643'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/11/closure-based-getters-setters-in-jquery.html' title='Closure based Getters &amp; Setters in jQuery'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-415588573979886795</id><published>2010-10-28T18:40:00.000-07:00</published><updated>2011-01-16T09:48:54.712-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Closures with Getters and Setters in JavaScript</title><content type='html'>&lt;p&gt;Whenever we are working on Object Oriented code the best practice is to have getters (also known as &lt;i&gt;accessors&lt;/i&gt;) and setters.  The benefits of these are beyond the scope of this blog post, but if you aren't using them yet do yourself a favor and read up on them and use them.&lt;/p&gt;&lt;p&gt;JavaScript is a forgiving language that allows us to get away with bad practices.  Unfortunately, even with best intentions we may not always be aware of the hidden pitfalls we develop as we go.  One of them is the cluttering of the namespace.&lt;/p&gt;&lt;h3&gt;Problem&lt;/h3&gt;&lt;p&gt;In this example we will assume that we are a relatively well versed JavaScript developer and we want to use private getters and setters within our class.  Let's take a look at a simple class.&lt;/p&gt;&lt;pre name="code" class="js"&gt;function StudentClass(args)&lt;br /&gt;  {&lt;br /&gt;   this.greet = greet;&lt;br /&gt;&lt;br /&gt;   var _data = {&lt;br /&gt;                firstName : '',&lt;br /&gt;               };&lt;br /&gt;   &lt;br /&gt;   function getFirstName()&lt;br /&gt;    {&lt;br /&gt;     return _data.firstName;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   function greet()&lt;br /&gt;    {&lt;br /&gt;     alert(getFirstName());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   function setFirstName(args)&lt;br /&gt;    {&lt;br /&gt;     _data.firstName = args;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   setFirstName(args &amp;&amp; args.name ? args.name : '');&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  var student = new StudentClass({ name : "Milan Adamovsky" });&lt;br /&gt;  student.greet();&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Best Practices&lt;/h4&gt;&lt;p&gt;Above we observe a few good conventions and practices:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Proper Class naming convention (PascalCase as per Java &lt;i&gt;de facto&lt;/i&gt; convention) &lt;br /&gt;&lt;li&gt; Constructor&lt;br /&gt;&lt;li&gt; Private Getter&lt;br /&gt;&lt;li&gt; Private Setter&lt;br /&gt;&lt;li&gt; Exposed public interface (this.greet)&lt;br /&gt;&lt;li&gt; Alphabetized functions&lt;br /&gt;&lt;li&gt; Used underscored variable to imply private variable&lt;br /&gt;&lt;/ol&gt;Can we see an issue with the above implementation?  We sure can:  The namespace is cluttered with a private variable that &lt;i&gt;can&lt;/i&gt; be accessed directly if we choose to bypass the getter and setter.  Urgh! &lt;/p&gt;&lt;h3&gt;Solution&lt;/h3&gt;&lt;p&gt;Is there a way we can keep our private variables truly private?  Yes there is.  I challenge you to think a little bit about it.  You have a hint:  the title of this blog post :)&lt;/p&gt;&lt;p&gt;Okay, challenge is over, now this is where the fun truly begins.  Let's rewrite the above code excerpt with a truly private variable that cannot be accessed directly any other way than the getter.&lt;/p&gt;&lt;pre name="code" class="js"&gt;function StudentClass(args)&lt;br /&gt;  {&lt;br /&gt;   this.greet = greet;&lt;br /&gt;&lt;br /&gt;   function getFirstName()&lt;br /&gt;    {&lt;br /&gt;     return undefined;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   function greet()&lt;br /&gt;    {&lt;br /&gt;     alert(getFirstName());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   function setFirstName(args)&lt;br /&gt;    {&lt;br /&gt;     getFirstName = function ()&lt;br /&gt;                     {&lt;br /&gt;                      return (args);&lt;br /&gt;                     };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   setFirstName(args &amp;&amp; args.name ? args.name : '');&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  var student = new StudentClass({ name : "Milan Adamovsky" });&lt;br /&gt;  student.greet();&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is some cool stuff!  We can immediately notice that there is not one single variable in the encapsulated global namespace of the Class (e.g. &lt;i&gt;_data&lt;/i&gt; in the first example).&lt;/p&gt;&lt;h4&gt;Break Down&lt;/h4&gt;&lt;p&gt;Closures are a powerful concept, but most developers can't find an obvious use for them.  Next time you go to an interview, tell them it's perfect for private getters and setters ;)  In case someone like me interviews you and wants an explanation, here it is.&lt;/p&gt;&lt;h5&gt;Step 1&lt;/h5&gt;&lt;p&gt;The first thing we do is create the getter and setter.  We need both as not to throw any errors (there are ways around this, but let's keep it simple).  This is why we have this :&lt;/p&gt;&lt;pre name="code" class="js"&gt;function getFirstName()&lt;br /&gt;    {&lt;br /&gt;     return undefined;&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;We want &lt;i&gt;getFirstName&lt;/i&gt; to be in the namespace of the Class but we don't want it to actually return anything.  It's essentially just a memory place holder for the real getter &lt;i&gt;to come&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;Let me repeat this:  The declared getter returns nothing because we will overwrite the getter with the actual value through a closure.  We actually need to do it this way so that we can get away with not having to have a global variable (e.g. &lt;i&gt;_data&lt;/i&gt;).&lt;/p&gt;&lt;h5&gt;Step 2&lt;/h5&gt;&lt;p&gt;This leads us into the &lt;i&gt;setter&lt;/i&gt; that happens to be the closure for the &lt;i&gt;getter&lt;/i&gt;.&lt;/p&gt;&lt;pre name="code" class="js"&gt;function setFirstName(args)&lt;br /&gt;    {&lt;br /&gt;     getFirstName = function ()&lt;br /&gt;                     {&lt;br /&gt;                      return (args);&lt;br /&gt;                     };&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Take a minute to look at this and it will make sense.&lt;/p&gt;&lt;p&gt;Essentially what is happening is when we set the value we overwrite the respective &lt;i&gt;getter&lt;/i&gt; with a new function that returns the passed in parameter to the &lt;i&gt;setter&lt;/i&gt;.  In our example, that would be the &lt;i&gt;args&lt;/i&gt; variable.&lt;/p&gt;&lt;p&gt;The &lt;i&gt;args&lt;/i&gt; variable, you will notice, is passed in via &lt;i&gt;setFirstName(&lt;/i&gt;&lt;b&gt;args&lt;/b&gt;&lt;i&gt;)&lt;/i&gt; and captured in the anonymous function that is then assigned to the variable &lt;i&gt;getFirstName&lt;/i&gt; which occupies the same namespace as the &lt;i&gt;getFirstName&lt;/i&gt; function.  Voilà!  There is no way to access &lt;i&gt;args&lt;/i&gt; unless you use the getter.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-415588573979886795?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/415588573979886795/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/10/closures-with-getters-and-setters-in.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/415588573979886795'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/415588573979886795'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/10/closures-with-getters-and-setters-in.html' title='Closures with Getters and Setters in JavaScript'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-6718622002138342707</id><published>2010-10-03T09:00:00.000-07:00</published><updated>2010-10-03T09:00:48.428-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='freebsd'/><category scheme='http://www.blogger.com/atom/ns#' term='fedora'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>Berkeley DB not found on Fedora 8</title><content type='html'>&lt;p&gt;My preferred Operating System to work on is FreeBSD, but recently I was working on a project on a Fedora AMI on the Amazon EC2 platform.  There are a few differences between the two systems and I have to develop a cross-platform script.&lt;/p&gt;&lt;p&gt;The binary I was trying to compile was the Apache Portable Runtime utility called &lt;b&gt;apr-util&lt;/b&gt; which is needed to compile the Apache web server.  As you may already know, one of the prerequisites is Berkeley DB.&lt;/p&gt;&lt;h3&gt;Compilation&lt;/h3&gt;&lt;p&gt;Whenever developing cross-platforms scripts or applications it is important to rely on tarballs as opposed to native OS package systems such as FreeBSD's &lt;i&gt;ports&lt;/i&gt;, Linux' &lt;i&gt;rpm&lt;/i&gt; or &lt;i&gt;yum&lt;/i&gt;.  The main reason for this is that doing manual compilations gives you granular control over the dependencies, patches, and compilation options that may and may not be better suited for cross-platform operations.  That is assuming that the goal is to have an identical binary cross-platform.&lt;/p&gt;&lt;p&gt;To compile apr-util we use the following sequential commands:&lt;/p&gt;&lt;pre name="code" class="bash"&gt;./configure  --with-apr=/usr/local/apr/bin/apr-1-config --with-berkeley-db=/usr/local/BerkeleyDB.4.8&lt;br /&gt;make&lt;br /&gt;make install&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The pre-requisite is that &lt;a href="http://apache.securedservers.com//apr/apr-1.4.2.tar.gz"&gt;apr&lt;/a&gt; and &lt;a href="http://www.oracle.com/technetwork/database/berkeleydb/downloads/index.html"&gt;Berkeley&lt;/a&gt; have already been installed on the system.  In the example above we use Berkeley 4.8 but feel free to use the latest version.&lt;/p&gt;&lt;h4&gt;Problem&lt;/h4&gt;&lt;p&gt;The problem that we encounter when we compile apr-util manually is the following:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;checking for Berkeley DB... not found configure: error: Berkeley DB not found.&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This error message indicates that the linker was unable to find Berkeley DB libraries to compile against.  This gives us enough information to immediately figure out that the problem lies with a tool called &lt;i&gt;ldconfig&lt;/i&gt;.&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;The solution involves calibrating the linker to be aware of where the Berkeley DB libraries can be found, and this is exactly what we will do.&lt;/p&gt;&lt;p&gt;It may at first seem that we should focus on fixing something in the files of &lt;i&gt;apr-util&lt;/i&gt; but the real solution lies with Berkeley DB.&lt;/p&gt;&lt;p&gt;When Berkeley DB is compiled we simply need to expose the various paths to the linker.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;echo /usr/local/BerkeleyDB.4.8/lib &gt; /etc/ld.so.conf&lt;br /&gt;ldconfig&lt;br /&gt;export CPPFLAGS="-I/usr/local/BerkeleyDB.4.8/include"&lt;br /&gt;export LD_LIBRARY_PATH="/usr/local/BerkeleyDB.4.8/lib/"&lt;br /&gt;export LDFLAGS="-L/usr/local/BerkeleyDB.4.8/lib"&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I normally extrapolate the path into a variable such as $BERKELEY_PREFIX but for sake of clarity I've avoided that in the examples.  Feel free to do so however since it makes your code more manageable and flexible.  Doing so the code would look like this:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;export BERKELEY_PREFIX=/usr/local/BerkeleyDB.4.8&lt;br /&gt;echo $BERKELEY_PREFIX/lib &gt;&gt; /etc/ld.so.conf&lt;br /&gt;ldconfig&lt;br /&gt;export CPPFLAGS="-I$BERKELEY_PREFIX/include"&lt;br /&gt;export LD_LIBRARY_PATH="$BERKELEY_PREFIX/lib/"&lt;br /&gt;export LDFLAGS="-L$BERKELEY_PREFIX/lib"&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Just a little bonus.&lt;/p&gt;&lt;p&gt;Continuing with our solution, what we accomplish with the above is adding the path of where Berkeley DB libraries can be found to the linker configuration file (&lt;i&gt;ld.so.conf&lt;/i&gt;).  Be very careful to &lt;i&gt;append&lt;/i&gt; the path to the ld.so.conf as not to overwrite any existing contents of the file.  This is simply done by ensuring you use '&gt;&gt;' as opposed to '&gt;' as shown above.  Consider this a word of caution.&lt;/p&gt;&lt;p&gt;Once the path is in your ld.so.conf you will simply need to run the linker &lt;i&gt;ldconfig&lt;/i&gt; to make it aware of the changes.  This will suck in all libraries.  We can then verify that they have taken effect by listing all the libraries that ldconfig is aware of.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;[root@server ~]# ldconfig -p | grep libdb&lt;br /&gt;libdbus-1.so.3 (libc6,x86-64) =&gt; /lib64/libdbus-1.so.3&lt;br /&gt;libdbus-1.so.3 (libc6) =&gt; /lib/libdbus-1.so.3&lt;br /&gt;libdbus-glib-1.so.2 (libc6,x86-64) =&gt; /usr/lib64/libdbus-glib-1.so.2&lt;br /&gt;libdbus-glib-1.so.2 (libc6) =&gt; /usr/lib/libdbus-glib-1.so.2&lt;br /&gt;libdb-4.8.so (libc6,x86-64) =&gt; /usr/local/BerkeleyDB.4.8/lib/libdb-4.8.so&lt;br /&gt;libdb-4.6.so (libc6,x86-64) =&gt; /lib64/libdb-4.6.so&lt;br /&gt;libdb-4.6.so (libc6,x86-64) =&gt; /usr/lib64/libdb-4.6.so&lt;br /&gt;libdb-4.6.so (libc6) =&gt; /lib/libdb-4.6.so&lt;br /&gt;libdb-4.6.so (libc6) =&gt; /usr/lib/libdb-4.6.so&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;We can see from the above output that we have two Berkeley DBs installed on the system.  One of them is version 4.6 and one of them is our new version 4.8.  If you choose to install any other version your output would reflect an entry with the selected version respectively.&lt;/p&gt;&lt;h4&gt;FreeBSD listing&lt;/h4&gt;&lt;p&gt;In FreeBSD the ldconfig switch to see the listing above is &lt;i&gt;-r&lt;/i&gt; instead of &lt;i&gt;-p&lt;/i&gt;.  You would thus run the command below:&lt;/p&gt;&lt;pre name="code" class="bash"&gt;[root@server ~]# ldconfig -r | grep Berkeley&lt;/pre&gt;&lt;p&gt;Though in FreeBSD the libraries may not even be listed at all if we simply add the path of Berkeley DB to the search path as such:&lt;/p&gt;&lt;pre name="code" class="bash"&gt;ldconfig -m /usr/local/BerkeleyDB.4.8/lib &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;However as long as it is in the search path the linker will find the libraries at compilation.&lt;/p&gt;&lt;h3&gt;Automation&lt;/h3&gt;&lt;p&gt;At this point you should already have fixed the problem.  You do not need to do anything anymore.  The information below is just a little extra.&lt;/p&gt;&lt;p&gt;You can take it a step further by doing a conditional check ensuring you do not clutter your /etc/ld.so.conf file by not appending the path if it already exists.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;export BERKELEY_PREFIX=/usr/local/BerkeleyDB.4.8&lt;br /&gt;if [[ "$(grep $BERKELEY_PREFIX/lib /etc/ld.so.conf)" =~ 'lib' ]]; then&lt;br /&gt;  echo $BERKELEY_PREFIX/lib &gt;&gt; /etc/ld.so.conf&lt;br /&gt;  ldconfig&lt;br /&gt;fi&lt;br /&gt;export CPPFLAGS="-I$BERKELEY_PREFIX/include"&lt;br /&gt;export LD_LIBRARY_PATH="$BERKELEY_PREFIX/lib/"&lt;br /&gt;export LDFLAGS="-L$BERKELEY_PREFIX/lib"&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above would usually be put in an automation bash script.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-6718622002138342707?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/6718622002138342707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/10/berkeley-db-not-found-on-fedora-8.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/6718622002138342707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/6718622002138342707'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/10/berkeley-db-not-found-on-fedora-8.html' title='Berkeley DB not found on Fedora 8'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-3197077839655440193</id><published>2010-09-25T11:05:00.001-07:00</published><updated>2010-09-30T16:21:54.163-07:00</updated><title type='text'>jQuery Plugin Pattern 2.0</title><content type='html'>&lt;p&gt;After having developed the &lt;a href="http://milanadamovsky.blogspot.com/2010/02/how-to-write-advanced-jquery-plugins.html"&gt;original jQuery authoring pattern&lt;/a&gt; a few issues caught my attention that kept me unhappy with that pattern.  Luckily I had found workarounds for the few shortcomings I identified, but having to keep these in mind during development was a pain and did not provide for as a robust solution as I'd like it to be. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Time to review the pattern and start from scratch.  You will see that this is a more elegant solution with all kinks ironed out.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Criteria&lt;/h4&gt;&lt;p&gt;I still want to have a pattern that allows me to write plugins that meet these criteria:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;that maintain only one entry in jQuery's namespace&lt;br /&gt;&lt;/li&gt;&lt;li&gt;that allow secondary methods&lt;br /&gt;&lt;/li&gt;&lt;li&gt;access to selector&lt;br /&gt;&lt;/li&gt;&lt;li&gt;access to $(this) through secondary methods&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The good thing is that because this pattern uses jQuery's conventions, you do not have to learn anything new - no new framework, no new names, no new trickery, just simple straight forward jQuery programming mixed with Object Oriented JavaScript programming.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Research&lt;/h4&gt;&lt;p&gt;I do encourage everyone to read the official &lt;a href="http://docs.jquery.com/Plugins/Authoring"&gt;jQuery plug-in authoring tutorial&lt;/a&gt;.  This is pretty simple and straight forward, and in this article I will refer to it as the "normal method".&lt;/p&gt;&lt;p&gt;Another great read is Mike Alsup's &lt;a href="http://www.learningjquery.com/2007/10/a-plugin-development-pattern"&gt;plugin development pattern&lt;/a&gt;.  His tutorial is closer to what my &lt;i&gt;pattern&lt;/i&gt; tackles.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Goal&lt;/h4&gt;&lt;p&gt;As with my &lt;a href="http://milanadamovsky.blogspot.com/2010/02/how-to-write-advanced-jquery-plugins.html"&gt;original pattern&lt;/a&gt;, in this new pattern I also want to be able to have global access to the selector along with the $(this) object regardless of how many levels deep I am in my methods (e.g. &lt;i&gt;$(selector).x.y.z()&lt;/i&gt;).  This is something that jQuery does not natively support, and is limited to making the selector and $(this) available only to the main plug-in (first level as in &lt;i&gt;$(selector).x()&lt;/i&gt;).&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;First I want to begin with giving a complete example of how a very basic plugin is developed using my proposed pattern so you know what you'll be dealing with.&lt;/p&gt;&lt;p&gt;Behold... the new plugin pattern!&lt;/p&gt;&lt;pre name="code" class="js"&gt;(function($)&lt;br /&gt;  {&lt;br /&gt;   $.fn.extend({ &lt;br /&gt;                _plugin: null, &lt;br /&gt;                jQueryInit: jQuery.fn.init &lt;br /&gt;               });&lt;br /&gt;    &lt;br /&gt;   $.fn.extend({&lt;br /&gt;                init: function( selector, context ) &lt;br /&gt;                       {&lt;br /&gt;                        return jQuery.fn._plugin = new jQuery.fn.jQueryInit(selector, context);&lt;br /&gt;                       }&lt;br /&gt;               });&lt;br /&gt;    &lt;br /&gt;   function MyPluginClass(args)&lt;br /&gt;    {&lt;br /&gt;     &lt;br /&gt;     var _config;&lt;br /&gt;     &lt;br /&gt;     this.version = '1.0';&lt;br /&gt;    &lt;br /&gt;     this.show = _(showMessage);&lt;br /&gt;     &lt;br /&gt;     initConfig(args);&lt;br /&gt;&lt;br /&gt;     function getConfig()&lt;br /&gt;      {&lt;br /&gt;       return _config;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     function setConfig(args)&lt;br /&gt;      {&lt;br /&gt;       _config = args;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     function initConfig(args)&lt;br /&gt;      { &lt;br /&gt;       setConfig($.extend({&lt;br /&gt;                           chainable : true,&lt;br /&gt;                           className : 'MyPluginClass'&lt;br /&gt;                          }, args));&lt;br /&gt;       return (this);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     function showMessage(args)&lt;br /&gt;      {  &lt;br /&gt;       var myDiv = $(this);&lt;br /&gt;           &lt;br /&gt;       var config = getConfig();&lt;br /&gt;&lt;br /&gt;       alert('My Plugin is ' + config.className);&lt;br /&gt;              &lt;br /&gt;       return (this);&lt;br /&gt;      }&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;     function _ (fn) &lt;br /&gt;      {&lt;br /&gt;       return function (args)&lt;br /&gt;               {&lt;br /&gt;                return this.prototype.rc(function () &lt;br /&gt;                                          { &lt;br /&gt;                                           fn.call(this, args) &lt;br /&gt;                                          }); &lt;br /&gt;               }&lt;br /&gt;      }&lt;br /&gt;      &lt;br /&gt;     this.rc = function (args)&lt;br /&gt;      {&lt;br /&gt;       if (typeof args == 'function')&lt;br /&gt;        {&lt;br /&gt;         return $.fn._plugin.each(args);&lt;br /&gt;        }&lt;br /&gt;       else&lt;br /&gt;        {&lt;br /&gt;         initConfig(args);&lt;br /&gt;         &lt;br /&gt;         return getConfig().chainable&lt;br /&gt;                 ? $.fn._plugin&lt;br /&gt;                 : $.fn.createBox;&lt;br /&gt;        }&lt;br /&gt;      };&lt;br /&gt;       &lt;br /&gt;     &lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     var _p = new MyPluginClass({});&lt;br /&gt;     &lt;br /&gt;     $.fn.pluginName = _p.rc;&lt;br /&gt;     $.extend($.fn.pluginName.prototype,_p);&lt;br /&gt;     $.extend($.fn.pluginName,_p);&lt;br /&gt;     &lt;br /&gt;    })(jQuery);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;At first it may seem a little counter-intuitive, but much of this code you will simply copy and paste without having to understand.  All you need to understand is where your code goes and a few simple rules to follow and you will write really cool plugins.&lt;/p&gt;&lt;h4&gt;Usage&lt;/h4&gt;&lt;p&gt;The above dummy plugin would be called as such&lt;/p&gt;&lt;pre name="code" class="js"&gt;$(document).ready(function() &lt;br /&gt; {&lt;br /&gt;  $(selector).pluginName.show();&lt;br /&gt; });&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Before we break down the pattern I want to show why we go through this process and how cool your plugins will become.&lt;/p&gt;&lt;p&gt;This pattern is fully backwards compatible to jQuery's suggested use.  This means you can still use the traditional form of calling your plugin (if you want) as shown below.&lt;/p&gt;&lt;pre style="background-color: #eaeaea; padding: 5px;"&gt;$(&lt;i&gt;selector&lt;/i&gt;).pluginName(&lt;i&gt;args&lt;/i&gt;);&lt;br /&gt;&lt;/pre&gt;So we got backwards compatibility covered.  But where is the magic?&lt;br /&gt;The official jQuery pattern promotes the use of plugins are stand-alone widgets more or less that can be customized by way of tweaking various publicly exposed options.  This is where my pattern diverges.&lt;br /&gt;&lt;pre style="background-color: #eaeaea; padding: 5px;"&gt;$(&lt;i&gt;selector&lt;/i&gt;).pluginName(&lt;i&gt;args&lt;/i&gt;);&lt;br /&gt;$(&lt;i&gt;selector&lt;/i&gt;).pluginName(&lt;i&gt;args&lt;/i&gt;).&lt;i&gt;method()&lt;/i&gt;;&lt;br /&gt;$(&lt;i&gt;selector&lt;/i&gt;).&lt;i&gt;pluginName&lt;/i&gt;.&lt;i&gt;method()&lt;/i&gt;&lt;br /&gt;$(&lt;i&gt;selector&lt;/i&gt;).&lt;i&gt;pluginName&lt;/i&gt;.&lt;i&gt;object&lt;/i&gt;.&lt;i&gt;method()&lt;/i&gt;&lt;br /&gt;$(&lt;i&gt;selector&lt;/i&gt;).&lt;i&gt;pluginName&lt;/i&gt;.&lt;i&gt;object&lt;/i&gt;.&lt;i&gt;method(args)&lt;/i&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;All of the above are valid syntax when coded using this pattern, and yes, it's still chainable as long as you adhere to jQuery's plugin conventions to make it chainable.  Sweet!&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;Still working on the write-up... follow my blog for updates.  Gotta go get some sleep...&lt;/i&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3&gt;Questions &amp; Answers&lt;/h3&gt;&lt;p&gt;Here are a few questions asked by jQuery developers introduced to this new pattern.  I am also linking back those questions asked in forums or other places.&lt;br /&gt;&lt;/p&gt;&lt;dl&gt;&lt;dt&gt;&lt;b&gt;&lt;a href="http://forum.jquery.com/topic/jquery-plugin-pattern-2-0#14737000001434084"&gt;Why break away from the common pattern of $(&lt;i&gt;selector&lt;/i&gt;).&lt;i&gt;plugin&lt;/i&gt;("&lt;i&gt;method&lt;/i&gt;", &lt;i&gt;args&lt;/i&gt;) for secondary methods?&lt;/a&gt; &lt;br /&gt;&lt;/b&gt;&lt;/dt&gt;&lt;dd&gt; &lt;p&gt;The "common pattern" is specific to jQuery but unconventional to programmers coming from other backgrounds.  My pattern does not &lt;i&gt;break away&lt;/i&gt; from the jQuery way, but &lt;i&gt;extends&lt;/i&gt; the possibilities by merging the two.  Remember that this pattern is still backwards compatible with jQuery's convention.&lt;/p&gt;&lt;p&gt;This pattern allows for you to stick to the way jQuery promotes specifying methods, as well as stay with the conventional way of coding methods as done in most object oriented languages.  In a sense it welcomes a wider audience of developers to develop plugins for jQuery.&lt;/p&gt;&lt;p&gt;Using an Object Oriented convention allows you to leverage all the benefits that OOP yields and integrate those into your jQuery plugins.&lt;/p&gt;&lt;p&gt;It simplifies having a granular syntax for your plugins.  The whole concept of objects is to be able to interconnect them easily - this pattern makes it easy since it provides for a gateway to expose core JavaScript OOP.&lt;/p&gt;&lt;p&gt;Consider this pattern like an extended namespace:  All the methods within the plugin belong to the plugin where it is safe to return an object in the traditional OO sense, and the selector continues to be passed on until you are ready to expose it for chainability.&lt;/p&gt;&lt;/dd&gt; &lt;/dl&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-3197077839655440193?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/3197077839655440193/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/09/jquery-plugin-pattern-20.html#comment-form' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/3197077839655440193'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/3197077839655440193'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/09/jquery-plugin-pattern-20.html' title='jQuery Plugin Pattern 2.0'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-3109991656014299406</id><published>2010-08-01T00:30:00.000-07:00</published><updated>2010-09-28T21:39:12.796-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Contextual Indent</title><content type='html'>&lt;p&gt;There are many different coding conventions that have developed over the years to make coding easier, faster, and intuitive.  Amongst these convention lies an important component:  &lt;i&gt;indentation&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;As is the case with many standards and conventions, indentation is not immune to debates and criticism.  Whether you are a &lt;i&gt;spacer&lt;/i&gt; or a &lt;i&gt;tabber&lt;/i&gt; you have undoubtedly felt strongly about the respective conventions, but this indentation style will cater to &lt;i&gt;spacers&lt;/i&gt; - or people who use spaces to indent code.  Finally this will show that there is a good &lt;i&gt;reason&lt;/i&gt; to use spaces as opposed to just it being a personal preference.&lt;/p&gt;&lt;p&gt;In this article I'm introducing a convention I've perfected over my many years of programming in both back-end as well as front-end technologies.  The name I've assigned it is: &lt;i&gt;contextual indent&lt;/i&gt;.  The reason will become clear below.&lt;/p&gt;&lt;p&gt;Ultimately the purpose of this indentation style is to let the code guide your eye intuitively and attach instinctual sense of what it sees without having to put much thought into it.&lt;/p&gt;&lt;h2&gt;What Is Indention&lt;/h2&gt;&lt;p&gt;In an earlier article I had introduced my arguments for using spaces instead of tabs to indent your code.  I went a step further by suggesting &lt;i&gt;one&lt;/i&gt; space is all you need.  Not four, not two, but only one space to demarcate indentation.  This will prove useful for this indentation style.&lt;/p&gt;&lt;p&gt;Before we continue however we should take a minute to clarify what an indentation represent.  Having a solid understanding of this concept is important to be able to agree with anything else in this article.  If you disagree with the fundamental concept, you will not understand the benefits of this indentation style.&lt;/p&gt;&lt;p&gt;An indentation in code represents a relationship in the abstract sense.  It indicates that whatever is indented belongs to or is controlled by whatever it is relatively indented to.&lt;/p&gt;&lt;pre class="brush: js;"&gt;if (true)&lt;br /&gt; {&lt;br /&gt;  alert('hello');&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Above we can see that the braces belong to the &lt;i&gt;if&lt;/i&gt; statement, and the &lt;i&gt;alert&lt;/i&gt; statement belongs to the braces that is in turn controlled by the &lt;i&gt;if&lt;/i&gt; statement.  We can see a hierarchy.  This is the same hierarchy we want to preserve aesthetically in our code by way of indentation.&lt;/p&gt;&lt;h2&gt;Contextual Indentation Guidelines&lt;/h2&gt;&lt;p&gt;There are several guidelines that should be followed to successfully implement this indentation style.  The best way to illustrate these is by way of examples.&lt;/p&gt;&lt;h3&gt;Braces&lt;/h3&gt;&lt;p&gt;In programming braces often denote a block of code, and sometimes even scope.  Wherever braces are used we can follow the same indentation convention.  This applies to functions, if statements, loops, with statements, and all other language specific functionality that involves braces.&lt;/p&gt;&lt;p&gt;A function can also represent a method, subroutine, class, or any other derivative that is similar in concept to a function.  These are all indented in the same way.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function myFunctionName(args&lt;br /&gt; {&lt;br /&gt;  ....&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;We can see that the opening brace is on its own line as is the closing brace.  This will allow for the opening and closing braces to line up perfectly, and give a sense of scope immediately and visually.  This will become more important as one develops advanced code where anonymous functions may get defined anywhere in the code.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function myFunctionName(args)&lt;br /&gt; {&lt;br /&gt;  return (function ()&lt;br /&gt;           {&lt;br /&gt;            ....&lt;br /&gt;           });&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above shows an anonymous function being returned.  We can see that the function's braces are still indented with one space relative to the context (the return function's definition).  This is how we derive the name of this indentation style.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;if (condition)&lt;br /&gt; {&lt;br /&gt;  if (second condition)&lt;br /&gt;   {&lt;br /&gt;    ...&lt;br /&gt;   }&lt;br /&gt;  else&lt;br /&gt;   {&lt;br /&gt;    ...&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;else&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The last example shows how a nested &lt;i&gt;if&lt;/i&gt; statement is supposed to be indented as well as illustrate the earlier point that the same style applies to any construct that involves braces regardless of whether it is an &lt;i&gt;if&lt;/i&gt; statement or function.&lt;/p&gt;&lt;h3&gt;Ternary Operator&lt;/h3&gt;&lt;p&gt;Many times we will want to use a ternary operator (?:) instead of an if statement.  This is usually the case during variable assignments.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;var myVariable = (condition)&lt;br /&gt;                   ? true&lt;br /&gt;                   : false;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above example shows how the condition is on its own line, and the actual operators are lined up underneath each other.  This alignment is most useful when we have nested ternary operators, but is also useful to immediately see the alternative paths visually.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;var myVariable = &lt;i&gt;first condition&lt;/i&gt;&lt;br /&gt;                  ? &lt;i&gt;second condition&lt;/i&gt;&lt;br /&gt;                     ? true&lt;br /&gt;                     : false&lt;br /&gt;                  : false;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above is very clear.  Next I will show you how it would look if we flattened it.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;var myVariable = &lt;i&gt;first condition&lt;/i&gt; ? &lt;i&gt;second condition&lt;/i&gt; ? true : false : false;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Even with this overly simplified example it is still difficult to follow the logic of this nested ternary operator in flattened view.  It becomes clear that taking the extra time to indent the code properly yields great savings when it comes to reading your code, and more importantly when having others read your code.&lt;/p&gt;&lt;h3&gt;Objects&lt;/h3&gt;&lt;p&gt;The beauty of Object Oriented Programming is the ability to interconnect different objects to alter the final behavior.  This beauty can quickly become a long-winded chain of objects that can be difficult to read.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;i&gt;objectA&lt;/i&gt;.&lt;i&gt;objectB&lt;/i&gt;.&lt;i&gt;objectC&lt;/i&gt;.&lt;i&gt;objectD&lt;/i&gt;.&lt;i&gt;methodDA(paramA,paramB)&lt;/i&gt;.&lt;i&gt;objectE(params)&lt;/i&gt;.&lt;i&gt;methodEA(paramA,paramB)&lt;/i&gt;&lt;/pre&gt;&lt;p&gt;While the above example is fictitious, it is actually shorter than many real-life examples may be.  The point is that it can become difficult to read.&lt;/p&gt;&lt;p&gt;Using &lt;i&gt;contextual indentation&lt;/i&gt; the rule becomes to have one object/method per line with the exception of the first one.  Re-writing the above example results in the code below.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;i&gt;objectA&lt;/i&gt;.&lt;i&gt;objectB&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;objectC&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;objectD&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;methodDA(paramA,paramB)&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;objectE(params)&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;methodEA(paramA,paramB)&lt;/i&gt;&lt;/pre&gt;&lt;p&gt;As you can see, we align the dots.  In languages that use other signs, such as Perl or PHP that use arrows (e.g. &lt;i&gt;-&gt;&lt;/i&gt;), we would simply vertically align those.&lt;/p&gt;&lt;p&gt;The reason we want to align the dots up front is because it suggests what follows is related to what's before it.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The above illustrates how to properly indent the objects.  We observe another data set that causes the code to look to busy:  Arguments.&lt;/p&gt;&lt;h3&gt;Arguments&lt;/h3&gt;&lt;p&gt;As with objects arguments can quickly become a long list of information that can be difficult to visually separate.  The &lt;i&gt;contextual indent&lt;/i&gt; provides a solution for this as well.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function(&lt;i&gt;paramA&lt;/i&gt;,&lt;i&gt;paramB&lt;/i&gt;,&lt;i&gt;paramC&lt;/i&gt;,&lt;i&gt;paramD&lt;/i&gt;,&lt;i&gt;paramE&lt;/i&gt;,&lt;i&gt;paramF&lt;/i&gt;,&lt;i&gt;paramG&lt;/i&gt;);&lt;/pre&gt;&lt;p&gt;Again, the above does not illustrate a real-life example, but it could very well be similar to the above.  Furthermore, in the case of OOP it is possible to have several chained objects or methods that take parameters as shown in the example above for &lt;i&gt;Objects&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;Re-factoring the above would yield the output below.&lt;br /&gt;&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function(&lt;i&gt;paramA&lt;/i&gt;,&lt;br /&gt;         &lt;i&gt;paramB&lt;/i&gt;,&lt;br /&gt;         &lt;i&gt;paramC&lt;/i&gt;,&lt;br /&gt;         &lt;i&gt;paramD&lt;/i&gt;,&lt;br /&gt;         &lt;i&gt;paramE&lt;/i&gt;,&lt;br /&gt;         &lt;i&gt;paramF&lt;/i&gt;,&lt;br /&gt;         &lt;i&gt;paramG&lt;/i&gt;);&lt;/pre&gt;&lt;p&gt;Unlike &lt;i&gt;objects&lt;/i&gt; we can see that in this case we don't align the commas up front.  As a matter of fact the above is just coincidentally that the commas are vertically aligned, but depending on the length of the parameter this would not be the case, nor is there any visual value to doing so.  As a result, we just keep the commas at the end regardless of how they appear visually.&lt;/p&gt;&lt;p&gt;Again, unlike &lt;i&gt;objects&lt;/i&gt; the parameters or arguments are not related to each other - it's just a list. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Fixing the &lt;i&gt;objects&lt;/i&gt; example would yield the output below.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;i&gt;objectA&lt;/i&gt;.&lt;i&gt;objectB&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;objectC&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;objectD&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;methodDA(paramA,&lt;br /&gt;                 paramB)&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;objectE(params)&lt;/i&gt;&lt;br /&gt;       .&lt;i&gt;methodEA(paramA,&lt;br /&gt;                 paramB)&lt;/i&gt;&lt;/pre&gt;&lt;p&gt;It become obvious real fast what belongs to what at first glance - unlike its serialized predecessor.&lt;/p&gt;&lt;p&gt;Having said all of this regarding arguments, keep in mind that most of the time this can be avoided by the use of &lt;a href="http://milan.adamovsky.com/2009/09/javascript-arguments-return-pattern.html"&gt;HARP&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-3109991656014299406?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/3109991656014299406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/08/contextual-indent.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/3109991656014299406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/3109991656014299406'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/08/contextual-indent.html' title='Contextual Indent'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-4956245243307417774</id><published>2010-06-29T18:08:00.000-07:00</published><updated>2010-06-29T18:52:41.598-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='subversion'/><title type='text'>SVN Merge Branch To Trunk with minimal Tree Conflicts</title><content type='html'>&lt;p&gt;After having spent (too) much time trying to figure out how to get around receiving Tree Conflicts when I merge my branch with my trunk I have finally found a solution.  I'm a little disappointed that SVN makes this task somewhat difficult, but this is not surprising since apparently SVN is not designed for branching according to &lt;a href="http://svn.apache.org/repos/asf/subversion/trunk/doc/user/svn-best-practices.html"&gt;Apache's best practices&lt;/a&gt;.&lt;/p&gt;&lt;h3&gt;Development Environment Setup&lt;/h3&gt;&lt;p&gt;In my development environment I prefer to branch off my trunk into &lt;i&gt;dev&lt;/i&gt; projects in a very pessimistic way:  &lt;i&gt;Let me mess up with no negative impact&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;In other words I want to isolate my active development into its own sandbox to where I can have the peace of mind that I am free to experiment, corrupt files, corrupt code, and do anything I want with no consequences.  This is what drives progress: &lt;i&gt;experimentation&lt;/i&gt;.  How can you have progress if you're scared to try new things?&lt;/p&gt;&lt;p&gt;As a result of this I work in isolated branches.  These branches are then gradually merged into the trunk as I develop and become happy with some code worthy of making it into the trunk.&lt;/p&gt;&lt;h4&gt;SVN layout&lt;/h4&gt;&lt;p&gt;A typical setup will look something similar to this:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;/projects&lt;br /&gt;         /projectA&lt;br /&gt;                  /branches&lt;br /&gt;                           /active&lt;br /&gt;                  /tags&lt;br /&gt;                  /trunk&lt;br /&gt;         /projectB&lt;br /&gt;                  /branches&lt;br /&gt;                           /active&lt;br /&gt;                  /tags&lt;br /&gt;                  /trunk&lt;br /&gt;         /projectC&lt;br /&gt;                  /branches&lt;br /&gt;                           /active&lt;br /&gt;                  /tags&lt;br /&gt;                  /trunk&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;As you can see it conforms the Subversion's &lt;a href="http://svnbook.red-bean.com/en/1.0/svn-book.html#svn-ch-4-sect-7.1"&gt;recommended layout&lt;/a&gt;.  Chances are that you are already setup this way.&lt;/p&gt;&lt;h4&gt;Server layout&lt;/h4&gt;&lt;p&gt;Here is where I begin to deviate from the recommended setup:  Instead of having a branch &lt;i&gt;and&lt;/i&gt; a trunk checked out, I only checkout a &lt;i&gt;branch&lt;/i&gt;.  It is silly in my opinion to check out the trunk for every project.  Leave the trunk in SVN and only worry about your active branch (in your active development environment that is).&lt;/p&gt;&lt;p&gt;In my setup I never work on the trunk directly.  Consider the trunk as the folder that contains &lt;i&gt;pre-&lt;/i&gt;finalized code.  That's right, read this again, no trunk development.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;A typical setup on my server will look something similar to this:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;/home/milan/projects/&lt;br /&gt;                     projectA/&lt;br /&gt;                     projectB/&lt;br /&gt;                     projectC/&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Each of these projects is actually a checked out branch of the trunk.  This I do with a simple &lt;i&gt;svn checkout&lt;/i&gt; command as in:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;mkdir -p /home/milan/projects/projectA &lt;br /&gt;svn co svn+ssh://local.svn.server/usr/repository/svn/projects/projectA/branches/active /home/milan/projects/projectA&lt;br /&gt;svn co svn+ssh://local.svn.server/usr/repository/svn/projects/projectB/branches/active /home/milan/projects/projectB&lt;br /&gt;svn co svn+ssh://local.svn.server/usr/repository/svn/projects/projectC/branches/active /home/milan/projects/projectC&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is neat because nowhere do we have to &lt;i&gt;see&lt;/i&gt; the words "trunk" or "branch".  This is perfect for developers who do not want to fiddle in SVN lingo and who may rely on an in-house developed build script.  As far as the developer is concerned there is only a set of source files that then somehow get magically placed in a repository.&lt;/p&gt;&lt;p&gt;Either way it's clean and compact for every developer at all skill levels.&lt;/p&gt;&lt;h3&gt;Branch Merging&lt;/h3&gt;&lt;p&gt;There are many resources online discussing how to merge branch to trunk or trunk to branch.  What we will not find of as much is how to merge our branches in such a way as to avoid the annoying &lt;i&gt;tree conflicts&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;A &lt;i&gt;tree conflict&lt;/i&gt; can occur for many reasons.  In my case the conflict occurred on files that were either added or deleted in my branch but somehow were not making it out or in to the trunk after a merge.&lt;/p&gt;&lt;p&gt;To narrow the example down even more, when the trunk had a file for example, and I removed the file from my branch, it would still stay in the trunk even after a branch to trunk merge.  What did I get as a message to help me out in resolving this?  A tree conflict.  Great.  That tells me nothing.&lt;/p&gt;&lt;h4&gt;Merging Convention&lt;/h4&gt;&lt;p&gt;The &lt;a href="http://svnbook.red-bean.com/en/1.0/svn-book.html#svn-ch-4-sect-4"&gt;SVN book&lt;/a&gt;'s solution on how to merge my branch back to the trunk, we find we would have to do something like this:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$ cd projectA/trunk&lt;br /&gt;$ svn update&lt;br /&gt;At revision 405.&lt;br /&gt;&lt;br /&gt;$ svn merge -r 341:HEAD svn+ssh://local.svn.server/usr/repository/svn/projects/projectC/branches/active&lt;br /&gt;U   integer.c&lt;br /&gt;U   button.c&lt;br /&gt;U   Makefile&lt;br /&gt;&lt;br /&gt;$ svn status&lt;br /&gt;M   integer.c&lt;br /&gt;M   button.c&lt;br /&gt;M   Makefile&lt;br /&gt;&lt;br /&gt;# ...examine the diffs, compile, test, etc...&lt;br /&gt;&lt;br /&gt;$ svn commit -m "Merged projectC branch changes r341:405 into the trunk."&lt;br /&gt;Sending        integer.c&lt;br /&gt;Sending        button.c&lt;br /&gt;Sending        Makefile&lt;br /&gt;Transmitting file data ...&lt;br /&gt;Committed revision 406.&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Notice how it relies on having a trunk checked out.  To me that's a no no.  Not only that but to find the &lt;i&gt;341&lt;/i&gt; number one would have to run a command such as:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;svn log --stop-on-copy&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;One would then have to find the last entry and take the revision number of that entry.  It's a mouthful but I wrote another article how to speed up that step as well.&lt;/p&gt;&lt;h3&gt;Problem&lt;/h3&gt;&lt;p&gt;As mentioned before the common problem are tree conflicts from added and deleted files between the trunk and checked out branches.  This means that when we run a &lt;i&gt;svn status&lt;/i&gt; we will have a bunch of "C" characters appearing next to files in conflict that will need to be resolved prior being able to do a &lt;i&gt;svn commit&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;This is painful and not only that but when you &lt;i&gt;svn resolved&lt;/i&gt; the file and successful &lt;i&gt;svn commit&lt;/i&gt; it &lt;b&gt;still&lt;/b&gt; doesn't reflect such changes onto the trunk when merged.  What the heck!?&lt;/p&gt;&lt;p&gt;Okay so I'm sure there is a technical reason for why this is happening, but quite frankly this is not something SVN should cave in on and be sufficiently smart to figure out what we want to do.&lt;/p&gt;&lt;h3&gt;Solution&lt;/h3&gt;&lt;p&gt;My solution is actually a lot simpler than the aforementioned official version and the files that we add or remove in our branch will actually get added or removed from the trunk after a merge.&lt;/p&gt;&lt;p&gt;In my example we assume we only have a branch checked out and no trunk.  This means that my example will assume you're working in a checked out branch.  That's it.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;cd projectA/&lt;br /&gt;svn up&lt;br /&gt;svn delete someFile&lt;br /&gt;svn commit&lt;br /&gt;svn up&lt;br /&gt;svn switch svn+ssh://local.svn.server/usr/repository/svn/projects/projectA/trunk&lt;br /&gt;svn up&lt;br /&gt;svn merge svn+ssh://local.svn.server/usr/repository/svn/projects/projectA/trunk \&lt;br /&gt; svn+ssh://local.svn.server/usr/repository/svn/projects/projectA/branches/active&lt;br /&gt;svn commit&lt;br /&gt;svn up&lt;br /&gt;svn switch svn+ssh://local.svn.server/usr/repository/svn/projects/projectA/branches/active&lt;br /&gt;svn up&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;It may appear convoluted at first, but after you understand that you need to run a &lt;i&gt;svn up&lt;/i&gt; to avoid &lt;a href="http://svn.apache.org/repos/asf/subversion/trunk/doc/user/svn-best-practices.html"&gt;mixed-revision working copies&lt;/a&gt; it begins to make sense.&lt;/p&gt;&lt;p&gt;What it boils down to is this:&lt;/p&gt;&lt;ol&gt;&lt;li&gt; Add/delete your files in your branch&lt;br /&gt;&lt;li&gt; Switch your branch to become your trunk&lt;br /&gt;&lt;li&gt; Merge your branch into this trunk&lt;br /&gt;&lt;li&gt; Switch back your working directory to become your branch again&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;This allows you to not have a separate checked out trunk and a separate checked out branch.&lt;/p&gt;&lt;h3&gt;Merge Tool&lt;/h3&gt;&lt;p&gt;You have by now undoubtedly come across a tool that exists to facilitate branch merging called &lt;a href="http://svn.apache.org/repos/asf/subversion/trunk/contrib/client-side/svnmerge/svnmerge.py"&gt;svnmerge.py&lt;/a&gt;.  You can always use it, but that's another prerequisite for your system ;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-4956245243307417774?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/4956245243307417774/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/06/svn-merge-branch-to-trunk-with-minimal.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/4956245243307417774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/4956245243307417774'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/06/svn-merge-branch-to-trunk-with-minimal.html' title='SVN Merge Branch To Trunk with minimal Tree Conflicts'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-7316984899370391751</id><published>2010-06-28T12:35:00.000-07:00</published><updated>2010-06-28T12:37:08.243-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='subversion'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>SVN one-liner: Get branch creation revision</title><content type='html'>&lt;p&gt;It is sometimes useful to know at what revision a project was branched.  Mostly this is used for merges, which in turn may be automated in build systems.  This is where a one-liner may be useful.&lt;/p&gt;&lt;h4&gt;SVN Log&lt;/h4&gt;&lt;p&gt;We know that &lt;i&gt;svn log --stop-on-copy&lt;/i&gt; let's us see when a codebase was branched off.  This is usually the last revision number in the list generated by this command.  The question is: &lt;i&gt;how do we extract this revision number?&lt;/i&gt;&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;The one-liner assumes a relatively full UNIX installation that contains the tools &lt;i&gt;grep&lt;/i&gt;, &lt;i&gt;tail&lt;/i&gt;, and &lt;i&gt;sed&lt;/i&gt;.  If your system doesn't have either of them, install them.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;svn log --stop-on-copy | grep r[0-9] | tail -1 | sed 's/r\([0-9]*\)\ .*/\1/g'&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above one-liner gets all revisions, takes the last line, and then uses some regular expression magic to extract the revision number at which time the branch was created (this is an assumption based on good SVN housekeeping).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-7316984899370391751?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/7316984899370391751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/06/svn-one-liner-get-branch-creation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/7316984899370391751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/7316984899370391751'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/06/svn-one-liner-get-branch-creation.html' title='SVN one-liner: Get branch creation revision'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-1617656334967047563</id><published>2010-06-12T14:22:00.000-07:00</published><updated>2010-06-12T14:23:02.253-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='freebsd'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><title type='text'>FreeBSD Makefile Local Variables</title><content type='html'>&lt;p&gt;It is sometimes useful to have local variables in a Makefile that are available only to certain targets.  In GNU make this is possible, however in the make utility included in FreeBSD's distribution the only local variables available to us are the make's seven included local variables.  In other words, in FreeBSD there is no mechanism to have local variables - but there is a way to simulate it.&lt;/p&gt;&lt;h3&gt;GNU make&lt;/h3&gt;&lt;p&gt;In GNU make we can create local variables by specifying them on the target line as such:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;target: SOMEVAR=1&lt;br /&gt;      @echo "I see " ${SOMEVAR}&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This will yield the following output:&lt;/p&gt;&lt;pre&gt;I see 1&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;GNU make is great, but what if we don't have &lt;i&gt;gmake&lt;/i&gt; installed?  This is where we have to get a little creative.&lt;/p&gt;&lt;h3&gt;FreeBSD's make&lt;/h3&gt;&lt;p&gt;The out-of-the-box make utility that comes with FreeBSD has some built-in features that we can use to simulate local variables.  The above code would normally throw an error on FreeBSD saying something to the effect that &lt;i&gt;SOMEVAR=1&lt;/i&gt; target doesn't exist since it treats it as a dependency unable to understand the &lt;i&gt;gmake&lt;/i&gt; local variable declaration construct.  Boohoo.&lt;/p&gt;&lt;p&gt;The solution is pretty simply.  We can translate the above GNU make code into FreeBSD native make code:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;.ifmake target&lt;br /&gt;SOMEVAR=1&lt;br /&gt;.endif&lt;br /&gt;&lt;br /&gt;target:&lt;br /&gt;        @echo "I see " $(SOMEVAR);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The variable will still be global, but it will only be defined if the intended target is called upon.  We can effectively wipe it out with an &lt;i&gt;else&lt;/i&gt; statement if we don't want it to be available on any other targets.  Again, this is just simulated, not a real local variable.  This is very useful when you want to do some advanced conditional tasks on targets.  I like to use this to maintain one target that can adapt to Apache 1 and Apache 2 accordingly (e.g. when compiling PHP).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-1617656334967047563?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/1617656334967047563/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/06/freebsd-makefile-local-variables.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/1617656334967047563'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/1617656334967047563'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/06/freebsd-makefile-local-variables.html' title='FreeBSD Makefile Local Variables'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-985071764921725534</id><published>2010-06-04T13:10:00.000-07:00</published><updated>2010-06-04T13:10:50.151-07:00</updated><title type='text'>Multiple Monitors via USB</title><content type='html'>&lt;p&gt;If you are looking to extend your workspace with multiple monitors but you do not have many video ports, there is an alternative solution: monitor-over-USB.&lt;/p&gt;&lt;p&gt;In my setup I have five (5) monitors, but my laptop only has one video port and one digital video port.  This means that my hardware limits me to two (2) monitors.  To extend this I got three &lt;a href="http://www.arkview.com/eshop/goods.php?id=19"&gt;&lt;i&gt;Arkview USB 2.0 Display Adapter&lt;/i&gt;s&lt;/a&gt;.  It supports up to six (6) adapters, which means I could go as much as eight (8) monitors.&lt;/p&gt;&lt;p&gt;While they work relatively well there are some small quirks with some of them.  In this post I will describe some issues I have with them and how I manually solve them in case you encounter the same.&lt;/p&gt;&lt;h3&gt;Troubleshooting&lt;/h3&gt;&lt;h4&gt;Monitor doesn't turn on at system boot&lt;/h4&gt;&lt;p&gt;This is an interesting issue and there are several things to try when this happens. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;The first thing you have to make sure of is that the Arkview adapter powered on properly.  It seems that this is the root of all evil with screens not displaying anything.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The next thing you want to try is unplug the adapters that did not fire up.  There are two ways you can do this:&lt;br /&gt;&lt;/p&gt;&lt;ol&gt; &lt;li&gt; Unplug the USB side of the adapter and re-plug it back in.  This may be sufficient to get it back up and running.&lt;br /&gt; &lt;li&gt; Unplug the USB and the video cables of the adapter, replug the USB side into the adapter and then replug the video side.  It may take a second for the green light to come back on.&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;If the above don't work, try to unplug all adapters that failed and try the above in different orders.  You do not usually have to unplug the adapters that did fire up properly in order to get the failed ones to work.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-985071764921725534?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/985071764921725534/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/06/multiple-monitors-via-usb.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/985071764921725534'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/985071764921725534'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/06/multiple-monitors-via-usb.html' title='Multiple Monitors via USB'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-1598082592054234465</id><published>2010-04-24T20:00:00.000-07:00</published><updated>2010-04-27T13:02:05.660-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Convert mod_rewrite to mod_perl</title><content type='html'>&lt;p&gt;We know that mod_perl allows us to take over much of Apache's work flow.  This holds true for any &lt;i&gt;mod_proxy&lt;/i&gt; directives and functionality as well.&lt;/p&gt;&lt;p&gt;In this article I want to show how we can easily do some advanced mod_rewrite stuff using purely &lt;i&gt;mod_perl&lt;/i&gt; and without having to use LWP for any proxy activity (as some modules do)!&lt;/p&gt;&lt;p&gt;I want to take this a step further though:  I want to do this by giving a configuration in &lt;i&gt;mod_rewrite&lt;/i&gt; and then I want to &lt;i&gt;translate&lt;/i&gt; this into &lt;i&gt;mod_perl&lt;/i&gt; so you can draw the parallels on what needs to happen in mod_perl that correlates to the corresponding functionality using mod_rewrite and mod_proxy.  Strap yourself in for we're entering some really exciting territory, and I know documentation out there for this type of comparison is really scattered and scarce.&lt;/p&gt;&lt;p&gt;We will explore this example using mod_perl 1 so it reaches a wider Perl audience.  The thinking is that there's easily accessible documentation on mod_perl 2's equivalents to mod_perl 1's features.&lt;/p&gt;&lt;h4&gt;Rewrite Goal&lt;/h4&gt;&lt;p&gt;In this example we want to accomplish the following:&lt;/p&gt;&lt;ol&gt;&lt;li&gt; Rewrite visible URL in browser's location bar&lt;br /&gt;&lt;li&gt; Proxy content from another location&lt;br /&gt;&lt;li&gt; Make content appear under the newly rewritten content.&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;In this example we will use the following URIs:&lt;/p&gt;&lt;ol&gt;&lt;li&gt; Original URI: &lt;i&gt;http://www.adamovsky.com/cgi-bin/show_page.pl?hello.html&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Desired URI: &lt;i&gt;http://www.adamovsky.com/show/hello.html&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Display content from: &lt;i&gt;http://www.adamovsky.com/long/folder/hello.html&lt;/i&gt;&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;Are you excited yet or what?  Strap yourself in, this is going to get exciting.&lt;/p&gt;&lt;h4&gt;Apache Setup: mod_rewrite&lt;/h4&gt;&lt;p&gt;The first thing we want to do is configure our Apache so that it will be able to support our desired setup.  If you need a refresher, read some Apache configuration docs &lt;a href="http://httpd.apache.org/docs/1.3/"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;We will need two virtual host directives.  One will serve as the user facing virtual host, and one will be a background virtual host that will serve the proxied content.  The reason we do it this way is because it will demonstrate a setup that will allow for more complex setups.  In other words, you could get away with just one virtual host for both the front and back end in most instances, but again, I want to assume a wider audience.&lt;/p&gt;&lt;h5&gt;Public Virtual Host&lt;/h5&gt;&lt;p&gt;The user facing, or public, virtual host entry would look something like this:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;VirtualHost _default_&gt;&lt;br /&gt;   ServerName adamovsky.com&lt;br /&gt;   ServerAlias www.adamovsky.com&lt;br /&gt;   DocumentRoot /home/path/to/adamovsky.com&lt;br /&gt;   &lt;b&gt;RewriteEngine on&lt;br /&gt;   RewriteCond %{REQUEST_URI} ^/cgi-bin/show_page.pl$&lt;br /&gt;   RewriteCond %{QUERY_STRING} ^(.+)$&lt;br /&gt;   RewriteRule ^(.+)$ /show/$1             [R]&lt;br /&gt;   RewriteRule ^/show/(.+)$ http://10.15.1.5/long/folder/$1  [P,L]&lt;/b&gt;&lt;br /&gt; &amp;lt;/VirtualHost&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;In case this is a little confusing, here is what is happening:&lt;/p&gt;&lt;ol&gt;&lt;li&gt; First we try to match the URI without the query string&lt;br /&gt;&lt;li&gt; Next we match the query string to make sure it conforms to what we need (this would usually be a more complex regular expression)&lt;br /&gt;&lt;li&gt; If the conditions are true, we will rewrite the URL in the location bar&lt;br /&gt;&lt;li&gt; The new rewritten URL will now make a proxy request to the back end virtual host&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;The &lt;i&gt;[R]&lt;/i&gt; stands for &lt;i&gt;rewrite&lt;/i&gt;, and the &lt;i&gt;[P,L]&lt;/i&gt; stands for &lt;i&gt;proxy&lt;/i&gt; and &lt;i&gt;last&lt;/i&gt; as in this being the last rule of the rewrite ruleset that matches the given condition (in case you have other rulesets for other conditions).&lt;/p&gt;&lt;h5&gt;Private Virtual Host&lt;/h5&gt;&lt;p&gt;The virtual host block that will be responsible for actually delivering the content that is proxied will look something like below.  Note that we will use a private IP address.  This can be any private IP address or public IP address though you will not need to have a public IP address as it would be a waste.  In our example we use &lt;i&gt;10.15.1.5&lt;/i&gt; as our private IP address.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;VirtualHost 10.15.1.5&gt;&lt;br /&gt;   ServerName adamovsky.com&lt;br /&gt;   ServerAlias www.adamovsky.com&lt;br /&gt;   DocumentRoot /home/path/to/adamovsky.com&lt;br /&gt; &amp;lt;/VirtualHost&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This example is simple yet advanced in concept.  Take some time to pause, absorb, and understand what is going on.  This will empower you to further develop rulesets that will be a lot more complex.&lt;/p&gt;&lt;p&gt;The back end, or private, block could be anything.  It could be a &lt;a href="http://www.lighttpd.net/"&gt;lighttpd&lt;/a&gt; server instead, a lightweight Apache instance, or even a remote server.  To keep this example simple however we will do everything on the same server.&lt;/p&gt;&lt;h4&gt;Apache Setup: mod_perl&lt;/h4&gt;&lt;p&gt;What follows is the equivalent functionality as described above.  If you have not read the above example do so now.&lt;/p&gt;&lt;p&gt;You might be asking yourself &lt;i&gt;and why are we doing this?&lt;/i&gt;  There are many reasons for this but the main reason is in the event where you have a complex setup that needs a &lt;a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html#RewriteMap"&gt;rewrite map&lt;/a&gt;.  This is where this solution will really shine since with a rewrite map (assuming it's a Perl script) will load up a Perl instance each time (think CGI and not mod_perl).  We're talking rapidly decreasing performance on an active website.&lt;/p&gt;&lt;p&gt;If nothing more, use this as a guide to see how to circumvent mod_rewrite for complex setups just to further your understanding of mod_perl for this purpose.&lt;/p&gt;&lt;h5&gt;Public Virtual Host&lt;/h5&gt;&lt;p&gt;The only block of the two that needs to be modified is the public facing one since the back-end block is just a dummy block serving files.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;VirtualHost _default_&gt;&lt;br /&gt;   ServerName adamovsky.com&lt;br /&gt;   ServerAlias www.adamovsky.com&lt;br /&gt;   DocumentRoot /home/path/to/adamovsky.com&lt;br /&gt;   &lt;b&gt;PerlTransHandler RewriteModule&lt;/b&gt;&lt;br /&gt; &amp;lt;/VirtualHost&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;That's right: we have removed all &lt;i&gt;mod_rewrite&lt;/i&gt; specific directives and replaced them with a &lt;i&gt;PerlTransHandler&lt;/i&gt; which points to our Perl module called &lt;i&gt;RewriteModule&lt;/i&gt;.pm.&lt;/p&gt;&lt;p&gt;Now whenever an incoming request is handled, we pass it off to &lt;i&gt;mod_perl&lt;/i&gt; instead &lt;i&gt;mod_rewrite&lt;/i&gt;.&lt;/p&gt;&lt;h5&gt;Perl Module&lt;/h5&gt;&lt;p&gt;The final piece to this puzzle is the actual mod_perl handler.  Again, keep in mind that this is merely a translation of the equivalent mod_rewrite rulesets listed above.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;package RewriteModule;&lt;br /&gt;&lt;br /&gt;use Apache::Constants qw( :common REDIRECT );&lt;br /&gt;&lt;br /&gt;$| = 1; &lt;br /&gt;my $source_url = 'http://10.15.1.5';  # have this reflect your private IP&lt;br /&gt;&lt;br /&gt;sub handler {&lt;br /&gt; my $r = shift;&lt;br /&gt; return &amp;parse_uri($r);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;sub parse_uri {&lt;br /&gt; my $r = shift;&lt;br /&gt; my $hostname = $r-&gt;hostname;&lt;br /&gt; my $uri = $r-&gt;uri;&lt;br /&gt; my $query = $r-&gt;args;&lt;br /&gt;&lt;br /&gt; if ($uri =~ /^\/cgi-bin\/show_page.pl$/ &amp;&amp; $query =~ /^(.+)$/)&lt;br /&gt;  {&lt;br /&gt;   $r-&gt;headers_out-&gt;set('Location' =&gt; "http://www.adamovsky.com/show/$1");&lt;br /&gt;   $r-&gt;status(REDIRECT);&lt;br /&gt;   $r-&gt;send_http_header;&lt;br /&gt;   return DECLINED;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; if ($uri =~ /^\/show\/(.+)/)&lt;br /&gt;  {&lt;br /&gt;   return DECLINED if $r-&gt;proxyreq;&lt;br /&gt;   $r-&gt;proxyreq(1);   # this is equivalent to &lt;i&gt;[P]&lt;/i&gt;&lt;br /&gt;   $r-&gt;args($query);  # this sets the query string&lt;br /&gt;   $r-&gt;uri("http://$source_url/long/folder/$1");&lt;br /&gt;   $r-&gt;filename( "proxy:http://$source_url/long/folder/$1" );&lt;br /&gt;   $r-&gt;handler('proxy-server');&lt;br /&gt;   return OK;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; return DECLINED;  # in case neither if()'s validate&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;1;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Again, this is a very specific example with much hard-coded paths, URIs, etc.  This is just to show the concept, but you should modularize the code to fit your needs.&lt;/p&gt;&lt;p&gt;If this doesn't excite you, I don't know what will.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-1598082592054234465?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/1598082592054234465/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/04/convert-modrewrite-to-modperl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/1598082592054234465'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/1598082592054234465'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/04/convert-modrewrite-to-modperl.html' title='Convert mod_rewrite to mod_perl'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-2867578472438247211</id><published>2010-04-16T18:47:00.000-07:00</published><updated>2010-04-24T20:10:34.060-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>Advanced CSS Style Order</title><content type='html'>&lt;p&gt;There are as many opinions on how to organize CSS rules as there are personalities.  Whenever I am put in charge of cleaning up the CSS or promulgate a best practice, without hesitation I push for the described solution.  In this article I will present an enterprise level way of organizing CSS rules.&lt;/p&gt;&lt;p&gt;Enterprise level here is defined by how simple it is to augment, maintain, and debug in context of a team rather than an individual author.&lt;/p&gt;&lt;p&gt;At the end of this article it should be evident that this order offers all the benefits that will be outlined in this article.  To be able to make a sound decision on how to organize your CSS you should read what others recommend.  A quick Google search will yield the following:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://erraticwisdom.com/2006/01/18/5-tips-for-organizing-your-css"&gt;5 Tips for organizing your CSS&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.vanseodesign.com/css/how-to-organize-css-files/"&gt;How to organize CSS files?&lt;/a&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.smashingmagazine.com/2007/05/10/70-expert-ideas-for-better-css-coding/"&gt;70 expert ideas for better CSS coding&lt;/a&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;As you can see, everyone has an opinion, and here is mine.&lt;/p&gt;&lt;h4&gt;Benefits&lt;/h4&gt;&lt;p&gt;It is important to me that my CSS works for me, and not the other way around.  To make this happen I need the CSS to be organized in a way that guides me to where I need to be to work with the right style block.  In other words, I don't want to have to &lt;i&gt;waste&lt;/i&gt; my time looking for the right place to edit my rules, I just want to be guided there.&lt;/p&gt;&lt;p&gt;So how can be give our CSS file this unspoken intelligence?&lt;/p&gt;&lt;p&gt;This "intelligence" should yield the following benefits:&lt;/p&gt;&lt;ul&gt;&lt;li&gt; Eliminate duplicate blocks&lt;br /&gt;&lt;li&gt; Eliminate duplicate style properties&lt;br /&gt;&lt;li&gt; Easily identify CSS specificity&lt;br /&gt;&lt;li&gt; Minimize scrolling and searching&lt;br /&gt;&lt;li&gt; Facilitate copy and pasting&lt;br /&gt;&lt;li&gt; Make the CSS predictable&lt;br /&gt;&lt;li&gt; Make the CSS intuitive&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;You get the idea.  It should virtually do all the thinking for you.&lt;/p&gt;&lt;h4&gt;Advanced CSS Order&lt;/h4&gt;&lt;p&gt;The key lies in sorting &lt;i&gt;everything alphabetically&lt;/i&gt; with decreasing scope of elements.  Simple as that.  No funky hierarchical layout, no funky indentation, no ad-hoc ordering.  This is fool-proof and we will see how it some cases it will actually benefit you technically.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;body,&lt;br /&gt;html &lt;br /&gt; {&lt;br /&gt;  height: 100%;&lt;br /&gt;  margin: 0;&lt;br /&gt;  padding: 0;&lt;br /&gt;  width: 100%;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;.sprite&lt;br /&gt; {&lt;br /&gt;  background-image: url('sprite.png'),&lt;br /&gt;  display: inline-block;&lt;br /&gt;  padding: 2px 0px;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;#footer&lt;br /&gt; {&lt;br /&gt;  background-color: #fff&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above illustrates the gist of the decreasing scope sort-order while maintaining an &lt;i&gt;alphabetical order&lt;/i&gt; of &lt;i&gt;everything&lt;/i&gt;.&lt;/p&gt;&lt;h4&gt;Decreasing Scope-Order&lt;/h4&gt;&lt;p&gt;Imagine how the CSS is applied to the elements based on the selector.  If a DOM element such as &lt;i&gt;div&lt;/i&gt; is the selector, the scope of that CSS will be all &lt;i&gt;div&lt;/i&gt;s.  A class such as &lt;i&gt;.sprite&lt;/i&gt; will limit that scope only to those elements that have such a class defined onto them.  Lastly, an id will limit the scope to a unique element.  This correlates to the &lt;a href="http://www.w3.org/TR/CSS2/cascade.html#specificity"&gt;CSS specificity&lt;/a&gt; which makes it relatively simple to visualize how a CSS rule will be applied onto the document just by the virtue of its definition order within the CSS file.&lt;/p&gt;&lt;p&gt;Okay maybe the last sentence above was a little overly ambitious, but this is the &lt;i&gt;only&lt;/i&gt; order that will give you anything close to that.&lt;/p&gt;&lt;p&gt;To recap, this means we will order our file in this order:&lt;/p&gt;&lt;ul&gt;&lt;li&gt; DOM Elements&lt;br /&gt;&lt;li&gt; Classes&lt;br /&gt;&lt;li&gt; Ids&lt;br /&gt;&lt;/ul&gt;&lt;h4&gt;Alphabetical Sorting&lt;/h4&gt;&lt;p&gt;It is worth repeating that we will alphabetically sort &lt;i&gt;everything&lt;/i&gt;.  This means the selectors as well as the style properties within CSS definition blocks.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;b&gt;a&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;div&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;h1&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;h2&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;p&lt;/b&gt;&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;b&gt;.entry&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;.row&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;.sprite&lt;/b&gt;&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;&lt;b&gt;#footer&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;#header&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;#navigation&lt;/b&gt;&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Take some time to soak this in.  Notice how we sort the selectors alphabetically?  We will do the same with properties.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;i&gt;selector&lt;/i&gt;&lt;br /&gt; {&lt;br /&gt;  &lt;b&gt;border: 1px solid black;&lt;br /&gt;  margin-bottom: 2px;&lt;br /&gt;  margin-left: 1px;&lt;br /&gt;  margin-right: 2px;&lt;br /&gt;  margin-top: 0px;&lt;br /&gt;  padding: 1px;&lt;br /&gt;  text-indent: 9999px;&lt;br /&gt;  width: 50%;&lt;br /&gt;  z-index: 1px;&lt;/b&gt;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Above we can see the style properties sorted alphabetically.  Give it a shot, and add a top margin and you will see how foolproof it is.  The mere order of things will guide you into the right direction where you would place it, and if there already is something there it will automagically stop you from &lt;i&gt;adding&lt;/i&gt; a &lt;i&gt;duplicate&lt;/i&gt; style property, and instead re-evaluate the existing property and assess whether to &lt;i&gt;edit&lt;/i&gt; it or remove it.  In either case, you will not end up with a bloated CSS file by entering duplicates.&lt;/p&gt;&lt;h4&gt;Multi-line Definitions&lt;/h4&gt;&lt;p&gt;Some CSS developers prefer to have all definitions on one line.  One of the rationales behind this is that they want to &lt;i&gt;see&lt;/i&gt; as much as possible on the screen so they don't have to scroll.&lt;/p&gt;&lt;p&gt;No really.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;i&gt;selector&lt;/i&gt;  { &lt;b&gt;width: 50%; margin-bottom: 2px; text-indent: 9999px; margin-left: 1px; z-in... &lt;/b&gt;  }&lt;br /&gt;&lt;i&gt;selector&lt;/i&gt;  { &lt;b&gt;width: 50%; margin-bottom: 2px; text-indent: 9999px; margin-left: 1px; z-in... &lt;/b&gt;  }&lt;br /&gt;&lt;i&gt;selector&lt;/i&gt;  { &lt;b&gt;width: 50%; margin-bottom: 2px; text-indent: 9999px; margin-left: 1px; z-in... &lt;/b&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I'm not even going to entertain long lines in my example, but as you can imagine these can be some very looooong lines.  Keep in mind that there usually is no sort-order on this line so it is next to impossible to quickly &lt;i&gt;see&lt;/i&gt; duplicates let alone get a visual idea of what's going on without having to &lt;i&gt;read&lt;/i&gt; through all properties.  This is something that can easily be fixed by simply breaking these definitions into separate lines.  No magic here.&lt;/p&gt;&lt;h4&gt;Multi-line Selectors&lt;/h4&gt;&lt;p&gt;The other thing I like to break up into separate lines are the actual selectors of the CSS blocks.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;b&gt;a&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;div&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;h1&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;h2&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;p&lt;/b&gt;&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above is how I like to do things.  It's not so obvious as to why we would want to organize it this way with the above example, but I want to illustrate a point.  Consider the following example.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;b&gt;a&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;div.sprite .entry .float&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;h1.sprite #deal&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;h2.subtitle .center&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;p a span.mail&lt;/b&gt;&lt;br /&gt; {&lt;br /&gt;  ...&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;A more realistic example, as the one above, clearly shows that the selectors can easily grow in length.  Consistently breaking these into separate lines will make it very easy to manage these just as it is managing CSS properties when they are broken up on individual lines.&lt;/p&gt;&lt;p&gt;The next question is &lt;i&gt;why do you put the opening bracket on a separate line?&lt;/i&gt;  Think copy &amp; paste.&lt;/p&gt;&lt;p&gt;When we modify the selectors, either adding or removing, we may trip that opening bracket if we don't pay attention.  The more people deal with our CSS file the more the chances of sloppiness.  To stay in line with enterprise development, we want to minimize the risks, therefore we adopt a convention that minimizes these risks.&lt;/p&gt;&lt;h4&gt;Maintenance&lt;/h4&gt;&lt;p&gt;The usual complaints that will arise from non-enterprise developers is that if a selector changes it will require to move around the block within the file.  Yeah, so?  That's called being professional and doing your job right.  Stop whining.&lt;/p&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;p&gt;We can clearly see that by simply exercising some discipline and uniformity we can achieve all the said benefits.&lt;/p&gt;&lt;p&gt;Try it.  You won't go back to any other order.  This is the new order.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-2867578472438247211?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/2867578472438247211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/04/advanced-css-style-order.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/2867578472438247211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/2867578472438247211'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/04/advanced-css-style-order.html' title='Advanced CSS Style Order'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-8288874073104137002</id><published>2010-04-13T14:40:00.000-07:00</published><updated>2010-04-24T20:11:52.507-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>Automatic SVN file handling one-liner</title><content type='html'>&lt;p&gt;Recently I needed a quick solution for adding and removing my source controlled files that I manage via Subversion (SVN).  The constraints were that I didn't want to write a script for two reasons: it would be silly to write a script for something so conceptually simple, and I have better things to do with my time.&lt;/p&gt;&lt;h4&gt;Problem&lt;/h4&gt;&lt;p&gt;SVN by default requires you to manually add and delete (rm) files.  This is a pain because if you have many files, you will be busy for a while.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;[root@server /root]# svn status&lt;br /&gt;?       milan.txt&lt;br /&gt;!       test.txt&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above symbols indicate &lt;i&gt;milan.txt&lt;/i&gt; is not checked in SVN (new file) and &lt;i&gt;test.txt&lt;/i&gt; is in SVN but no longer on the file system (deleted).&lt;/p&gt;&lt;p&gt;One thing I really like is one-liners when you have access to a command prompt - especially in UNIX flavored operating systems.  One-liners makes it very easy to integrate complex functionality inside other scripts, easily executable from within crontabs, perfect for System Administration, and so on.&lt;/p&gt;&lt;p&gt;There are several resources out there (&lt;a href="http://wimleers.com/blog/syncvsvn-synchronize-cvs-working-copy-with-svn-working-copy"&gt;here&lt;/a&gt;, &lt;a href="http://ceardach.com/blog/2008/07/quick-svn-script-automatically-adding-and-deleting-files"&gt;here&lt;/a&gt;, and &lt;a href="http://blog.sosedoff.com/2009/01/16/svn-auto-add-and-delete/"&gt;here&lt;/a&gt; to name a few) on how to accomplish the addition and removal of files that are source controlled via SVN.&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;My solution is just one line and thus more portable.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px; "&gt;svn status | sed 's/^\!\ *\(.*\)/svn rm \1/' | sed 's/^\?\ *\(.*\)/svn add \1/' | \ &lt;br /&gt;sed -n '/^svn\ / p'&lt;/pre&gt;&lt;p&gt;The output will result in the corresponding SVN commands that can then be fed to whatever you want.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px; "&gt;svn add milan.txt&lt;br /&gt;svn rm test.txt&lt;/pre&gt;&lt;p&gt;You could feed this to &lt;i&gt;xargs&lt;/i&gt; and &lt;i&gt;bash&lt;/i&gt; to execute it sequentially like this:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px; "&gt;svn status | sed 's/^\!\ *\(.*\)/svn rm \1/' | sed 's/^\?\ *\(.*\)/svn add \1/' | \ &lt;br /&gt;sed -n '/^svn\ / p' &lt;b&gt;| xargs -I % bash -c %&lt;/b&gt;&lt;/pre&gt;&lt;p&gt;Pretty simple no? And now you can simply copy and paste this wherever you need it.  I chose to feed it to &lt;i&gt;bash&lt;/i&gt; because that's the shell I use, but you can use whatever you want.&lt;/p&gt;&lt;p&gt;Following this pattern one could easily add handling for any other SVN status.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-8288874073104137002?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/8288874073104137002/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/04/automatic-svn-file-handling-one-liner.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/8288874073104137002'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/8288874073104137002'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/04/automatic-svn-file-handling-one-liner.html' title='Automatic SVN file handling one-liner'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-2275459525693234135</id><published>2010-03-21T11:27:00.000-07:00</published><updated>2010-06-22T11:41:56.887-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='freebsd'/><title type='text'>Setting up a Cloud on FreeBSD</title><content type='html'>This article will explore how to create a cloud-like environment on a FreeBSD server.&lt;br /&gt;&lt;h4&gt;Terminology&lt;/h4&gt;Throughout this article I will make use of certain words that may be foreign to the average user or used in a different context that may call for confusion.  To synchronize our definitions, here is the list of words as used in context of this article:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;cloud&lt;/b&gt; - The architecture that will allow a more fault-tolerant response to a request.&lt;br /&gt;&lt;li&gt;&lt;b&gt;host&lt;/b&gt; - The physical server that runs the &lt;i&gt;proxy&lt;/i&gt; and hosts all jail instances.&lt;br /&gt;&lt;li&gt;&lt;b&gt;jail&lt;/b&gt; - A virtual server instance via FreeBSD's jail() command.&lt;br /&gt;&lt;li&gt;&lt;b&gt;node&lt;/b&gt; - Any given building block of the cloud environment (e.g. jail, proxy, host, ...)&lt;br /&gt;&lt;li&gt;&lt;b&gt;proxy&lt;/b&gt; - The proxy software running on the &lt;i&gt;host&lt;/i&gt; (e.g. HAProxy).&lt;br /&gt;&lt;li&gt;&lt;b&gt;repository&lt;/b&gt; - A shared folder containing common files. &lt;br /&gt;&lt;li&gt;&lt;b&gt;user&lt;/b&gt; - An end-user making requests to your services.&lt;br /&gt;&lt;/ul&gt;&lt;h4&gt;Desired Architecture&lt;/h4&gt;&lt;p&gt;Here I will attempt to give a quick snapshot of where we're headed so you can decide if this is a setup you want to mimic.&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S5-Kn63d3cI/AAAAAAAAACE/ld7mwvUsTKc/s1600-h/Example.gif" imageanchor="1" linkindex="17" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S5-Kn63d3cI/AAAAAAAAACE/ld7mwvUsTKc/s320/Example.gif" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;When a user makes a request it will have to figure out which &lt;i&gt;node&lt;/i&gt; in the &lt;i&gt;cloud&lt;/i&gt; is best suited to handle the request.  The course of action happens something along these lines:&lt;/p&gt;&lt;ul&gt;&lt;li&gt; Request goes to DNS&lt;br /&gt;&lt;li&gt; DNS sends the request to either &lt;i&gt;Server A&lt;/i&gt; or &lt;i&gt;Server B&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Selected server forwards request to internal &lt;i&gt;proxy&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Proxy load balances the jail nodes&lt;br /&gt;&lt;li&gt; Proxy proxies request to best suited jail node&lt;br /&gt;&lt;li&gt; Response get sent back to user.&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;This is a basic request/response schema.  Now we have to configure it so that when one of the jail nodes are down, it can continue serving the requests transparently.  Keep in mind this is a simple illustration of the concept; in production this will be replicated to as many nodes as needed.  Once you understand a basic setup, you can very quickly expand it to a very sophisticated design.&lt;/p&gt;&lt;h4&gt;Pre-requisites&lt;/h4&gt;We will need to download a few software packages to get the whole setup going.  If you follow these steps, it should be a relatively smooth process. &lt;ul&gt;&lt;li&gt; FreeBSD 6.2+&lt;br /&gt;&lt;li&gt; Network already setup and configured&lt;br /&gt;&lt;li&gt; GNU make (gmake)&lt;br /&gt;&lt;li&gt; HAProxy&lt;br /&gt;&lt;li&gt; DNS (e.g. Bind, myDNS)&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;Not too bad.  The hardest part will be having the discipline of adhering to some conventions that will be spelled out in this article.  The good thing is that even if there is a lack of discipline it will not break the architecture, it will merely clutter it.  In a sense this is a fool-proof design.&lt;/p&gt;&lt;h4&gt;Naming Convention&lt;/h4&gt;&lt;p&gt;It is important to settle on an extensible naming convention for your cloud environment.  This is a fundamental key ingredient to a successful architecture that is overlooked more often than not.  Here you will see a naming convention that I have come up with that is abstract, flexible, and extensible all in one.&lt;/p&gt;&lt;p&gt;Before we explore the naming convention itself, I want to highlight the goals this convention is intended to tackle.&lt;/p&gt;&lt;p&gt;The naming convention successfully considers the following points&lt;/p&gt;&lt;ul&gt;&lt;li&gt; Geographically agnostic (&lt;i&gt;we don't care &lt;/i&gt;where&lt;i&gt; the node is e.g. data center, city, country&lt;/i&gt;)&lt;br /&gt;&lt;li&gt; Owner agnostic (&lt;i&gt;we don't care &lt;/i&gt;who&lt;i&gt; the node belongs to&lt;/i&gt;)&lt;br /&gt;&lt;li&gt; Product agnostic (&lt;i&gt;we don't care &lt;/i&gt;what&lt;i&gt; software runs on the node&lt;/i&gt;)&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;In a cloud environment it is very important to decouple each node as much as logically possible.  This is analogous to good Object Oriented Programming, where we abstract our classes so they can be as interchangeable as logically possible.&lt;/p&gt;&lt;p&gt;For our sake and purposes we want to achieve this decoupling so that the nodes can remain mobile.  This means we want to be able to move them around anywhere in the cloud without having to worry about the name of the node misleading the user as to its functionality based on an out-of-sync description.  If none of this makes sense or you have not thought of these points, simply follow my convention and you will be relatively safe and immune to any shortcomings accompanied by an expanding or dynamic topology.&lt;/p&gt;&lt;h4&gt;Name Anatomy&lt;/h4&gt;&lt;p&gt;The name that you choose is divided into three logical parts.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Purpose&lt;br /&gt;&lt;li&gt;Environment&lt;br /&gt;&lt;li&gt;Enumerator&lt;br /&gt;&lt;/ol&gt;&lt;h5&gt;Purpose&lt;/h5&gt;&lt;p&gt;The &lt;b&gt;purpose&lt;/b&gt; of a node would describe what the node's main reason for being is - or &lt;i&gt;purpose&lt;/i&gt;.  We want to keep this abstract so a purpose such as &lt;i&gt;db&lt;/i&gt; would be preferred over &lt;i&gt;oracle&lt;/i&gt;, &lt;i&gt;mysql&lt;/i&gt;, or &lt;i&gt;microsoft-sql&lt;/i&gt;.  While it is highly recommended to keep the purposes abstract, it may be desired by business owners to associate &lt;i&gt;what&lt;/i&gt; is running on the node.  I don't advise it.&lt;/p&gt;&lt;p&gt;Take the example of everyone running Oracle in the 90's and now those same companies migrating to mySQL to lower their financial overhead (e.g. licensing fees).  Had they attached &lt;i&gt;what&lt;/i&gt; instead of &lt;i&gt;purpose&lt;/i&gt;, they would now have to find all occurrences of &lt;i&gt;oracle&lt;/i&gt; to &lt;i&gt;mysql&lt;/i&gt; in all documentation, code, topology maps, etc.  Time well wasted, not to mention the opportunity for human error by way of overlooking some occurrences leading to potential software failures.&lt;/p&gt;&lt;h5&gt;Environment&lt;/h5&gt;&lt;p&gt;The next part of a name is the &lt;i&gt;environment&lt;/i&gt; the node finds itself under.  The generally accepted environments consist of a development, staging, and production environment - commonly referred to as &lt;i&gt;dev&lt;/i&gt;, &lt;i&gt;stag&lt;/i&gt;, and &lt;i&gt;prod&lt;/i&gt;.  We can leverage this convention and integrate it into our name.&lt;/p&gt;&lt;p&gt;Sticking to the example we've used up to this point, our name looks something similar to &lt;i&gt;db.dev&lt;/i&gt;, &lt;i&gt;db.stag&lt;/i&gt;, &lt;i&gt;db.prod&lt;/i&gt; thus far.  This is an incomplete name!  Keep reading for the full intended name.  I'm just illustrating what we have accomplished up to this point.&lt;/p&gt;&lt;p&gt;It is important to understand that all of these environments mirror at least what's in the &lt;i&gt;prod&lt;/i&gt; node.  This means that what we see on the final product, or &lt;i&gt;production&lt;/i&gt;, can also be found in &lt;i&gt;stag&lt;/i&gt; and &lt;i&gt;dev&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;Conversely, everything we find on &lt;i&gt;dev&lt;/i&gt; will definitely not be on &lt;i&gt;stag&lt;/i&gt; and &lt;i&gt;prod&lt;/i&gt;.  This is stating the obvious, but I want for even the beginner to understand this, and that this architecture is actually designed to allow a developer to be able to literally crash his or her own development node without adversely effecting the rest of the infrastructure.&lt;/p&gt;&lt;h5&gt;Enumerator&lt;/h5&gt;&lt;p&gt;The last part is the enumerator.  This is a numeric value that is simply incremented by one and can be anything.  I like to use double digit (e.g. &lt;i&gt;01&lt;/i&gt;) as the likelihood of exceeding single digit is high, but exceeding double digit is low - in my case.  Again, keep in mind that with virtual nodes (e.g. jail, vmware, xen) it is very easy to quickly pile up node names.&lt;/p&gt;&lt;p&gt;Finally we come up with a name such as &lt;i&gt;db.dev.01&lt;/i&gt;, &lt;i&gt;db.stag.01&lt;/i&gt;, and &lt;i&gt;db.prod.01&lt;/i&gt;.  This can then be sliced and diced anyhow you want with the node's integrity intact.&lt;/p&gt;&lt;p&gt;There is one more important caveat to the enumerator in context of the environment.  Pay attention.  This is very important to understand, accept, and agree on, for the sake of keeping in line with the goals of a successful cloud implementation: &lt;i&gt;An equivalent enumerator across the environments does not imply mirroring&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;In other words, what I'm saying is that you do not want to get trapped into thinking that &lt;i&gt;db.prod.01&lt;/i&gt; is necessarily a mirror of &lt;i&gt;db.stag.01&lt;/i&gt;.  On a small topology this will &lt;b&gt;coincidentally&lt;/b&gt; be the case, but never intentionally.  It can therefore very well be that when we push content from stag to prod, that we push from &lt;i&gt;db.prod.03&lt;/i&gt; from &lt;i&gt;db.stag.01&lt;/i&gt;.  These are then linked &lt;i&gt;implicitly&lt;/i&gt; as opposed to &lt;i&gt;explicitly&lt;/i&gt;.  This means that we do not define this relationship by way of the naming convention.  All relationships between nodes are &lt;i&gt;always&lt;/i&gt; handled externally to the naming convention via some sort of programmatic logic (e.g. proxy, code).&lt;/p&gt;&lt;p&gt;The importance of the previous paragraph cannot be stressed enough.  The enumerator's purpose is really to just uniquely identify the node.  This will prove very helpful in a collaborative environment where each developer may &lt;i&gt;each&lt;/i&gt; get a same purpose node, with a different enumerator, that will all push to the same staging and production environment.&lt;/p&gt;&lt;h4&gt;Naming Convention Examples&lt;/h4&gt;&lt;p&gt;To get you on your merry way here are some names that I like to use (keep in mind that they all have postfixes of environments and enumerators e.g. web.&lt;i&gt;dev.01&lt;/i&gt;):&lt;p&gt;&lt;ul&gt;&lt;li&gt;asset - Static asset server (lighttpd serving GIFs, JPGs, JS libraries)&lt;br /&gt;&lt;li&gt;db - Database server&lt;br /&gt;&lt;li&gt;proxy - Proxy server&lt;br /&gt;&lt;li&gt;server - Host server (physical server that runs jails for example)&lt;br /&gt;&lt;li&gt;web - Web server&lt;br /&gt;&lt;/ul&gt;&lt;h4&gt;Preparing FreeBSD&lt;/h4&gt;&lt;p&gt;The first thing we want to make sure is that we have a clean, and that means lean, &lt;i&gt;host&lt;/i&gt; server.  We want to try to keep only the absolutely necessary software installed on the &lt;i&gt;host&lt;/i&gt; as to minimize potential application-originating security holes as well as reducing any physical server resource hogging.&lt;/p&gt;&lt;p&gt;The best approach is to disable all daemons such as DNS, sendmail, Apache, inetd, and anything else.  We do not need these on the &lt;i&gt;host&lt;/i&gt; server since we will be running all of these services within sandboxed &lt;i&gt;jail&lt;/i&gt;s.  How to disable these is beyond the scope of this article, but it shouldn't be that difficult.  &lt;a href="http://www.google.com"&gt;Google it&lt;/a&gt;.&lt;/p&gt;&lt;h5&gt;FreeBSD Source&lt;/h5&gt;&lt;p&gt;It is critical that when FreeBSD was installed, all the sources were installed as well.  To check if this is the case check the &lt;i&gt;/usr/src&lt;/i&gt; folder.  If it is populated you're good - otherwise install it before proceeding.  This will be necessary for jail creations.&lt;/p&gt;&lt;h5&gt;Filesystem Hierarchy&lt;/h5&gt;&lt;p&gt;There are a million and one ways you can organize your file system.  In this tutorial I will follow my recommendations but do feel free to adapt any examples to your hierarchy.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;h5&gt;Jail base&lt;/h5&gt;&lt;p&gt;We want to keep all our jails inside one common root folder.  Let that path be &lt;i&gt;/usr/jails/&lt;/i&gt;.  This means if I will setup a jail with the hostname &lt;i&gt;web.dev.01.adamovsky.com&lt;/i&gt;, the root folder of that jail would be situated in &lt;i&gt;/usr/jails/web/dev/01/adamovsky.com&lt;/i&gt;.  You can of course choose any type of convention you want since this convention does not have any impact on the actual setup we are trying to achieve.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;h5&gt;System File Repository&lt;/h5&gt;&lt;p&gt;The next thing is a little controversial in setup, but assuming security precautions have been taken on your overall OS setup, this repository will make it very easy to keep all jails in sync in regards to system files. Disclaimer has been given.&lt;/p&gt;&lt;p&gt;&lt;p&gt;The goal of this setup is to make these system files shared amongst all jail nodes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;/etc/hosts&lt;br /&gt;&lt;li&gt;/etc/resolv.conf&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;You can of course expand upon this list.  Basically these are important files that are to be shared so that when an update is made to them they are immediately reflected in all jails automagically.&lt;/p&gt;&lt;p&gt;The folder I like to place all the system files is in the semantically correct folder &lt;i&gt;/usr/local/share/system/&lt;/i&gt;.  In this folder I replicate the hierarchy of the files.  This means &lt;i&gt;/etc/hosts&lt;/i&gt; would be in &lt;i&gt;/usr/local/share/system/etc/hosts&lt;/i&gt;.  Keeps it easy to navigate.&lt;/p&gt;&lt;p&gt;All we need to do at this point is just move the files into this shared repository.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;mkdir -p /usr/local/share/system/etc&lt;br /&gt;     mv /etc/hosts /usr/local/share/system/etc/hosts&lt;br /&gt;     mv /etc/resolv.conf /usr/local/share/system/etc/resolv.conf&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Scary stuff.  We have just moved some critical files to networking away from the expected locations.  Let's make some adjustments so that FreeBSD won't complain.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;ln -s /usr/local/share/system/etc/hosts /etc/hosts&lt;br /&gt;     ln -s /usr/local/share/system/etc/resolv.conf /etc/resolv.conf&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;What we have done here is symbolically link these files from the common repository into their intended locations.  Coincidentally this is exactly the same steps we will follow for any jails we create.  It is these steps that will allow us to have a shared system file that will automagically reflect any changes across all jails.&lt;/p&gt;&lt;p&gt;&lt;b&gt;A word of caution:&lt;/b&gt; If the server relies on any NFS mounted filesystems, such mounts may fail upon a server reboot since the &lt;i&gt;/etc/hosts&lt;/i&gt; file may not yet be available for resolving the hosts of your NFS sources.  If this is the case one quick and rigid solution is to simply use the IP addresses rather than hostnames.  Keep this in mind and prepare accordingly as a server reboot &lt;i&gt;will&lt;/i&gt; happen sooner or later.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Jail Setup&lt;/h4&gt;&lt;p&gt;The actual setup of the jail nodes is pretty straight forward.  We will simply follow the steps found in the jail manual (&lt;i&gt;man jail&lt;/i&gt;) but nothing is stopping you from using helper tools like &lt;a href="http://erdgeist.org/arts/software/ezjail/"&gt;ez-jail&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;We will continue using &lt;i&gt;web.dev.01.adamovsky.com&lt;/i&gt; in the examples to follow.  Adjust this according to your needs.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;D=/usr/jails/web/dev/01/adamovsky.com&lt;br /&gt;     cd /usr/src&lt;br /&gt;     mkdir -p $D&lt;br /&gt;     make world DESTDIR=$D&lt;br /&gt;     make distribution DESTDIR=$D&lt;br /&gt;     mount_devfs devfs $D/dev&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;h5&gt;Preparing Filesystem&lt;/h5&gt;&lt;p&gt;We need to make some small tweaks to the filesystem hierarchy to prepare it for some steps down the road.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;h5&gt;Ports Collection&lt;/h5&gt;&lt;p&gt;We need to create the &lt;i&gt;/usr/ports&lt;/i&gt; folder within the jail so we can mount the Ports Collection into the jail.  This will be important for when we will want to add extra applications within the jail.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;mkdir -p /usr/jails/web/dev/01/adamovsky.com/usr/ports&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Once we have the folder created we can mount the ports folder of the &lt;i&gt;host&lt;/i&gt; server.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;mount_nullfs /usr/ports /usr/jails/web/dev/01/adamovsky.com/usr/ports&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Let's not forget about the boot-up process and add this line to &lt;i&gt;/etc/rc.local&lt;/i&gt; too.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;echo "mount_nullfs /usr/ports \&lt;br /&gt;     /usr/jails/web/dev/01/adamovsky.com/usr/ports" &gt;&gt; /etc/rc.local&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;li&gt;&lt;h5&gt;Shared Repository&lt;/h5&gt;&lt;p&gt;The next thing we want to do is create a folder that mirrors our shared repository &lt;i&gt;/usr/local/share/system&lt;/i&gt;.  The reason for this is because we only want one mount point rather than always having to mount individual files.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;mkdir -p /usr/jails/web/dev/01/adamovsky.com/usr/local/share/system&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;As mentioned before, we will repeat the same steps and symbolically link the system files into their respective locations.  Let's do it.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;cd /usr/jails/web/dev/01/adamovsky.com&lt;br /&gt;     rm etc/hosts etc/resolv.conf&lt;br /&gt;     ln -s /usr/local/share/system/etc/hosts etc/hosts&lt;br /&gt;     ln -s /usr/local/share/system/etc/resolv.conf etc/resolv.conf&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Notice the &lt;i&gt;etc&lt;/i&gt; paths are relative to the folder you changed into.&lt;/p&gt;&lt;p&gt;At this point if you make a change in the &lt;i&gt;host&lt;/i&gt; server's &lt;i&gt;/etc/hosts&lt;/i&gt; file for example you should see the changes in the &lt;i&gt;jail&lt;/i&gt;'s &lt;i&gt;/etc/hosts&lt;/i&gt; file (in our example that file would be &lt;i&gt;/usr/jails/web/dev/01/adamovsky.com/etc/hosts&lt;/i&gt;).&lt;br /&gt;&lt;/ul&gt;&lt;h5&gt;Configure Jail&lt;/h5&gt;&lt;p&gt;There is one more critical thing we need to do:  setup the startup configuration for the jail.  This will ensure the jail is booted up properly in the event of a server reboot.  These same settings will be used for starting the &lt;i&gt;jail&lt;/i&gt; manually.&lt;/p&gt;&lt;p&gt;Open up the file &lt;i&gt;/etc/rc.conf&lt;/i&gt;.  In this file we need to make sure that the following few lines exist and if they don't add them.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;jail_enable="YES"&lt;br /&gt;  jail_set_hostname_allow="NO"&lt;br /&gt;  jail_list="dev"&lt;br /&gt;  jail_interface="bge0"&lt;br /&gt;  jail_procfs_enable="YES"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Pay attention to what needs to be configured here.  The two directives we're interested in are &lt;i&gt;jail_list&lt;/i&gt; and &lt;i&gt;jail_interface&lt;/i&gt;.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;h5&gt;jail_list&lt;/h5&gt;&lt;p&gt;This is the only line that will need to be edited every time a new jail is added.  It essentially stores the list of all the jails that are defined so FreeBSD knows what jails to boot-up for example.&lt;/p&gt;&lt;p&gt;This is a space separated list of all the defined jails.  The jail &lt;i&gt;name&lt;/i&gt; is what needs to be entered here.  This &lt;i&gt;name&lt;/i&gt; is defined in the actual jail definition; read below.&lt;/p&gt;&lt;li&gt;&lt;h5&gt;jail_interface&lt;/h5&gt;&lt;p&gt;This actually determines which network card interface the jail's network is supposed to be attached to.&lt;/p&gt;&lt;p&gt;You can find your interface by running the command &lt;i&gt;ifconfig -a&lt;/i&gt;.  Once you have the interface name simply define it as the &lt;i&gt;jail_interface&lt;/i&gt;.&lt;/p&gt;&lt;/ul&gt;&lt;p&gt;Other than these two directives the other settings will remain pretty untouched as your architecture grows.&lt;/p&gt;&lt;h5&gt;Jail Definition&lt;/h5&gt;&lt;p&gt;The next thing we need to do is configure the actual jail's properties such as IP address, hostname, etc...&lt;/p&gt;&lt;p&gt;Again, open up &lt;i&gt;/etc/rc.conf&lt;/i&gt; in the &lt;i&gt;host&lt;/i&gt; server and add the following (if it's not already in there):&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;jail_dev_hostname="web.dev.01.adamovsky.com"&lt;br /&gt;  jail_dev_ip="10.2.2.10"&lt;br /&gt;  jail_dev_rootdir="/usr/jails/web/dev/01/adamovsky.com"&lt;br /&gt;  jail_dev_devfs_enable="YES"&lt;br /&gt;  jail_dev_exec_start="/bin/sh /etc/rc"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This is the template for a jail definition.  Copy and paste this every time a new jail is added.  There should be one set of the aforementioned configurations for every jail and configured accordingly.&lt;/p&gt;&lt;p&gt;The naming convention that the jail() command expects is jail_&lt;i&gt;jailname&lt;/i&gt;_*.  This means that whenever an entry is made into &lt;i&gt;/etc/rc.conf&lt;/i&gt;, the directives will need to be adjusted to reflect the name of the jail that is being setup.  In our example we use the name &lt;i&gt;dev&lt;/i&gt; but it could be anything.&lt;/p&gt;&lt;p&gt;One important directive here is the &lt;i&gt;jail_dev_ip&lt;/i&gt;.  This directive defined what IP address our jail will be listening to.  This can be any IP address you want, but since our setup will not require it to have direct external access we can get away by assigning an internal IP address (see &lt;a href="http://en.wikipedia.org/wiki/Private_network"&gt;Private Network&lt;/a&gt; Wikipedia entry for internal IP address ranges or consult your Network Administrator).&lt;/p&gt;&lt;p&gt;Save &lt;i&gt;/etc/rc.conf&lt;/i&gt; and exit; you are done with that file - for now.&lt;/p&gt;&lt;h4&gt;Starting Jail&lt;/h4&gt;&lt;p&gt;At this point we are ready to start up our newly created jail.  We will use the standard jail tools for our jail administration.  You can later automated some of these tasks but at this point it is important that you understand what is going on.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;/etc/rc.d/jail start dev&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above command will start the jail with the jail &lt;i&gt;name&lt;/i&gt; "dev" - which we defined in the jail definition up top.&lt;/p&gt;&lt;h4&gt;Install Software Inside Jail&lt;/h4&gt;&lt;p&gt;Now we're ready to setup whatever software we want inside the jail.  To keep our example simple I will limit this to installing the &lt;i&gt;bash&lt;/i&gt; shell as it is my preferred shell to work with.&lt;/p&gt;&lt;p&gt;Let's enter the jail.&lt;/p&gt;&lt;p&gt;We need to find the jail id of our jail.  To do so we use the command &lt;i&gt;jls&lt;/i&gt; which will list all the running jail. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;[root@server /etc]# jls&lt;br /&gt;   JID  IP Address      Hostname                      Path&lt;br /&gt;     3  10.2.2.10       web.dev.01.adamovsky.com      /usr/jails/web/dev/01/adamovsky.com&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;We are ready to enter.  All we need to do is call the command &lt;i&gt;jexec 3 sh&lt;/i&gt;.  This assumes the jail id is &lt;i&gt;3&lt;/i&gt; - but it will be whatever number is displayed using the &lt;i&gt;jls&lt;/i&gt; command above.  In our example it happened to be &lt;i&gt;3&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;At this point you should have gotten a new command prompt.  To ensure that you are in the correct jail check the hostname using the &lt;i&gt;hostname&lt;/i&gt; command.  This should reflect whatever hostname you assigned to the jail in your jail definition.&lt;/p&gt;&lt;h5&gt;Install Bash&lt;/h5&gt;&lt;p&gt;What follows is the process to install any software from the ports collection.&lt;/p&gt;&lt;p&gt;As mentioned above we will install &lt;i&gt;bash&lt;/i&gt; as an example.  So let's get to it.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;cd /usr/ports/shells/bash3&lt;br /&gt;   make clean install&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;We need to make sure to do a &lt;i&gt;clean&lt;/i&gt; install whenever we install anything from the Ports Collection since it's linked against the &lt;i&gt;host&lt;/i&gt; server's ports tree.  This means that if that same package has already been installed on the &lt;i&gt;host&lt;/i&gt; server there will be files that will make the jail ports tree think that the package has already been installed within the jail as well.  The &lt;i&gt;clean&lt;/i&gt; keyword during the make process takes care of this misconception by the build system.&lt;/p&gt;&lt;p&gt;Remember to follow this piece of advice when installing any ports.&lt;/p&gt;&lt;p&gt;Okay we're done with prepping the jail system.  Let's jump back to the &lt;i&gt;host&lt;/i&gt; server.  Simply type &lt;i&gt;exit&lt;/i&gt; at the jail command prompt and that will take you back to the &lt;i&gt;host&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;Repeat all the above jail steps to setup another jail (e.g. &lt;i&gt;web.dev.02.adamovsky.com&lt;/i&gt;).&lt;/p&gt;&lt;h4&gt;Setting Up HAProxy&lt;/h4&gt;&lt;p&gt;Here is where the magic happens.  We need to setup a proxy on the &lt;i&gt;host&lt;/i&gt; server that will act as the load balancer for all our jails.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;fetch http://haproxy.1wt.eu/download/1.4/src/haproxy-1.4.2.tar.gz&lt;br /&gt;   tar -xvzpf haproxy-1.4.2.tar.gz&lt;br /&gt;   make -f Makefile.bsd REGEX=pcre DEBUG= COPTS.generic="-Os -fomit-frame-pointer";&lt;br /&gt;   gmake install&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Okay so I'm making a leap of faith.  The setup that I did used haproxy 1.3.22, but I'm sure it will work with a more recent version as well.  If not, feel free to download an older version of haproxy to get the gist of it and make any needed adjustments to make it work under 1.4.x or the latest version.&lt;/p&gt;&lt;p&gt;That was pretty easy.  Next let's configure the proxy.&lt;/p&gt;&lt;h5&gt;Configure HAProxy&lt;/h5&gt;&lt;p&gt;The configuration of the proxy happens in the file at &lt;i&gt;/usr/local/etc/haproxy/haproxy.conf&lt;/i&gt; in my example, but you can adjust it to reflect your location of the file.&lt;/p&gt;&lt;p&gt;Here is a copy of how the haproxy.conf file would look for our example, assuming two jail nodes, and that your external/outside facing IP address of the &lt;i&gt;host&lt;/i&gt; server is &lt;i&gt;222.222.222.222&lt;/i&gt; (obviously tweak this to reflect your true IP address).&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;global&lt;br /&gt;        log 127.0.0.1   local0&lt;br /&gt;        log 127.0.0.1   local1 notice&lt;br /&gt;        daemon&lt;br /&gt;&lt;br /&gt;  defaults&lt;br /&gt;        log     global&lt;br /&gt;        mode    http&lt;br /&gt;        option  httplog&lt;br /&gt;        option  dontlognull&lt;br /&gt;        option redispatch&lt;br /&gt;        retries 3&lt;br /&gt;        maxconn 2000&lt;br /&gt;        contimeout      5000&lt;br /&gt;        clitimeout      50000&lt;br /&gt;        srvtimeout      120000&lt;br /&gt;&lt;br /&gt;  frontend web_proxy&lt;br /&gt;        bind 222.222.222.222:80&lt;br /&gt;        acl is_web_dev hdr_beg(host) -i web.dev&lt;br /&gt;        use_backend web_dev_cluster if is_web_dev&lt;br /&gt;&lt;br /&gt;  backend web_dev_cluster&lt;br /&gt;        option httpchk&lt;br /&gt;        option httplog&lt;br /&gt;        option httpclose&lt;br /&gt;        option forwardfor&lt;br /&gt;        balance roundrobin&lt;br /&gt;        server web.dev.01 10.2.2.10:80&lt;br /&gt;        server web.dev.02 10.2.2.11:80&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I'm not going into detail as to what does what as it would become too involved.  What you need to do however is understand the basics of how to &lt;a href="http://haproxy.1wt.eu/download/1.4/doc/configuration.txt"&gt;configure HAProxy&lt;/a&gt;.  Comment on this post if you are interested in having me break this down in a separate article.&lt;/p&gt;&lt;p&gt;Once the changes have been made to the haproxy.conf file we need to completely stop the HAProxy daemon and then start it back up.  A regular &lt;i&gt;kill -HUP&lt;/i&gt; will not do.  We need to &lt;i&gt;kill -9&lt;/i&gt; the process and start it back up.&lt;/p&gt;&lt;p&gt;If this is a first install, to start the haproxy all we need to do is call it.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;haproxy -f /usr/local/etc/haproxy/haproxy.conf -p /var/run/haproxy.pid&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Make sure to add this line to &lt;i&gt;/etc/rc.local&lt;/i&gt; as well to ensure proper start-up at boot-up of the &lt;i&gt;host&lt;/i&gt; server.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;echo "haproxy -f /usr/local/etc/haproxy/haproxy.conf \ &lt;br /&gt;   -p /var/run/haproxy.pid &gt;&gt; /etc/rc.local&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Great, now we're done with the TCP proxy.  Next we will need to setup a DNS proxy which happens to be a UDP proxy - something that HAProxy is not suitable for.&lt;/p&gt;&lt;h4&gt;Setting Up DNSProxy&lt;/h4&gt;&lt;p&gt;The other port that is important in this setup is &lt;i&gt;dnsproxy&lt;/i&gt;.  This is a UDP based proxy server specifically developed for DNS proxying.  We will want to use this under the assumption that we are running a DNS service within a jail node.  It would be best to follow the above jail setup steps to setup a new jail for DNS only called &lt;i&gt;dns.prod.01.adamovsky.com&lt;/i&gt; following the convention of our examples.  Adjust the name to your liking.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;cd /usr/ports/dns/dnsproxy &lt;br /&gt;   make clean install&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This should be a relatively simple setup.  Make sure to run this on your &lt;i&gt;host&lt;/i&gt; server and NOT within a jail since it is the &lt;i&gt;host&lt;/i&gt; server that is the acting proxy for all services.&lt;/p&gt;&lt;h5&gt;Configure DNSProxy&lt;/h5&gt;&lt;p&gt;The configuration file for DNSProxy is &lt;i&gt;/usr/local/etc/dnsproxy/dnsproxy.conf&lt;/i&gt; - open it up and edit it to look something like this:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;#&lt;br /&gt;# dnsproxy 1.15 configuration file example&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Authoritative server&lt;br /&gt;#&lt;br /&gt;authoritative           10.2.2.12       # Internal IP of DNS jail&lt;br /&gt;authoritative-port      53              # It's port. Defaults to 53.&lt;br /&gt;authoritative-timeout   10              # Seconds to wait for answers.&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Recursive resolver&lt;br /&gt;#&lt;br /&gt;recursive               10.2.2.12       # Internal IP of DNS jail&lt;br /&gt;recursive-port          53              # It's port. Defaults to 53.&lt;br /&gt;recursive-timeout       90              # Seconds to wait for answers.&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Local address and port of dnsproxy&lt;br /&gt;#&lt;br /&gt;listen 222.222.222.222&lt;br /&gt;port 53&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Security features&lt;br /&gt;#&lt;br /&gt;#chroot /var/empty&lt;br /&gt;user nobody&lt;br /&gt;&lt;br /&gt;#&lt;br /&gt;# Internal networks (allowed to do recursive queries)&lt;br /&gt;#&lt;br /&gt;internal 10.2.2.12&lt;br /&gt;internal 127.0.0.1&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Here we assume that a jail for DNS was setup on the IP address &lt;i&gt;10.2.2.12&lt;/i&gt;.  However if you choose to run a DNS service within another jail simply use the IP address of that jail.  I prefer to segregate my services into individual jails.&lt;/p&gt;&lt;h5&gt;Configure Boot-Up&lt;/h5&gt;&lt;p&gt;Next we need to make sure that DNSProxy is started up automatically when the server reboots.&lt;/p&gt;&lt;p&gt;In &lt;i&gt;/etc/rc.conf&lt;/i&gt; add the line&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;dnsproxy_enable="YES"&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;After everything is done fire it up.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;/usr/local/sbin/dnsproxy -c /usr/local/etc/dnsproxy/dnsproxy.conf -d&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Checking Setup&lt;/h4&gt;&lt;p&gt;At this point you have a basic understanding for what is needed to setup FreeBSD to act as a cloud environment.  Consider this a framework for whatever you want it to do.  Feel free to comment any improvements, additions, or changes you've made with your setup.&lt;/p&gt;&lt;p&gt;Let's run through a checklist to make sure we've done everything:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Configured and started network on &lt;i&gt;host&lt;/i&gt;&lt;br /&gt;&lt;li&gt;Setup jails&lt;br /&gt;&lt;ul&gt;&lt;li&gt;web.dev.01.adamovsky.com&lt;br /&gt;&lt;li&gt;web.dev.02.adamovsky.com&lt;br /&gt;&lt;/ul&gt;&lt;li&gt;Started jails&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Started Apache** inside all jails&lt;br /&gt;&lt;li&gt;Started BIND** inside all jails&lt;br /&gt;&lt;/ul&gt;&lt;li&gt;Started HAProxy&lt;br /&gt;&lt;li&gt;Started DNSProxy&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;** = This assumes you are using the most popular software packages for a given service, but you can run whatever software package you want as long as it listens on the configure ports.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-2275459525693234135?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/2275459525693234135/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/03/setting-up-cloud-on-freebsd.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/2275459525693234135'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/2275459525693234135'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/03/setting-up-cloud-on-freebsd.html' title='Setting up a Cloud on FreeBSD'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S5-Kn63d3cI/AAAAAAAAACE/ld7mwvUsTKc/s72-c/Example.gif' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-668900280794359996</id><published>2010-03-20T17:22:00.000-07:00</published><updated>2010-04-24T20:13:56.860-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><title type='text'>jQuery a-tools plugin insertAtCaretPos() bug solution</title><content type='html'>&lt;p&gt;Andrey Kramarev is the author of the excellent jQuery plugin called a-tools that allows advanced text selection manipulation of HTML form elements.&lt;/p&gt;&lt;p&gt;After having reported a bug that he resolved rapidly in his new version (a-tools 1.3.1), there is another bug that I found in Internet Explorer (tested in IE7 and IE8) that I feel deserves an article as it is easily  circumventable and you may find yourself stuck in a deployment environment where upgrading is not a simple option.  Knowing Andrey, he will undoubtedly have a fix by the time this article reaches you.&lt;/p&gt;&lt;p&gt;Before proceeding, &lt;a href="http://plugins.jquery.com/project/a-tools"&gt;check the repository&lt;/a&gt; to see if a newer version than 1.3.1 is out, and if you have the freedom to upgrade, do so.  Otherwise, if your code is constrained by having to continue using 1.3.1, read below.&lt;/p&gt;&lt;h4&gt;Problem&lt;/h4&gt;&lt;p&gt;The problem lies in the &lt;i&gt;insertAtCaretPos()&lt;/i&gt; function when used on a &amp;lt;textarea&gt; HTML element.&lt;/p&gt;&lt;p&gt;The way to duplicate the problem is to try to insert something into a textarea element that hasn't gotten &lt;i&gt;focus&lt;/i&gt;, doesn't have any content in it, and make sure to use Internet Explorer as a browser.  You can test this using the official demo page at &lt;a href="http://www.ampparit.com/projects/a-tools/demo.html"&gt;http://www.ampparit.com/projects/a-tools/demo.html&lt;/a&gt; if you don't want to create your own test page.&lt;/p&gt;&lt;h5&gt;Demo Page&lt;/h5&gt;&lt;p&gt;If you do choose to use the official demo page, simply try to enter text into the input field next to the &lt;i&gt;Input following text to the caret position&lt;/i&gt; and click the button.  Your content should appear at the very top of the document to the left of the page title.&lt;/p&gt;&lt;p&gt;Pressing the button continuously will result in every other click to insert the text at the top of the page, and every click in between into the correct input field.  Weird, isn't it?&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;The cause of the problem appears to be some sort of incorrect caret positioning handling.  Knowing this, the solution will become a little clearer to understand.&lt;/p&gt;&lt;p&gt;Before we begin hacking away, it's worth mentioning that luckily the hack is cross-browser compatible and will not interfere with browsers who handle a-tools properly, such as FireFox.&lt;/p&gt;&lt;h5&gt;Intended Code&lt;/h5&gt;&lt;p&gt;Normally if we wanted to insert the letter &lt;i&gt;a&lt;/i&gt; into a textarea HTML element using this jQuery plugin, the code would look something like this:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$('textarea').insertAtCaretPos('a');&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;As we can see, a one-liner.&lt;/p&gt;&lt;h5&gt;Hacked Code&lt;/h5&gt;&lt;p&gt;We will need to add some caret manipulation code to help a-tools staying synchronized with the caret's position.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;     var element = $('textarea'),&lt;br /&gt;         caretPos = element.getSelection().start,&lt;br /&gt;         isTextarea = element.is('textarea');&lt;br /&gt;&lt;br /&gt;     if (isTextarea &amp;&amp; caretPos == 0 &amp;&amp; element.val().length == 0)&lt;br /&gt;      {&lt;br /&gt;       element.setCaretPos(2);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     element.insertAtCaretPos('a');&lt;br /&gt;&lt;br /&gt;     if (isTextarea)&lt;br /&gt;      {&lt;br /&gt;       caretPos = element.getSelection().start;&lt;br /&gt;       element.setCaretPos(caretPos + 1);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I used the &lt;i&gt;isTextarea&lt;/i&gt; variable to make it clear what code is needed only for textarea elements.  Make sure to put a conditional around it if your form consists of different HTML form elements as this solution will mess up the normal functionality of non-textarea elements.&lt;/p&gt;&lt;h4&gt;Explanantion&lt;/h4&gt;&lt;p&gt;Let's take a minute to understand the logic behind this code.&lt;/p&gt;&lt;p&gt;First we need to figure out if the textarea that we're dealing with is empty.  This is necessary as the bug doesn't show up on elements who are no longer empty.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;     ...&lt;br /&gt;&lt;br /&gt;     &lt;b&gt;if (isTextarea &amp;&amp; caretPos == 0 &amp;&amp; element.val().length == 0)&lt;br /&gt;      {&lt;/b&gt;&lt;br /&gt;       element.setCaretPos(2);&lt;br /&gt;      &lt;b&gt;}&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;     ...&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;If this proves to be an empty textarea, we need to tell a-tools to set its internal caret position to &lt;i&gt;2&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;The reason for this magical number is that zero doesn't work probably because the official a-tools documentation states &lt;i&gt;1&lt;/i&gt; as being the beginning of the field, and &lt;i&gt;1&lt;/i&gt; not working as far as resetting the internal caret position.  So we increase it to &lt;i&gt;2&lt;/i&gt;; somewhat crude of a method but it works.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;     ...&lt;br /&gt;&lt;br /&gt;     if (isTextarea &amp;&amp; caretPos == 0 &amp;&amp; element.val().length == 0)&lt;br /&gt;      {&lt;br /&gt;       &lt;b&gt;element.setCaretPos(2);&lt;/b&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     ...&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Internally we have now instructed a-tools to focus on the textarea and not target the main document.  This fixes that weird behavior of having the content inserted at the top of the document on every other click rather than inside the input field.&lt;/p&gt;&lt;p&gt;Next we call the normal &lt;i&gt;insertAtCaretPos()&lt;/i&gt; and since we have told a-tools to focus on the textarea at caret position &lt;i&gt;2&lt;/i&gt; (which doesn't exist since the textarea is empty), it will do the next best thing and put it at the beginning of the textarea.  Urgh, what a hack!&lt;/p&gt;&lt;p&gt;The hack is not over though.  Next we need to still help a-tools out.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;     ...&lt;br /&gt;&lt;br /&gt;     if (isTextarea)&lt;br /&gt;      {&lt;br /&gt;       &lt;b&gt;caretPos = element.getSelection().start;&lt;br /&gt;       element.setCaretPos(caretPos + 1);&lt;/b&gt;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above code only applies for textarea elements, so we want to have a conditional around it.&lt;/p&gt;&lt;p&gt;What we do next is get the current caret position &lt;i&gt;after&lt;/i&gt; the text has been inserted, and force the internals of a-tools to increment it by one.  This will ensure that next time we call a-tools it doesn't lose track of its caret position to prevent it from trying to insert the text at the top of the document on every other attempt.&lt;/p&gt;&lt;p&gt;I haven't tried it, but if you will insert a longer string than just a character, you may have to account for the length when resetting the caret.  The code might then look as such:&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;     ...&lt;br /&gt;&lt;br /&gt;     element.insertAtCaretPos(&lt;b&gt;insertedString&lt;/b&gt;);&lt;br /&gt;&lt;br /&gt;     if (isTextarea)&lt;br /&gt;      {&lt;br /&gt;       caretPos = element.getSelection().start;&lt;br /&gt;       element.setCaretPos(caretPos + &lt;b&gt;insertedString.length&lt;/b&gt;);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Follow this solution and you can get away with continue using a-tools 1.3.1 at the cost of a slightly bigger code.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-668900280794359996?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/668900280794359996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/03/jquery-tools-plugin-insertatcaretpos.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/668900280794359996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/668900280794359996'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/03/jquery-tools-plugin-insertatcaretpos.html' title='jQuery a-tools plugin insertAtCaretPos() bug solution'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-2701833211251670155</id><published>2010-03-11T06:02:00.000-08:00</published><updated>2010-04-24T20:14:16.151-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='photoshop'/><title type='text'>Hand tool stuck in Photoshop CS4</title><content type='html'>&lt;p&gt;Recently I was working with Photoshop where all of a sudden the &lt;i&gt;hand tool&lt;/i&gt; was the only tool available to me.  It was almost as if I was in a modal state disallowing me any operations.&lt;/p&gt;&lt;h4&gt;Troubleshooting&lt;/h4&gt;&lt;p&gt;The way I went about finding a solution to this problem was to check that I didn't have any special keys stuck on my keyboard that could alter the behavior of Photoshop.  Nope, all clear.  No shifts, no alts, no stuck function keys, etc.&lt;/p&gt;&lt;p&gt;Next I tried to identify any menu items that were checked that I did not intend to have checked.  Everything seemed to be set normally.&lt;/p&gt;&lt;p&gt;Finally I did a quick Google search and found the solution.&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;Follow these simple steps:&lt;/p&gt;&lt;ul&gt;&lt;li&gt; Enter the &lt;i&gt;Edit&lt;/i&gt; menu&lt;br /&gt;&lt;li&gt; Select &lt;i&gt;Preferences&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Select &lt;i&gt;General&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Click the &lt;i&gt;Reset All Warning Dialogs&lt;/i&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;Problem solved.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-2701833211251670155?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/2701833211251670155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/03/hand-tool-stuck-in-photoshop-cs4.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/2701833211251670155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/2701833211251670155'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/03/hand-tool-stuck-in-photoshop-cs4.html' title='Hand tool stuck in Photoshop CS4'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-5869903814333779962</id><published>2010-03-05T21:04:00.000-08:00</published><updated>2010-04-24T20:14:32.809-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='system administration'/><category scheme='http://www.blogger.com/atom/ns#' term='freebsd'/><title type='text'>NFS Input/Output Error in FreeBSD</title><content type='html'>&lt;p&gt;I had recently experienced some of NFS shares no longer available.  Trying to access them yielded an &lt;i&gt;Input/Output Error&lt;/i&gt; with no errors logged on either the client or server side.&lt;/p&gt;&lt;p&gt;This article will quickly explain how I went about debugging and fixing it.&lt;/p&gt;&lt;h4&gt;Troubleshooting&lt;/h4&gt;&lt;p&gt;The first thing I did was check if the shares were listed.  This can be achieved with a simple &lt;i&gt;df&lt;/i&gt; command.  The chances are your problematic NFS shares will &lt;i&gt;not&lt;/i&gt; show up when running df.&lt;/p&gt;&lt;p&gt;At first you may think that the NFS client cannot mount the NFS shares.  This is incorrect.  The shares &lt;i&gt;are&lt;/i&gt; mounted, since you can access them (except it will yield the Input/Output Error) and it can be &lt;i&gt;umount&lt;/i&gt;ed.  That's right, the NFS shares are mounted, just inaccessible.&lt;/p&gt;&lt;p&gt;The next step is to check the /var/log/messages log file on both the NFS client and server machines.  These will most likely be of little help.  If there are some helpful error messages, follow those as you may be experiencing a different problem with identical symptoms. &lt;/p&gt;&lt;p&gt;The last step to ensure that the NFS is working properly and the shares are mounted, try to unmount them!  This can be done with the command &lt;i&gt;umount /mounts/nfs/share&lt;/i&gt; (where /mounts/nfs/share is replace with your actual NFS share).  You can then try to run the command once more and it should tell you the NFS share cannot be unmount since it's not mounted.  In other words, it &lt;i&gt;was&lt;/i&gt; unmounted successfully the first time aaaaand it also means that it was mounted to begin with.&lt;/p&gt;&lt;p&gt;At this point we have done our due diligence in gathering as much superficial information as we can to assess the state of the problem.  Let's try to solve it now.&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;The solution is pretty simple, and the reason for this article is as much the solution as giving you an insight how to go about debugging NFS issues that may not log any helpful details via syslog or other logging mechanisms.&lt;/p&gt;&lt;p&gt;Connect to the NFS server machine (the server that runs &lt;i&gt;nfsd&lt;/i&gt;) and find the process ID (pid) of the service &lt;i&gt;mountd&lt;/i&gt; and &lt;i&gt;kill -HUP&lt;/i&gt; that process.  In other words simply restart the &lt;i&gt;mountd&lt;/i&gt; process.&lt;/p&gt;&lt;p&gt;This will automagically solve the problem, with no need to remount any of the problematic NFS shares since they were all mounted - just inaccessible.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-5869903814333779962?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/5869903814333779962/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/03/nfs-inputoutput-error-in-freebsd.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/5869903814333779962'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/5869903814333779962'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/03/nfs-inputoutput-error-in-freebsd.html' title='NFS Input/Output Error in FreeBSD'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-884810969595384026</id><published>2010-02-27T19:33:00.000-08:00</published><updated>2010-03-07T15:02:37.035-08:00</updated><title type='text'>One Space Indentation</title><content type='html'>&lt;p&gt;There is always someone on every team that is rigid in their ways, lacks the skill to adapt, or is purely stubbornly set in their ways.  This article is not for such people.  This article is for Enterprise level developers.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Here I want to talk about indentation in coding, and how over the course of 15 years of development on both front-end and back-end systems I have determined the most effective way to indent my code.  That conclusion is that one space is all you need.&lt;/p&gt;&lt;h4&gt;Research&lt;/h4&gt;&lt;p&gt;Whenever I introduce new concepts or ideas I like to do my due research.  I was recently challenged by a fellow web developer on my indent style, with no research on his part.  While I encourage debates, discussions, and questions - I do not respect unfounded statements where the individual has not done their due research before wasting everybody's time.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;There are many good books covering code styles, and without going into a library and reading all these PhD authored books that are based on good research, I do encourage a basic Google search or at the very least referencing Wikipedia's &lt;a href="http://en.wikipedia.org/wiki/Indent_style"&gt;Indent Style&lt;/a&gt; article.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;My indent style follows closest the GNU style (see Wikipedia).&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Tabs Are For Beginners&lt;/h4&gt;&lt;p&gt;Many developers when starting out learn programming reading great books where code samples are illustrated to be clear for beginners.  Much attention is given to the &lt;i&gt;programming&lt;/i&gt; aspect of such books, with formatting being addressed only in the beginning - but they never evolve the formatting throughout the pages causing for the reader to blindly accept such formatting and develop a complacent mindset in that regards.&lt;/p&gt;&lt;p&gt;Needless to say many books use &lt;i&gt;tabs&lt;/i&gt; to clearly illustrate indentation.  This is, in my opinion, a highly exaggerated display of indentation just like teachers would use exaggerated letter sizes when teaching the alphabet.  In other words, tabs are nothing more than a learning tool, training wheels, something one has to evolve away from as one gets more sophisticated.&lt;/p&gt;&lt;h4&gt;Four spaces are tabs&lt;/h4&gt;&lt;p&gt;Read above.&lt;/p&gt;&lt;h4&gt;Two Spaces Are Good&lt;/h4&gt;&lt;p&gt;They are half as wasteful as tabs or four spaces, so this is a good start. &lt;/p&gt;&lt;p&gt;The only place I feel that two spaces are needed is in HTML code as keeping it down to one space would lose the indentation due to the opening character of each indent, which happens to be the &lt;i&gt;less than&lt;/i&gt; sign - or "&lt;".&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;html&gt;&lt;br /&gt; &amp;lt;head&gt;&lt;br /&gt;  &amp;lt;title&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Using the Courier New font we can see the indentation somewhat, but with other fonts it seems to give off a visual diagonal line when connecting the lesser than signs.  Adding two spaces cleans this up.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;html&gt;&lt;br /&gt;   &amp;lt;head&gt;&lt;br /&gt;      &amp;lt;title&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;This only applies to HTML due to the aforementioned reason.  Any brace-enabled language such as CSS, JavaScript, C, Perl, PHP, etc... only need one space indentation to remain clear.  This is where the whining should stop (e.g. &lt;i&gt;but I'm used to&lt;/i&gt;), and the will to evolve your style - not just your skill.  This of course does not apply to you if you are a beginner or intermediate developer, but if you consider yourself at least a senior developer that's another story.&lt;/p&gt;&lt;p&gt;To be clear, even as little as two spaces are excessive, and should not be used in advanced code.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;One Space Indentation&lt;/h4&gt;&lt;p&gt;Pat yourself on the back if you're still with me for you have my respects.  Here we will explore how to code like a pro.&lt;/p&gt;&lt;p&gt;Let's begin with a piece of code where we see how one space indentation looks like.  Keep in mind that this requires training your eye, and some practice.  Since when can you get good at something &lt;i&gt;without&lt;/i&gt; practice anyway?  Here is something that applies to just about everything in life:  If you don't practice, you can't be that good.  If I've lost you, you can still train your eye &lt;a href="http://en.wikipedia.org/wiki/Stereogram"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;if (milan == true)&lt;br /&gt;  {&lt;br /&gt;   while (coding)&lt;br /&gt;    {&lt;br /&gt;     i++;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt; else&lt;br /&gt;  {&lt;br /&gt;   goto school;&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;As we can see by combining proper alignment of braces (each on its own line) and one spaces, we effectively kill two birds with one stone:&lt;/p&gt;&lt;ol&gt;&lt;li&gt; Blocks are clearly identified by aligning opening and closing braces&lt;br /&gt;&lt;li&gt; Indirectly we achieve two space indentation between levels&lt;br /&gt;&lt;/ol&gt;&lt;p&gt;Okay so the &lt;i&gt;goto&lt;/i&gt; statement is bad programming, and is more geek humor in context of the code sample (e.g. if I disagree with Milan, then I may as well use other bad practices such as &lt;i&gt;goto&lt;/i&gt;).&lt;/p&gt;&lt;p&gt;Now let's take that same code sample with the other indent styles. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;if (milan == true) {&lt;br /&gt;     while (coding) {&lt;br /&gt;         i++;&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt; else {&lt;br /&gt;     goto school;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;There you have the four space and tabs.  Luckily this is a small piece of code with only two indentations - imagine a real-life example where we have multiple level depths.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;if (milan == true)&lt;br /&gt;   {&lt;br /&gt;     while (coding)&lt;br /&gt;       {&lt;br /&gt;          i++;&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt; else&lt;br /&gt;   {&lt;br /&gt;      goto school;&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;I used GNU style formatting for the above sample.  The code looks a little disconnected to me, and still a little more in line with &lt;i&gt;baby mode&lt;/i&gt;.  Either way, this is just to show why I do not like anything more than one space.&lt;/p&gt;&lt;h4&gt;Benefits&lt;/h4&gt;&lt;p&gt;The benefits of keeping to the &lt;i&gt;One Space Indent&lt;/i&gt; style as an enterprise level developer include:&lt;/p&gt;&lt;ol&gt;&lt;li&gt; Less horizontal white space&lt;br /&gt;&lt;li&gt; Clear indentation with proper curly bracket alignment&lt;br /&gt;&lt;li&gt; More code on screen without need of scrolling&lt;br /&gt;&lt;li&gt; Tighter visual relationship display&lt;br /&gt;&lt;li&gt; Stay focused on code and not scrolling back and forth&lt;br /&gt;&lt;li&gt; Displays on &lt;i&gt;all&lt;/i&gt; editors with no special configurations!&lt;/ol&gt;&lt;h4&gt;Real-life Examples&lt;/h4&gt;&lt;p&gt;While there are many cases where custom tabs may not be defined, I will collect some real-life examples that illustrate where spaces will work and tabs will fail. &lt;ol&gt;&lt;li&gt; &lt;b&gt;Web Inspector&lt;/b&gt;&lt;br /&gt;&lt;p&gt;This is the web development debugger used for Webkit browsers.  When using its built-in editor, any long lines will be auto-wrapped, not to mention tabs are displayed as tabs - with no customized view possible.  Combining these two effectively guaranteed really messy debugging.&lt;/p&gt;&lt;li&gt; &lt;b&gt;FireBug Script Debugger&lt;/b&gt;&lt;br /&gt;&lt;p&gt;This is the web development debugger used for FireBug browsers.  When using its built-in editor tabs are displayed as tabs - with no customized view possible.  &lt;/p&gt;&lt;li&gt; &lt;b&gt;WordPress&lt;/b&gt;&lt;br /&gt;&lt;p&gt;Okay, so this actually encompasses most web platforms.  Most of the time if you are a web developer you will not use a WYSIWYG editor - if such is offered by an online platform.&lt;/p&gt;&lt;/ol&gt;If you have any examples of where spaces work and tabs don't, feel free to comment.  Likewise, if you are a tab believer, comment on when tabs will work and spaces won't display correctly. &lt;/p&gt;&lt;h4&gt;Readings&lt;/h4&gt;&lt;p&gt;I just had a friendly debate on this topic with a fellow web developer where he happens to be a &lt;i&gt;tabber&lt;/i&gt; (as opposed to me being a &lt;i&gt;spacer&lt;/i&gt;), so he had recommended this read before he had read it to its full completion.  Knowing this, read the full article for a good laugh.  &lt;a href="http://www.codinghorror.com/blog/2009/04/death-to-the-space-infidels.html"&gt;http://www.codinghorror.com/blog/2009/04/death-to-the-space-infidels.html&lt;/a&gt;.&lt;/p&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;p&gt;Every developer will get used to one style or another, and there is no &lt;i&gt;functional&lt;/i&gt; reason to use one over the other.  This is purely a personal choice that a developer who wants to evolve every aspect of him or herself and not only their technical side has to make.  After all, technical know-how is only one part to being a successfully well-rounded web developer.&lt;/p&gt;&lt;script type="text/javascript"&gt;var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));&lt;/script&gt; &lt;script type="text/javascript"&gt;try {var pageTracker = _gat._getTracker("UA-13263204-1");pageTracker._trackPageview();} catch(err) {}&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-884810969595384026?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/884810969595384026/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/02/one-space-indentation.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/884810969595384026'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/884810969595384026'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/02/one-space-indentation.html' title='One Space Indentation'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-149220406549060228</id><published>2010-02-26T22:50:00.000-08:00</published><updated>2010-09-25T11:01:23.189-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><title type='text'>jQuery Plugin Pattern 2.0</title><content type='html'>&lt;p&gt;After having developed the &lt;a href="http://milanadamovsky.blogspot.com/2010/02/how-to-write-advanced-jquery-plugins.html"&gt;original jQuery authoring pattern&lt;/a&gt; a few issues caught my attention that kept me unhappy with that pattern.  Luckily I had found workarounds for the few shortcomings I identified, but having to keep these in mind during development was a pain and did not provide for as a robust solution as I'd like it to be. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Time to review the pattern and start from scratch.  You will see that this is a more elegant solution with all kinks ironed out.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Criteria&lt;/h4&gt;&lt;p&gt;I still want to have a pattern that allows me to write plugins that meet these criteria:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;that maintain only one entry in jQuery's namespace&lt;br /&gt;&lt;li&gt;that allow secondary methods&lt;br /&gt;&lt;li&gt;access to selector&lt;br /&gt;&lt;li&gt;access to $(this) through secondary methods&lt;br /&gt;&lt;/ol&gt;The good thing is that because this pattern uses jQuery's conventions, you do not have to learn anything new - no new framework, no new names, no new trickery, just simple straight forward jQuery programming mixed with Object Oriented JavaScript programming.&lt;/p&gt;&lt;h4&gt;Research&lt;/h4&gt;&lt;p&gt;I do encourage everyone to read the official &lt;a href="http://docs.jquery.com/Plugins/Authoring"&gt;jQuery plug-in authoring tutorial&lt;/a&gt;.  This is pretty simple and straight forward, and in this article I will refer to it as the "normal method".&lt;/p&gt;&lt;p&gt;Another great read is Mike Alsup's &lt;a href="http://www.learningjquery.com/2007/10/a-plugin-development-pattern"&gt;plugin development pattern&lt;/a&gt;.  His tutorial is closer to what my &lt;i&gt;pattern&lt;/i&gt; tackles.&lt;/p&gt;&lt;h4&gt;Goal&lt;/h4&gt;&lt;p&gt;As with my &lt;a href="http://milanadamovsky.blogspot.com/2010/02/how-to-write-advanced-jquery-plugins.html"&gt;original pattern&lt;/a&gt;, in this new pattern I also want to be able to have global access to the selector along with the $(this) object regardless of how many levels deep I am in my methods (e.g. &lt;i&gt;$(selector).x.y.z()&lt;/i&gt;).  This is something that jQuery does not natively support, and is limited to making the selector and $(this) available only to the main plug-in (first level as in &lt;i&gt;$(selector).x()&lt;/i&gt;).&lt;/p&gt;&lt;h4&gt;Solution&lt;/h4&gt;&lt;p&gt;First I want to begin with giving a complete example of how a very basic plugin is developed using my proposed pattern so you know what you'll be dealing with.&lt;/p&gt;&lt;p&gt;Behold... the new plugin pattern!&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($)&lt;br /&gt;  {&lt;br /&gt;   $.fn.extend({ &lt;br /&gt;                _plugin: null, &lt;br /&gt;                jQueryInit: jQuery.fn.init &lt;br /&gt;               });&lt;br /&gt;    &lt;br /&gt;   $.fn.extend({&lt;br /&gt;                init: function( selector, context ) &lt;br /&gt;                       {&lt;br /&gt;                        return jQuery.fn._plugin = new jQuery.fn.jQueryInit(selector, context);&lt;br /&gt;                       }&lt;br /&gt;               });&lt;br /&gt;    &lt;br /&gt;   function MyPluginClass(args)&lt;br /&gt;    {&lt;br /&gt;     &lt;br /&gt;     var _config;&lt;br /&gt;     &lt;br /&gt;     this.version = '1.0';&lt;br /&gt;    &lt;br /&gt;     this.show = _(showMessage);&lt;br /&gt;     &lt;br /&gt;     initConfig(args);&lt;br /&gt;&lt;br /&gt;     function getConfig()&lt;br /&gt;      {&lt;br /&gt;       return _config;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     function setConfig(args)&lt;br /&gt;      {&lt;br /&gt;       _config = args;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     function initConfig(args)&lt;br /&gt;      { &lt;br /&gt;       setConfig($.extend({&lt;br /&gt;                           chainable : true,&lt;br /&gt;                           className : 'MyPluginClass'&lt;br /&gt;                          }, args));&lt;br /&gt;       return (this);&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;     function showMessage(args)&lt;br /&gt;      {  &lt;br /&gt;       var myDiv = $(this);&lt;br /&gt;           &lt;br /&gt;       var config = getConfig();&lt;br /&gt;&lt;br /&gt;       alert('My Plugin is ' + config.className);&lt;br /&gt;              &lt;br /&gt;       return (this);&lt;br /&gt;      }&lt;br /&gt;   &lt;br /&gt;&lt;br /&gt;     function _ (fn) &lt;br /&gt;      {&lt;br /&gt;       return function (args)&lt;br /&gt;               {&lt;br /&gt;                return this.prototype.rc(function () &lt;br /&gt;                                          { &lt;br /&gt;                                           fn.call(this, args) &lt;br /&gt;                                          }); &lt;br /&gt;               }&lt;br /&gt;      }&lt;br /&gt;      &lt;br /&gt;     this.rc = function (args)&lt;br /&gt;      {&lt;br /&gt;       if (typeof args == 'function')&lt;br /&gt;        {&lt;br /&gt;         return $.fn._plugin.each(args);&lt;br /&gt;        }&lt;br /&gt;       else&lt;br /&gt;        {&lt;br /&gt;         initConfig(args);&lt;br /&gt;         &lt;br /&gt;         return getConfig().chainable&lt;br /&gt;                 ? $.fn._plugin&lt;br /&gt;                 : $.fn.createBox;&lt;br /&gt;        }&lt;br /&gt;      };&lt;br /&gt;       &lt;br /&gt;     &lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     var _p = new MyPluginClass({});&lt;br /&gt;     &lt;br /&gt;     $.fn.pluginName = _p.rc;&lt;br /&gt;     $.extend($.fn.pluginName.prototype,_p);&lt;br /&gt;     $.extend($.fn.pluginName,_p);&lt;br /&gt;     &lt;br /&gt;    })(jQuery);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;At first it may seem a little counter-intuitive, but much of this code you will simply copy and paste without having to understand.  All you need to understand is where your code goes and a few simple rules to follow and you will write really cool plugins.&lt;/p&gt;&lt;h4&gt;Usage&lt;/h4&gt;&lt;p&gt;Before we break down the pattern I want to show why we go through this process and how cool your plugins will become.&lt;/p&gt;&lt;p&gt;This pattern is fully backwards compatible to jQuery's suggested use.  This means you can still use the traditional form of calling your plugin (if you want) as shown below.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$(&lt;i&gt;selector&lt;/i&gt;).pluginName(&lt;i&gt;args&lt;/i&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;So we got backwards compatibility covered.  But where is the magic?&lt;/p&gt;&lt;p&gt;The official jQuery pattern promotes the use of plugins are stand-alone widgets more or less that can be customized by way of tweaking various publicly exposed options.  This is where my pattern diverges.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$(&lt;i&gt;selector&lt;/i&gt;).pluginName(&lt;i&gt;args&lt;/i&gt;);&lt;br /&gt;$(&lt;i&gt;selector&lt;/i&gt;).pluginName(&lt;i&gt;args&lt;/i&gt;).&lt;i&gt;method()&lt;/i&gt;;&lt;br /&gt;$(&lt;i&gt;selector&lt;/i&gt;).&lt;i&gt;pluginName&lt;/i&gt;.&lt;i&gt;method()&lt;/i&gt;&lt;br /&gt;$(&lt;i&gt;selector&lt;/i&gt;).&lt;i&gt;pluginName&lt;/i&gt;.&lt;i&gt;object&lt;/i&gt;.&lt;i&gt;method()&lt;/i&gt;&lt;br /&gt;$(&lt;i&gt;selector&lt;/i&gt;).&lt;i&gt;pluginName&lt;/i&gt;.&lt;i&gt;object&lt;/i&gt;.&lt;i&gt;method(args)&lt;/i&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;All of the above are valid syntax when coded using this pattern, and yes, it's still chainable as long as you adhere to jQuery's plugin conventions to make it chainable.  Sweet!&lt;/p&gt;&lt;i&gt;Okay gotta run off to little Italy, will continue this later...&lt;/i&gt;&lt;!--&lt;p&gt; Let's begin with seeing what the actual pattern would look like.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;/pre&gt;&lt;p&gt;The above illustrates a simple pattern needed to achieve namespaced methods (e.g. &lt;i&gt;$(selector).pluginNamespace.pluginMethod()&lt;/i&gt;)&lt;/p&gt;&lt;p&gt;Compared to the &lt;a href="http://milanadamovsky.blogspot.com/2010/02/how-to-write-advanced-jquery-plugins.html"&gt;original pattern&lt;/a&gt; we can clearly see that this code is more sophisticated, more compact, and it actually works better.&lt;/p&gt;&lt;h4&gt;Comparison&lt;/h4&gt;&lt;p&gt;In the &lt;a href="http://milanadamovsky.blogspot.com/2010/02/how-to-write-advanced-jquery-plugins.html"&gt;other pattern&lt;/a&gt; one of the major drawbacks was that when within a method, it was impossible to reliably query the present selector since the information was stored as a global (&lt;i&gt;yes, yes, shame on me&lt;/i&gt;).  This was fixed in this pattern by using closures that will keep the information &lt;i&gt;tied&lt;/i&gt; (or encapsulated) with the respective call.  This makes this new pattern more reliable. &lt;/p&gt;&lt;p&gt;The other major drawback required the inclusion of some engine code to overwrite jQuery's native &lt;i&gt;init()&lt;/i&gt; function to get to the selector.  I do not like to override default framework behavior, but back in jQuery 1.2.5 when &lt;a href="http://milanadamovsky.blogspot.com/2010/02/how-to-write-advanced-jquery-plugins.html"&gt;that pattern&lt;/a&gt; was developed this was the only way.  While the &lt;i&gt;selector&lt;/i&gt; property has been part of jQuery since 1.3 it would not trickle down to secondary methods as needed - thus the need for the &lt;i&gt;init()&lt;/i&gt; rewrite.  In the new pattern this is no longer necessary!&lt;/p&gt;&lt;h4&gt;Explanation&lt;/h4&gt;&lt;p&gt;Let's quickly break the new pattern apart to understand what is happening.  The first thing we need to do is define our plugin as we normally would under any pattern.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($) {&lt;br /&gt;&lt;br /&gt;  $.fn.pluginName = function(args)&lt;br /&gt;   {&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;   };&lt;br /&gt;&lt;br /&gt;});&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;There is nothing new here.  Simply replace &lt;i&gt;pluginName&lt;/i&gt; with whatever the name of your plugin will be.  At this point &lt;i&gt;this&lt;/i&gt; or &lt;i&gt;$(this)&lt;/i&gt; references  selected element object, as it should.  This is the jQuery behavior we want to make available to our secondary methods. &lt;/p&gt;&lt;p&gt;The next thing we can do is define our properties, and first level methods.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($) {&lt;br /&gt;&lt;br /&gt;  $.fn.pluginName = function(args)&lt;br /&gt;   {&lt;br /&gt;    &lt;b&gt;&lt;br /&gt;    this.someProperty = "SomeValue";&lt;br /&gt;    this.someOtherProperty = "SomeOtherValue";&lt;br /&gt;    &lt;br /&gt;    this.someMethod = function ()&lt;br /&gt;     { &lt;br /&gt;      return (this); &lt;br /&gt;     };&lt;br /&gt;    &lt;/b&gt;&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;   };&lt;br /&gt; });&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;At this point it looks just like any other native JavaScript class.  Watch what happens next, this is where the magic happens.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($) {&lt;br /&gt;&lt;br /&gt;  $.fn.pluginName = function(args)&lt;br /&gt;   {&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;&lt;br /&gt;    $.fn.pluginName = function () // leave arguments empty as it gets it from closure &lt;br /&gt;     {&lt;br /&gt;      return(this);&lt;br /&gt;     }.apply(this);&lt;br /&gt;    &lt;/b&gt;&lt;br /&gt;   };&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;We overwrite our newly defined plug-in to be a "clean" anonymous function in the form of a closure.  This will allow subsequent calls to the plug-in to be faster since some content will be automatically cached, and it allows to achieve better encapsulation. &lt;/p&gt;&lt;p&gt;That's all you need to know to accomplish a plugin whose syntax will be:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$(selector).pluginName.method();&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Advancing&lt;/h4&gt;&lt;p&gt;What if we want to have a more elaborate interface and have a syntax that allows several levels of methods?&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$(selector).pluginName.method.subMethod();&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;That is possible and can be achieved several ways.  I will cover what I believe to be the simplest because I'm like KISS.  The complete pattern would look something like this: &lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($) {&lt;br /&gt;&lt;br /&gt;  $.fn.pluginName = function(args)&lt;br /&gt;   {&lt;br /&gt;    &lt;b&gt;var self = this;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    this.someProperty = "SomeValue";&lt;br /&gt;    this.someOtherProperty = "SomeOtherValue";&lt;br /&gt;    &lt;br /&gt;    this.someMethod = function ()&lt;br /&gt;     { &lt;br /&gt;      return (this); &lt;br /&gt;     };&lt;br /&gt;    &lt;b&gt;&lt;br /&gt;    this.someClass = {&lt;br /&gt;                      subMethod : function()&lt;br /&gt;                                   {&lt;br /&gt;                                    this.subMethod = function ()&lt;br /&gt;                                                      {&lt;br /&gt;                                                       return (this);&lt;br /&gt;                                                      };&lt;br /&gt;                                 &lt;br /&gt;                                    this.subMethod.apply(self);&lt;br /&gt;                                   }&lt;br /&gt;                    }; &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    $.fn.pluginName = function () // leave arguments empty as it gets it from closure &lt;br /&gt;     {&lt;br /&gt;      return(this);&lt;br /&gt;     }.apply(this);&lt;br /&gt;   };&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;The above illustrates the very minimal code needed to accomplish multiple levels depth, keeping a namespace, while still maintaining the integrity of the plugin. &lt;/p&gt;&lt;p&gt;Let's break it apart. &lt;/p&gt;&lt;h4&gt;Step 1: Save &lt;i&gt;this&lt;/i&gt;&lt;/h4&gt;&lt;p&gt;The first thing we want to do is store jQuery's &lt;i&gt;this&lt;/i&gt; into &lt;i&gt;self&lt;/i&gt; so we can re-use it later.  Do not worry about why at this point, but what is allows is a class' &lt;i&gt;this&lt;/i&gt; to remain untouched as we begin adding more levels, and to maintain a hierarchy of methods so that no child method gets inappropriately tied to jQuery's namespace as its own plugin.  What a mouthful. &lt;/p&gt;&lt;p&gt;Once we are ready to make available jQuery's &lt;i&gt;this&lt;/i&gt; and selector to a sublevel method, we simply &lt;i&gt;apply()&lt;/i&gt; self to the subMethod().  We'll explore this further below.&lt;/p&gt;&lt;h4&gt;Step 2: Create secondary namespace level&lt;/h4&gt;&lt;p&gt;Whenever a new level is introduced there is a parent node that groups all sub-methods.  If we have a &lt;i&gt;customer&lt;/i&gt; plugin, and we want to split the functionality into working with a customer's data and personal information we would break it apart to something similar as illustrated below.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$(selector).customer.&lt;b&gt;info&lt;/b&gt;.getFirstName()&lt;br /&gt;  $(selector).customer.&lt;b&gt;account&lt;/b&gt;.getBalance()&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;In the above example the &lt;i&gt;info&lt;/i&gt; and &lt;i&gt;account&lt;/i&gt; would be considered sublevel namespaces.  This is just a suggestion, and this pattern does not force such an architecture - it's just something I would do.&lt;/p&gt;&lt;p&gt;So since these namespaces do not need any functionality of their own it is safe to simply set them up as hashes.&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;b&gt;this.someClass = {&lt;/b&gt;&lt;br /&gt;                      subMethod : function()&lt;br /&gt;                                   {&lt;br /&gt;                                    this.subMethod = function ()&lt;br /&gt;                                                      {&lt;br /&gt;                                                       return (this);&lt;br /&gt;                                                      };&lt;br /&gt;                                 &lt;br /&gt;                                    this.subMethod.apply(self);&lt;br /&gt;                                   }&lt;br /&gt;                    &lt;b&gt;}; &lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Now any sub-methods are encapsulated in their own simulated namespace, and a clear hierarchy is enforced.&lt;/p&gt;&lt;h4&gt;Step 3: Create sub-methods&lt;/h4&gt;Next we simply add all our methods as items in the hash.  Simple enough.  This is where we become a little fancier in our pattern.  Read carefully.  &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;this.someClass = {&lt;br /&gt;                      &lt;b&gt;subMethod&lt;/b&gt; : function()&lt;br /&gt;                                   {&lt;br /&gt;                                    this.&lt;b&gt;subMethod&lt;/b&gt; = function ()&lt;br /&gt;                                                      {&lt;br /&gt;                                                       &lt;i&gt;[method code goes here]&lt;/i&gt;&lt;br /&gt;                                                       return (this);&lt;br /&gt;                                                      };&lt;br /&gt;                                 &lt;br /&gt;                                    this.subMethod.apply(self);&lt;br /&gt;                                   }&lt;br /&gt;                    }; &lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Notice how defining a sub-method consists of a wrapper method that then overwrites itself with the actual content of the method.  I will try to explain why this is so, but if it doesn't make sense (especially if it doesn't make sense) simply follow this pattern and know this is how you need to construct your sub-methods. &lt;/p&gt;&lt;p&gt;What follows is an attempt at explaining the logic behind that code.  Again, if your eyes glaze over, do not stress over it, simply copy and paste. &lt;/p&gt;&lt;p&gt;First we define an interface that says, we want &lt;i&gt;subMethod&lt;/i&gt; to be a sub-method of &lt;i&gt;someClass&lt;/i&gt;.  Very good.  The problem however is that inside the &lt;i&gt;subMethod&lt;/i&gt; the keyword &lt;i&gt;this&lt;/i&gt; refers to that function and &lt;i&gt;not&lt;/i&gt; jQuery's magical &lt;i&gt;this&lt;/i&gt; (so $(this) would not refer to the selected element).  So what we need to do is override &lt;i&gt;subMethod&lt;/i&gt; with the actual content of the method so we can &lt;i&gt;apply()&lt;/i&gt; the jQuery &lt;i&gt;this&lt;/i&gt; onto the content while still preserving the intuitive syntax of $(selector).plugin.namespace.method&lt;b&gt;()&lt;/b&gt;. &lt;/p&gt;&lt;p&gt;Notice the last parenthesis of the syntax.  Had we not created the wrapped method, the apply would automatically run once &lt;i&gt;subMethod&lt;/i&gt; was called, leaving the parenthesis to expect a function reference to operate on that would never come.  A syntax error would crash the code.  So if you are comfortable with leaving parenthesis off when calling your sub-methods, you can &lt;i&gt;apply()&lt;/i&gt; directly on the wrapper method - but this would render your code unconventional (since it is normally &lt;i&gt;properties&lt;/i&gt; and not methods that are called without parenthesis).  My advice is to keep the above construct. &lt;/p&gt;&lt;p&gt;We use &lt;i&gt;apply()&lt;/i&gt; as the last call.  This simply takes the sub-method that we just re-defined with the actual code, takes the &lt;i&gt;self&lt;/i&gt; we had used up top to store jQuery's original &lt;i&gt;this&lt;/i&gt; and we tell the plugin that within the &lt;i&gt;subMethod&lt;/i&gt; we want &lt;i&gt;this&lt;/i&gt; to reflect the selected element.  As a side-effect we can now access &lt;i&gt;this.selector&lt;/i&gt; and &lt;i&gt;$(this)&lt;/i&gt; from within a sub-method regardless of depth when we follow this pattern.&lt;/p&gt;&lt;p&gt;The &lt;i&gt;return (this)&lt;/i&gt; within the code definition is what will make your method chain-able to keep it in line with jQuery's plugin requirements.  Here you can apply whatever return necessary to make it conform (e.g. this.each). &lt;p&gt;Notice that all of this happens with closures.  A good understanding of closures will help one understand the mechanism behind the pattern.  If closures are not well understood, you will be glad to know that the magic takes care of handling the wrapper only the first time.  Any subsequent calls to that same method will no longer have to &lt;i&gt;apply()&lt;/i&gt; or handle the wrapping code, since the method has already gone through it once.  Consider the wrapping method almost like an initializer for the method.  This is cool because it gives you some extra power of being able to set default values, or do other init work - which is beyond the scope of this tutorial.&lt;/p&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;This is a simple and flexible pattern that addresses all the issues the original pattern overlooked, with the added bonus of not having to learn much - all that is needed is just conform to a simple pattern that has a very minimalistic footprint.&lt;br /&gt;--&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-149220406549060228?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/149220406549060228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/02/new-jquery-plugin-pattern.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/149220406549060228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/149220406549060228'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/02/new-jquery-plugin-pattern.html' title='jQuery Plugin Pattern 2.0'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-3078188141877059652</id><published>2010-02-09T10:34:00.000-08:00</published><updated>2010-04-25T08:45:37.128-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Remove if() statements in JavaScript</title><content type='html'>Most of the time &lt;i&gt;if()&lt;/i&gt; statements make our lives easier.  It clearly depicts our intended logic flow.&lt;br /&gt;&lt;br /&gt;Here I want to show a piece of code re-factored so that we eliminate the &lt;i&gt;if()&lt;/i&gt; statement.  After a few benchmarks however, it apparently ends up being more costly to &lt;i&gt;not&lt;/i&gt; use if() statements!  So keep that in mind...&lt;br /&gt;&lt;br /&gt;Let's illustrate this by way of example.  This will give you the idea that you can then take a run with when writing your own code.&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Original Code&lt;/h4&gt;Here I am spelling out the code as would be written by a junior developer, or someone extremely explicit.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function someFunction(args)&lt;br /&gt;  {&lt;br /&gt;   var myCallback;&lt;br /&gt;&lt;br /&gt;   if (args)&lt;br /&gt;    {&lt;br /&gt;     if (typeof args.callback != 'undefined')&lt;br /&gt;      {&lt;br /&gt;       myCallback = args.callback;&lt;br /&gt;      }&lt;br /&gt;     else&lt;br /&gt;      {&lt;br /&gt;       myCallback = function() {};&lt;br /&gt;      }&lt;br /&gt;     myCallback();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;First Re-factor&lt;/h4&gt;Next we will re-factor the code to an intermediate developer's level.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function someFunction(args)&lt;br /&gt;  {&lt;br /&gt;   var myCallback;&lt;br /&gt;&lt;br /&gt;   if (args)&lt;br /&gt;    {&lt;br /&gt;     myCallback = (typeof args.callback != 'undefined')&lt;br /&gt;                   ? args.callback&lt;br /&gt;                   : function() {};&lt;br /&gt;     myCallback();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;Great, we removed one &lt;i&gt;if()&lt;/i&gt;.&lt;br /&gt;&lt;h4&gt;Second Re-factor&lt;/h4&gt;We still have an &lt;i&gt;if()&lt;/i&gt; statement so we will try to be a little more creative and re-factor it a little more.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function someFunction(args)&lt;br /&gt;  {&lt;br /&gt;   var myCallback;&lt;br /&gt;   myCallback = (args &amp;&amp; typeof args.callback != 'undefined')&lt;br /&gt;                 ? args.callback&lt;br /&gt;                 : function() {};&lt;br /&gt;   myCallback();&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;Now we no longer have an &lt;i&gt;if()&lt;/i&gt; statement but we do still have a ternary operator.  We &lt;i&gt;can&lt;/i&gt; get rid of that one too!&lt;br /&gt;&lt;h4&gt;Third Re-factor&lt;/h4&gt;Let's step up our game to a senior level.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function someFunction(args)&lt;br /&gt;  {&lt;br /&gt;   var myCallback = args &amp;&amp; args.callback || function() {};&lt;br /&gt;   myCallback();&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;Wow! No &lt;i&gt;if()&lt;/i&gt; or ternary operator.  Is there something more we can do? Yes.&lt;br /&gt;&lt;h4&gt;Fourth Re-factor&lt;/h4&gt;Now we're pushing ourselves and going for guru level.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function someFunction(args)&lt;br /&gt;  {&lt;br /&gt;   (args &amp;&amp; args.callback || function() {})();&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;Amazing! We were able to remove:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Two &lt;i&gt;if()&lt;/i&gt; statements&lt;br /&gt;&lt;li&gt;Variable declaration&lt;br /&gt;&lt;li&gt;Memory allocation&lt;br /&gt;&lt;/ul&gt;Okay so I wouldn't recommend the last re-factor in an enterprise environment where code should be maintainable and where different skill levels are collaborating.  I do however encourage this type of code in core functions that will usually only be maintained by senior developers, and where performance and small footprint is the objective. &lt;h4&gt;Explanation&lt;/h4&gt;A quick explanation of what is happening is that you check if &lt;i&gt;args&lt;/i&gt; exists, and if it does, then you want to get the value of one of its properties (e.g. &lt;i&gt;args.callback&lt;/i&gt;).  These can both be anything you want it to be, the above is just an example.  If the property &lt;i&gt;args.callback&lt;/i&gt; doesn't contain anything, we want to assign an empty anonymous function.  This way when we call it, the JavaScript doesn't crash on us.  Now that we have ensured we will have a function (well, we could be more specific by adding a &lt;i&gt;typeof&lt;/i&gt; checking for a function into the &lt;i&gt;&amp;&amp;&lt;/i&gt;, but let's not over-complicate things), we are ready to execute it.   To execute the function all we have to do is wrap it with parenthesis, append another pair of parenthesis, and that will do it.  If this spelled out version does not clarify what the code is doing, just look at the very first version of the code as they do the same thing.&lt;h4&gt;Try it!&lt;/h4&gt;Here is some code for you to try... &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;script&gt;&lt;br /&gt; function someFunction(args)&lt;br /&gt;  {&lt;br /&gt;   (args &amp;&amp; args.callback || function() { alert('Bye!') })();&lt;br /&gt;  }&lt;br /&gt; someFunction({ callback : function() { alert('Hi') } });&lt;br /&gt; someFunction();&lt;br /&gt;&amp;lt;/script&gt;&lt;br /&gt;&lt;/pre&gt;This code will hopefully get the average JavaScript developer to think outside the box, and expand their arsenal to different ways of thinking.  I'm not saying this is a solution for every situation, I'm not saying it's never a solution, I'm just saying that it is &lt;i&gt;a&lt;/i&gt; solution.&lt;br /&gt;&lt;br /&gt;Hope you enjoyed this little exercise.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-3078188141877059652?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/3078188141877059652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/02/remove-if-statements-in-javascript.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/3078188141877059652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/3078188141877059652'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/02/remove-if-statements-in-javascript.html' title='Remove if() statements in JavaScript'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-581016629943347359</id><published>2010-02-07T08:36:00.000-08:00</published><updated>2010-09-25T23:52:02.558-07:00</updated><title type='text'>Advanced jQuery Plugin Authoring Pattern</title><content type='html'>&lt;p&gt;When writing a jQuery plugin it can feel like a daunting task.  In this article I will give you a template that I've created for my plugins, that you can follow when creating yours.  This is my way of doing it; use it as a pattern or a tutorial.&lt;/p&gt;&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; I've perfected a new &lt;a href="http://milan.adamovsky.com/2010/09/jquery-plugin-pattern-20.html"&gt;jQuery Plugin Pattern 2.0&lt;/a&gt; that should be used instead of the one on this page.&lt;/p&gt;&lt;h4&gt;Research&lt;/h4&gt;I do encourage everyone to read the official &lt;a href="http://docs.jquery.com/Plugins/Authoring"&gt;jQuery plug-in authoring tutorial&lt;/a&gt;.  This is pretty simple and straight forward, and in this article I will refer to it as the "normal method".  &lt;br /&gt;&lt;br /&gt;Another great read is Mike Alsup's &lt;a href="http://www.learningjquery.com/2007/10/a-plugin-development-pattern"&gt;plugin development pattern&lt;/a&gt;.  His tutorial is closer to what my &lt;i&gt;pattern&lt;/i&gt; tackles. &lt;br /&gt;&lt;br /&gt;The next natural step is to look at other jQuery plugins to see how others have implemented their plugins.  &lt;br /&gt;&lt;br /&gt;Last but not least, continue reading this article.&lt;br /&gt;&lt;h4&gt;Goal&lt;/h4&gt;The biggest shortcoming of the jQuery plugin authoring method is that the plugins are not designed to have methods but rather have options to interact.  This is to allow chaining, so methods would essentially become other plugins.  &lt;br /&gt;&lt;br /&gt;This brings us to the next shortcoming: even if we use the "normal" method, it does not account for method conflicts of various plugins since there is no namespace.  This means that if two plugins have a method called &lt;i&gt;getInfo&lt;/i&gt;, one of them will be overwritten.  &lt;br /&gt;&lt;br /&gt;Finally, &lt;i&gt;one&lt;/i&gt; of the other big shortcomings is that jQuery does not let you know which selector was acted on (the &lt;i&gt;.selector&lt;/i&gt; introduced in jQuery 1.3 does not do the job in the same way as needed here). &lt;br /&gt;&lt;br /&gt;Okay, one more:  within a method it is not possible to get the selected element as you would normally with &lt;i&gt;this&lt;/i&gt; using the &lt;i&gt;normal method&lt;/i&gt;.  This one won't make sense until we understand &lt;i&gt;why&lt;/i&gt; we need it, and that will become obvious when we tie everything together.&lt;br /&gt;&lt;h4&gt;Rules&lt;/h4&gt;There are a few rules that I have come up with that make it very simple to keep my plugins consistent:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Keep all objects, variables, functions declared alphabetically&lt;br /&gt;&lt;li&gt; No globals (outside of plugin definition)&lt;br /&gt;&lt;li&gt; Minimize "globals" within the plugin definition&lt;br /&gt;&lt;li&gt; Define plugin methods as hash&lt;br /&gt;&lt;li&gt; Declare all local functions underneath &lt;i&gt;plugin hash&lt;/i&gt;&lt;br /&gt;&lt;li&gt; Provide a config() method to pass all options&lt;br /&gt;&lt;li&gt; Use camelCase&lt;br /&gt;&lt;/ol&gt;I highly advise these rules to be followed when using this method. &lt;h4&gt;Template&lt;/h4&gt;Here is a blank template for a plug-in.  Read it over a few times, and then we'll break it apart. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($) &lt;br /&gt;   {&lt;br /&gt;    var config = {}; &lt;br /&gt;&lt;br /&gt;    var global = {&lt;br /&gt;                  selected : '',&lt;br /&gt;                  selector : ''&lt;br /&gt;                 };&lt;br /&gt;&lt;br /&gt;    var init = $.prototype.init; &lt;br /&gt;  &lt;br /&gt;    $.prototype.init = function(selector, context) &lt;br /&gt;     {&lt;br /&gt;      var r = init.apply(this, arguments);&lt;br /&gt;   &lt;br /&gt;      if (selector &amp;&amp; selector.selector)&lt;br /&gt;        r.context = selector.context, r.selector = selector.selector;&lt;br /&gt;    &lt;br /&gt;      if ( typeof selector == 'string' )&lt;br /&gt;       {&lt;br /&gt;        r.context = context || document, r.selector = selector;&lt;br /&gt;        global.selector = r.selector;&lt;br /&gt;       }&lt;br /&gt;  &lt;br /&gt;      global.selected = r;   &lt;br /&gt;  &lt;br /&gt;      return r;&lt;br /&gt;     };&lt;br /&gt;&lt;br /&gt;    $.prototype.init.prototype = $.prototype;&lt;br /&gt;&lt;br /&gt;    $.fn.pluginName = {&lt;br /&gt;                       config : function(args) &lt;br /&gt;                        {&lt;br /&gt;                         setConfig($.extend({&lt;br /&gt;                                            'default' : 'value'&lt;br /&gt;                                            }, args));&lt;br /&gt;         &lt;br /&gt;                         return (getConfig());&lt;br /&gt;                        },&lt;br /&gt;                       methodA : function()&lt;br /&gt;                        {&lt;br /&gt;                         var config = getConfig();&lt;br /&gt;  &lt;br /&gt;                         return (global.selected);&lt;br /&gt;                        },&lt;br /&gt;                       methodB : function()&lt;br /&gt;                        {&lt;br /&gt;                         var config = getConfig();&lt;br /&gt;  &lt;br /&gt;                         return (global.selected);&lt;br /&gt;                        }&lt;br /&gt;                      };&lt;br /&gt;  &lt;br /&gt;    function setConfig(value)&lt;br /&gt;     {&lt;br /&gt;      config = value;&lt;br /&gt;     }&lt;br /&gt;  &lt;br /&gt;    function getConfig()&lt;br /&gt;     {&lt;br /&gt;      return config;&lt;br /&gt;     }&lt;br /&gt;   })(jQuery); &lt;br /&gt;&lt;/pre&gt;That was fun, wasn't it? &lt;h4&gt;Step 1: Encapsulate&lt;/h4&gt;The first thing we need to do is to "encapsulate" the whole plug-in definition.  This means wrapping it into a self-executing function block. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;b&gt;(function($) &lt;br /&gt;   {&lt;/b&gt;&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;   &lt;b&gt;})(jQuery);&lt;/b&gt; &lt;br /&gt;&lt;/pre&gt;Nothing new here. &lt;h4&gt;Step 2: Globals&lt;/h4&gt;In this context we declare globals &lt;i&gt;within&lt;/i&gt; the plug-in's encapsulation.  This means these variables will only be available to the plug-in and not to the real global namespace - so do not worry too much about global namespace cluttering, but do apply the same wisdom when deciding what to put into the localized global namespace, as you would in a true global namespace.  Remember that as far as the plug-in is concerned, the encapsulated namespace &lt;i&gt;is&lt;/i&gt; the global namespace.  So the question becomes: what &lt;i&gt;do&lt;/i&gt; we put in this namespace? &lt;ol&gt;&lt;li&gt;Options variable&lt;br /&gt;&lt;li&gt;Global jQuery selector information&lt;br /&gt;&lt;li&gt;Local methods&lt;br /&gt;&lt;/ol&gt;Not too bad. &lt;h4&gt;Step 3: Options&lt;/h4&gt;It will become a problem to have access to the options that are passed in to the plug-in, once we introduce a namespace.  Knowing this we need to accommodate this by way of globalizing the passed-in options. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($) &lt;br /&gt;   {&lt;br /&gt;    &lt;b&gt;var config = {}; &lt;/b&gt;&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;   })(jQuery); &lt;br /&gt;&lt;/pre&gt;While these are accessible directly since they are global in the plug-in namespace, I highly discourage this, and introduce a getter and setter function. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function setConfig(value)&lt;br /&gt;     {&lt;br /&gt;      config = value;&lt;br /&gt;     }&lt;br /&gt;  &lt;br /&gt;    function getConfig()&lt;br /&gt;     {&lt;br /&gt;      return config;&lt;br /&gt;     }&lt;br /&gt;&lt;/pre&gt;At this point they are just dummy functions, but the point is that one could easily add intelligence to this down the road.  Basic getter/setter 101 concept.  Stick with it, even if you don't think you'll need it. &lt;h4&gt;Step 4: Selector Information&lt;/h4&gt;The next global is the meaty part of how I write plug-ins.  Unfortunately, as of jQuery 1.4.1 we still have no way of getting the element that was selected, and we have no true way of knowing what selector was used.  Let's illustrate this with an example. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$('input').pluginName();&lt;br /&gt;&lt;/pre&gt;Using the above, the &lt;i&gt;input&lt;/i&gt; would be the selector; the &lt;i&gt;$('input')&lt;/i&gt; would return the object of the selected element.  This is how jQuery works, and it's wonderful.    Inside the &lt;i&gt;pluginName&lt;/i&gt; definition we can get to the selected element object by using &lt;i&gt;$(this)&lt;/i&gt;.  The problem is that it's restricted only to the first level functions.  This means, as long we use the above construct to call the plug-in we won't have a problem.  The problem with that construct however is that it doesn't isolate itself into a namespace.  The new construct should be: &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$('input').pluginName.someMethod();&lt;br /&gt;&lt;/pre&gt;If we now try to use &lt;i&gt;$(this)&lt;/i&gt; inside the &lt;i&gt;someMethod()&lt;/i&gt;, it will not give us the selected element object - let alone the selector.  This is what we will be overcoming, and to prepare for this we will need to maintain a global data structure that will hold on to this information. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;var global = {&lt;br /&gt;                  selected : '',&lt;br /&gt;                  selector : ''&lt;br /&gt;                 };&lt;br /&gt;&lt;/pre&gt;These will later be accessible by simply calling &lt;i&gt;global.selected&lt;/i&gt; to get the selected element object, or &lt;i&gt;global.selector&lt;/i&gt; to get the selector that was used to get to the selected element object.  If this doesn't make sense at this point, simply do it and it will all fall into place. &lt;h4&gt;Step 5: Overwrite jQuery's init&lt;/h4&gt;After having hacked away at jQuery's 1.2.x source code to figure out a way to get to the selector, I found an elegant piece of code by Brandon Aaron somewhere online that I borrowed and enhanced for my purposes. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;var init = $.prototype.init; &lt;br /&gt;  &lt;br /&gt;    $.prototype.init = function(selector, context) &lt;br /&gt;     {&lt;br /&gt;      var r = init.apply(this, arguments);&lt;br /&gt;   &lt;br /&gt;      if (selector &amp;&amp; selector.selector)&lt;br /&gt;        r.context = selector.context, r.selector = selector.selector;&lt;br /&gt;    &lt;br /&gt;      if ( typeof selector == 'string' )&lt;br /&gt;       {&lt;br /&gt;        r.context = context || document, r.selector = selector;&lt;br /&gt;        global.selector = r.selector;&lt;br /&gt;       }&lt;br /&gt;  &lt;br /&gt;      global.selected = r;   &lt;br /&gt;  &lt;br /&gt;      return r;&lt;br /&gt;     };&lt;br /&gt;&lt;br /&gt;    $.prototype.init.prototype = $.prototype;&lt;br /&gt;&lt;/pre&gt;The gist of the code is that it overwrites jQuery's init() function that is responsible for intercepting the selector used, and find the selected element object.  If the above doesn't make sense to you, just copy and paste and trust me.  The above will populate the &lt;i&gt;global&lt;/i&gt; data structure. &lt;h4&gt;Step 6: Namespace&lt;/h4&gt;This is another meaty part of my way to author plug-ins: simulating a &lt;i&gt;namespace&lt;/i&gt;. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&lt;b&gt;$.fn.pluginName&lt;/b&gt; = {&lt;br /&gt;                       config : function(args) &lt;br /&gt;                        {&lt;br /&gt;                         setConfig($.extend({&lt;br /&gt;                                            'default' : 'value'&lt;br /&gt;                                            }, args));&lt;br /&gt;         &lt;br /&gt;                         return (getConfig());&lt;br /&gt;                        },&lt;br /&gt;                       methodA : function()&lt;br /&gt;                        {&lt;br /&gt;                         var config = getConfig();&lt;br /&gt;  &lt;br /&gt;                         return (global.selected);&lt;br /&gt;                        },&lt;br /&gt;                       methodB : function()&lt;br /&gt;                        {&lt;br /&gt;                         var config = getConfig();&lt;br /&gt;  &lt;br /&gt;                         return (global.selected);&lt;br /&gt;                        }&lt;br /&gt;                      };&lt;br /&gt;&lt;/pre&gt;Unlike the "normal" method of writing plug-ins, here we declare our plug-in as a hash.  This is great since it will let us call our plug-ins with a cleaner syntax. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$('input').pluginName.methodA();&lt;br /&gt; $('input').pluginName.methodB();&lt;br /&gt;&lt;/pre&gt;We effectively tell everyone that our methods belong to &lt;i&gt;pluginName&lt;/i&gt; - even if such methods exist for another pluginName.  I would leave the &lt;i&gt;config&lt;/i&gt; method as-is, to be the method to use to send options to your plug-in.  This will provide a uniform convention for all jQuery plug-in authors using my way, and automatically know not to chain on it (since it's purposely designed not to chain). &lt;h4&gt;Step 7: Methods&lt;/h4&gt;The last step is to define the public methods.  This is easily done by simply adding another item to the plug-in hash. &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;$.fn.pluginName = {&lt;br /&gt;                       config : function(args) &lt;br /&gt;                        {&lt;br /&gt;                         setConfig($.extend({&lt;br /&gt;                                            'default' : 'value'&lt;br /&gt;                                            }, args));&lt;br /&gt;         &lt;br /&gt;                         return (getConfig());&lt;br /&gt;                        },&lt;br /&gt;                       &lt;b&gt;methodA : function()&lt;br /&gt;                        {&lt;br /&gt;                         var config = getConfig();&lt;br /&gt;  &lt;br /&gt;                         return (global.selected);&lt;br /&gt;                        }&lt;/b&gt;,&lt;br /&gt;                       &lt;b&gt;methodB : function()&lt;br /&gt;                        {&lt;br /&gt;                         var config = getConfig();&lt;br /&gt;  &lt;br /&gt;                         return (global.selected);&lt;br /&gt;                        }&lt;/b&gt;&lt;br /&gt;                      };&lt;br /&gt;&lt;/pre&gt;Here we add two methods: &lt;i&gt;methodA&lt;/i&gt; and &lt;i&gt;methodB&lt;/i&gt;.  You can add as many methods this way as you want.  You can even simply do references as I like to do to keep it clean.  &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($) &lt;br /&gt;   {&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    $.fn.pluginName = {&lt;br /&gt;                       config : function(args) &lt;br /&gt;                        {&lt;br /&gt;                         setConfig($.extend({&lt;br /&gt;                                            'default' : 'value'&lt;br /&gt;                                            }, args));&lt;br /&gt;         &lt;br /&gt;                         return (getConfig());&lt;br /&gt;                        },&lt;br /&gt;                       &lt;b&gt;methodA : someMethodReferenceA&lt;/b&gt;,&lt;br /&gt;                       &lt;b&gt;methodB : someMethodReferenceB&lt;/b&gt;&lt;br /&gt;                      };&lt;br /&gt;&lt;br /&gt;    function someMethodReferenceA()&lt;br /&gt;     {&lt;br /&gt;      &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    function someMethodReferenceB()&lt;br /&gt;     {&lt;br /&gt;      &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;   })(jQuery); &lt;br /&gt;&lt;/pre&gt;The two things to remember when writing your methods is to first retrieve all the configs available to you via &lt;i&gt;getConfig()&lt;/i&gt;, and to return the jQuery object for chainability as shown above.  We can now see where the &lt;i&gt;global.selected&lt;/i&gt; is needed now since returning &lt;i&gt;$(this)&lt;/i&gt; at this point would not return the jQuery object. &lt;h4&gt;Aliases&lt;/h4&gt;A little bonus to using the above method is that it is very easy to create aliased method names.  One would usually want that for developers who are more keen to using certain terminology over the one you may prefer.  An example would be where one may want to have a &lt;i&gt;removeItem&lt;/i&gt; method (most likely a UNIX or Mac person), whereas the rest of the world may want a &lt;i&gt;deleteItem&lt;/i&gt; method (most likely a Windows user).  &lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;(function($) &lt;br /&gt;   {&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    $.fn.pluginName = {&lt;br /&gt;                       config : function(args) &lt;br /&gt;                        {&lt;br /&gt;                         setConfig($.extend({&lt;br /&gt;                                            'default' : 'value'&lt;br /&gt;                                            }, args));&lt;br /&gt;         &lt;br /&gt;                         return (getConfig());&lt;br /&gt;                        },&lt;br /&gt;                       &lt;b&gt;removeItem : someMethodReferenceA&lt;/b&gt;&lt;br /&gt;                      };&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;[code]&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;$.fn.pluginName['deleteItem'] = $.fn.pluginName.removeItem;&lt;br /&gt;    $.fn.pluginName['eraseItem'] = $.fn.pluginName.removeItem;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;   })(jQuery); &lt;br /&gt;&lt;/pre&gt;Clean.&lt;br /&gt;&lt;br /&gt;That's all there is to it.  Once you get used to this way, you will never go back.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-581016629943347359?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/581016629943347359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/02/how-to-write-advanced-jquery-plugins.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/581016629943347359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/581016629943347359'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/02/how-to-write-advanced-jquery-plugins.html' title='Advanced jQuery Plugin Authoring Pattern'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-105828094304124312</id><published>2010-02-02T06:15:00.000-08:00</published><updated>2010-11-06T18:22:32.370-07:00</updated><title type='text'>GraphicsMagick on FreeBSD</title><content type='html'>Recently I've been wanting to install the latest GraphicsMagick 1.3.8 on a FreeBSD 8.0 server, with little success doing so manually - somewhat.&lt;br /&gt;&lt;br /&gt;Update: This solution still works with GraphicsMagick 1.3.12.&lt;br /&gt;&lt;br /&gt;I want GraphicsMagick to be enabled for the JPEG format but using the &lt;i&gt;--with-jpeg&lt;/i&gt; has no effect even though the JPEG libraries are installed.  The error that I get is this:&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;/usr/bin/gm convert: No decode delegate for this image format&lt;br /&gt;&lt;/pre&gt;This essentially means that the JPEG "decoder", or library, was not found. Urgh.  Well, I did see that it didn't compile properly during the &lt;i&gt;configure&lt;/i&gt; process, but I thought it might just be a wrongful statement.  No such luck.&lt;br /&gt;&lt;br /&gt;What are we left to do?  Ports.&lt;br /&gt;&lt;br /&gt;So the next thing we can do is install GraphicsMagick from FreeBSD's ports collection.  This is located in &lt;i&gt;/usr/ports/graphics/GraphicsMagick13&lt;/i&gt;.  There are other GraphicsMagick folders but we want this version.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;cd /usr/ports/graphics/GraphicsMagick13&lt;br /&gt; make install&lt;br /&gt;&lt;/pre&gt;&lt;h4&gt;Compilation issues&lt;/h4&gt;This ports is extremely picky about what libraries are on the server.  As you run &lt;i&gt;make&lt;/i&gt; you will undoubtedly run into compilation errors.  Some of the errors will state that you don't have &lt;i&gt;libtool&lt;/i&gt; installed, others will state you already have &lt;i&gt;autoconf&lt;/i&gt; installed and fail (this one didn't make sense to me). &lt;br /&gt;&lt;br /&gt;The solution is pretty simple and logical though:  Remedy all issues.  &lt;br /&gt;&lt;h4&gt;Missing libtool&lt;/h4&gt;&lt;p&gt;This means if it says libtool is not found, go to the ports (now I say ports because all ports are usually compiled with the ports sources in mind so you will have greater luck with it), and install it.  Then try again.&lt;/p&gt;&lt;p&gt;It may be necessary to take this step to succeed at building GraphicsMagick from ports.  If this is the case you need to simply do the following steps:&lt;/p&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;cd /usr/ports/devel/libtool22&lt;br /&gt; make install&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;If you do not have &lt;i&gt;libtool22&lt;/i&gt; in your ports simply look for the latest libtool version (the &lt;i&gt;22&lt;/i&gt; in the above example represents the version number).&lt;/p&gt;&lt;h4&gt;Autoconf exists&lt;/h4&gt;The other error I encountered was that &lt;i&gt;autoconf&lt;/i&gt; already exists on the system so it failed to continue.  Where is the logic in that?  So we fight lack of logic with lack of logic:  uninstall autoconf and let GraphicsMagick do its thing.&lt;br /&gt;&lt;br /&gt;We all know uninstalling binaries on UNIX is not easily accomplished if you haven't installed it through a system that lets you uninstall.  If you are like me and you have installed autoconf manually (via tarball), to uninstall it as far as GraphicsMagick is concerned all you need to do is remove the binary.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;rm /usr/local/sbin/autoconf&lt;br /&gt;&lt;/pre&gt;The path may differ from system to system depending on how you installed it.  Adjust the path accordingly.&lt;br /&gt;&lt;br /&gt;Once all compilation issues have been remedied, try to &lt;i&gt;make&lt;/i&gt; the ports of GraphicsMagick again until you succeed.&lt;br /&gt;&lt;h4&gt;Magic&lt;/h4&gt;This is where the true magic happens to get the latest GraphicsMagick to install.&lt;br /&gt;&lt;br /&gt;Now that FreeBSD took care of installing all the libraries, patches, and all the other files needed to get GraphicsMagick to compile, we can go back to GraphicsMagick's website, download the latest tarball, and install it.  It will work since all the prerequisite files are properly installed on the server thanks to the ports.&lt;br /&gt;&lt;br /&gt;Voila.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-105828094304124312?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/105828094304124312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/02/graphicsmagick-on-freebsd.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/105828094304124312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/105828094304124312'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/02/graphicsmagick-on-freebsd.html' title='GraphicsMagick on FreeBSD'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-717646390236073850</id><published>2010-01-30T12:44:00.000-08:00</published><updated>2010-04-25T08:46:01.972-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>Conditional DOCTYPE</title><content type='html'>I recently needed to switch the DOCTYPE of a page according to what browser was used.  If IE6 is used I want the page to render in quirks mode, conversely if the page is any other browser such as Firefox I want the page to render in HTML strict DOCTYPE.&lt;br /&gt;&lt;h4&gt;Problem&lt;/h4&gt;The problem is that there is no such thing as a conditional DOCTYPE.  You cannot fool it with JavaScript (and even if you could, you would not want to).&lt;br /&gt;&lt;h4&gt;Solution&lt;/h4&gt;The solution is quite simple, clean, and elegant.&lt;br /&gt;&lt;br /&gt;In IE6 anything that comes before the DOCTYPE declaration will automatically cause IE6 to jump into quirks mode.  This means even if you specify a HTML strict DOCTYPE on the page, as long as there is &lt;i&gt;something&lt;/i&gt; before it, it will be discarded.&lt;br /&gt;&lt;br /&gt;Are you with me so far?&lt;br /&gt;&lt;br /&gt;This is good news.  This means that all we need to do is start the page with a comment that will be ignored by &lt;i&gt;all&lt;/i&gt; browsers, with the extra benefit of disabling the DOCTYPE in IE6.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;!-- DOCTYPE disabler for IE6 --&gt;&lt;br /&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"&lt;br /&gt;   "http://www.w3.org/TR/html4/strict.dtd"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We have effectively created a conditional DOCTYPE, and it can be read as &lt;i&gt;"if we use IE6 put it in quirks mode, if any other browser is used such as Firefox then use the strict DOCTYPE."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Moving on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-717646390236073850?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/717646390236073850/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/01/conditional-doctype.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/717646390236073850'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/717646390236073850'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/01/conditional-doctype.html' title='Conditional DOCTYPE'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-2771868773475958077</id><published>2010-01-26T11:11:00.000-08:00</published><updated>2010-01-30T12:51:43.962-08:00</updated><title type='text'>Compile Locale::gettext on FreeBSD with Perl 5.10</title><content type='html'>On FreeBSD when you try to compile the Locale::gettext using Perl 5.10.1 you may get an error message that says:&lt;br /&gt;&lt;br /&gt;gettext function not found. Please install libintl at Makefile.PL line 18.&lt;br /&gt;&lt;br /&gt;So my solution is pretty simple:&lt;br /&gt;&lt;br /&gt;CC='cc -L/usr/local/lib -I/usr/local/include' perl Makefile.PL&lt;br /&gt;&lt;br /&gt;Tada!&lt;br /&gt;&lt;br /&gt;My logic is we piggy back off of the environment variable that is already built-in into the Makefile.pl and have it go for the compiler, but also inject the various paths (since apparently it's having trouble finding the libintl library on its own).&lt;br /&gt;&lt;br /&gt;With this method you will be able to compile successfully.&lt;br /&gt;&lt;h4&gt;Before&lt;/h4&gt;prompt&gt; perl Makefile.PL&lt;br /&gt;checking for gettext... no&lt;br /&gt;checking for gettext in -lintl... no&lt;br /&gt;gettext function not found. Please install libintl at Makefile.PL line 18.&lt;br /&gt;&lt;h4&gt;After&lt;/h4&gt;prompt&gt; CC='cc -L/usr/local/lib -I/usr/local/include' perl Makefile.PL&lt;br /&gt;checking for gettext... no&lt;br /&gt;checking for gettext in -lintl... yes&lt;br /&gt;checking for dgettext in -lintl... yes&lt;br /&gt;checking for ngettext in -lintl... yes&lt;br /&gt;checking for bind_textdomain_codeset in -lintl... yes&lt;br /&gt;Writing Makefile for Locale::gettext&lt;br /&gt;&lt;br /&gt;prompt&gt; make&lt;br /&gt;cp gettext.pm blib/lib/Locale/gettext.pm&lt;br /&gt;/usr/bin/perl /usr/local/lib/perl5/5.10.1/ExtUtils/xsubpp  -typemap /usr/local/lib/perl5/5.10.1/ExtUtils/typemap  gec&lt;br /&gt;Please specify prototyping behavior for gettext.xs (see perlxs manual)&lt;br /&gt;cc -c    -DHAS_FPSETMASK -DHAS_FLOATINGPOINT_H -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -O c&lt;br /&gt;Running Mkbootstrap for Locale::gettext ()&lt;br /&gt;chmod 644 gettext.bs&lt;br /&gt;rm -f blib/arch/auto/Locale/gettext/gettext.so&lt;br /&gt;LD_RUN_PATH="/usr/local/lib" cc  -shared  -L/usr/local/lib -fstack-protector gettext.o  -o blib/arch/auto/Locale/get&lt;br /&gt;chmod 755 blib/arch/auto/Locale/gettext/gettext.so&lt;br /&gt;cp gettext.bs blib/arch/auto/Locale/gettext/gettext.bs&lt;br /&gt;chmod 644 blib/arch/auto/Locale/gettext/gettext.bs&lt;br /&gt;Manifying blib/man3/Locale::gettext.3&lt;br /&gt;&lt;br /&gt;prompt&gt; make install&lt;br /&gt;Files found in blib/arch: installing files in blib/lib into architecture dependent library tree&lt;br /&gt;Installing /usr/local/lib/perl5/site_perl/5.10.1/i386-freebsd/auto/Locale/gettext/gettext.so&lt;br /&gt;Installing /usr/local/lib/perl5/site_perl/5.10.1/i386-freebsd/auto/Locale/gettext/gettext.bs&lt;br /&gt;Installing /usr/local/lib/perl5/site_perl/5.10.1/i386-freebsd/Locale/gettext.pm&lt;br /&gt;Installing /usr/local/man/man3/Locale::gettext.3&lt;br /&gt;Appending installation info to /usr/local/lib/perl5/5.10.1/i386-freebsd/perllocal.pod&lt;br /&gt;&lt;br /&gt;Hope this helps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-2771868773475958077?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/2771868773475958077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2010/01/on-freebsd-when-you-try-to-compile.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/2771868773475958077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/2771868773475958077'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2010/01/on-freebsd-when-you-try-to-compile.html' title='Compile Locale::gettext on FreeBSD with Perl 5.10'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-7793720160328035029</id><published>2009-10-29T06:16:00.000-07:00</published><updated>2010-02-03T09:25:16.254-08:00</updated><title type='text'>Dangers of document.write()</title><content type='html'>&lt;p&gt;Newcomers to JavaScript quickly learn that it is possible to write dynamic content onto the screen with document.write().  It gets the job done, it is easy to understand, and even easier to implement.  This article will cover of why document.write() should be used sparingly if at all.&lt;/p&gt;&lt;h4&gt;Pros&lt;/h4&gt;&lt;p&gt;Before we cover the serious disadvantages, let's be fair and address the benefits.&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Easy to understand&lt;br /&gt;&lt;li&gt; Quick to implement&lt;br /&gt;&lt;li&gt; Immediate rendering &lt;br /&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;The one time you may want to use this is when dynamically linking files into your page such as additional JavaScript libraries because of the immediate rendering.  There you have them.  If you are a serious developer, the next section will be more interesting.&lt;/p&gt;&lt;h4&gt;Cons&lt;/h4&gt;&lt;p&gt;I can count on one hand how many times I've used used document.write(), and I definitely have never used it to display content on the screen (&lt;i&gt;this is like using tables for layout&lt;/i&gt;).   The disadvantages are best seen when trying to extend existing code.  Nonetheless here they are: &lt;ul&gt;&lt;li&gt; Rigid implementation&lt;br /&gt;&lt;li&gt; Renders in-place&lt;br /&gt;&lt;li&gt; Cannot be manipulated&lt;br /&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;Alright so the list by itself doesn't help my case much; let's explore each point in greater detail.&lt;/p&gt;&lt;h4&gt;Rigid Implementation &lt;/h4&gt;&lt;p&gt;The document.write() is mostly used to write content to the screen as soon as that content is needed.  This means it happens anywhere:  in a JavaScript file or inside a script tag within an HTML file - with the script tag being placed anywhere within such an HTML file.  The latter is a definite no-no, but alas it happens.&lt;/p&gt;&lt;p&gt;It is a bad idea to have document.write() statements inside script blocks that are intertwined with HTML inside a web page for several reasons: &lt;ul&gt;&lt;li&gt; Changing code requires modifying an HTML file (which is not in line with MVC)&lt;br /&gt;&lt;li&gt; We cannot re-use what is written to the screen since it is not modular.  This means that if we want to do the same thing in some other file, we have to copy and paste the same code into that HTML file *shivers*&lt;br /&gt;&lt;li&gt; Since it renders in real-time it may render before other content is generated by another JavaScript that the logic responsible for the document.write() is in turn reliant on.  &lt;br /&gt;&lt;/ul&gt;&lt;/p&gt;&lt;p&gt;The above points are quite a mouthful, it is not surprising then that inexperienced developers do not know any better.&lt;/p&gt;&lt;h4&gt;Renders In-Place&lt;/h4&gt;&lt;p&gt;Well designed code in general will take any dynamically generated content, store it in memory, keep manipulating it as it passes through the code before it finally gets spit out to the screen.  I've seen many times that the document.write() does all of this in one swoop:  it concatenates logic.&lt;/p&gt;&lt;p&gt;So to reiterate the last point in the preceding section:  Rendering content in-place may render faster than other content that may be relied upon, but it may not be available to the other code that in turn requires the content to be rendered for processing.  A chicken and egg thing.&lt;/p&gt;&lt;p&gt;To solve this dilemma we need to get rid of the document.write() and implement it the right way.&lt;/p&gt;&lt;p&gt;We should have all content stored in memory.  This in turn allows us to shuffle the content around, parse it, tweak it, and manipulate it any way we want, back and forth, as many times as we need.  At this point nothing is on the screen, which gives us this flexibility.  Once we are happy, and all code has had an opportunity to work with it, only (and only) then do we spit it out - in MVC parlance: to our &lt;i&gt;view&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;To display the content we could resort to document.write() but unless one knows exactly what once is doing this should not be the preferred way.  Instead one should inject it into a DOM element by id or the like.  Frameworks usually provide an easy way to accomplish this.  In jQuery one would simply do a $('#id').html(content), and that's it.&lt;/p&gt;&lt;h4&gt;Impossible Manipulation&lt;/h4&gt;&lt;p&gt;As covered in the previous section one of the major drawbacks of document.write() is that once it's written it's done and over with.  We cannot go back to manipulate it without tapping into the DOM - adding to the mess.&lt;/p&gt;&lt;h4&gt;Conclusion&lt;/h4&gt;&lt;p&gt;This is one of those functions in the world of web development that are deceivingly simple but should only be used by experienced developers - if at all.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-7793720160328035029?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/7793720160328035029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2009/10/dangers-of-documentwrite.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/7793720160328035029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/7793720160328035029'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2009/10/dangers-of-documentwrite.html' title='Dangers of document.write()'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-5626933227639304497</id><published>2009-10-19T10:22:00.000-07:00</published><updated>2009-10-19T10:22:44.170-07:00</updated><title type='text'>Button line-height in FireFox</title><content type='html'>In a recent project I had to create a stylized button in a form.  This involved a sprite background with some superimposed text to achieve the desired look.&lt;br /&gt;&lt;br /&gt;The text on the button had to be center-aligned vertically.  This is usually accomplished by tweaking the &lt;i&gt;line-height&lt;/i&gt; CSS property.  Unfortunately, FireFox doesn't extend &lt;i&gt;line-height&lt;/i&gt; onto the &lt;i&gt;button&lt;/i&gt; element.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;button {&lt;br /&gt;   line-height : 20px&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;The above CSS declaration will not process as intended in FireFox (&lt;i&gt;as of this writing 3.5.3&lt;/i&gt;). &lt;br /&gt;&lt;br /&gt;Luckily there is a quick work-around that is cross-browser compatible.  It involves adding an element inside the &lt;i&gt;button&lt;/i&gt; whose location coordinates we can then manipulate.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;style&gt;&lt;br /&gt;    button {&lt;br /&gt;     line-height : 20px&lt;br /&gt;    }&lt;br /&gt;    button span {&lt;br /&gt;     position: relative;&lt;br /&gt;     top: -2px;&lt;br /&gt;    }&lt;br /&gt;  &amp;lt;/style&gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;button&gt;&lt;br /&gt;    &amp;lt;span&gt;&lt;br /&gt;      Button Text&lt;br /&gt;    &amp;lt;/span&gt;&lt;br /&gt;  &amp;lt;/button&gt;&lt;br /&gt;&lt;/pre&gt;Above we use a &lt;i&gt;span&lt;/i&gt; element, but anything can be used.&lt;br /&gt;&lt;h4&gt;Browser Compatibility&lt;/h4&gt;I've tested this to work with IE6+ and FireFox 3+.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-5626933227639304497?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/5626933227639304497/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2009/10/button-line-height-in-firefox.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/5626933227639304497'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/5626933227639304497'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2009/10/button-line-height-in-firefox.html' title='Button line-height in FireFox'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-4516039441345994594</id><published>2009-10-08T08:58:00.000-07:00</published><updated>2010-04-25T08:47:16.266-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><title type='text'>Cross-Browser Testing</title><content type='html'>&lt;p&gt;As a front-end developer the biggest challenge faced is ensuring cross-browser compatibility.  Presently the browsers that are expected to be supported are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Internet Explorer 6&lt;br /&gt;&lt;li&gt;Internet Explorer 7&lt;br /&gt;&lt;li&gt;Internet Explorer 8&lt;br /&gt;&lt;li&gt;FireFox 3&lt;br /&gt;&lt;li&gt;Safari&lt;br /&gt;&lt;/ul&gt;Other browsers with a smaller market share such as Chrome and Opera are nice-to-haves but are usually not required.  The options available to web developers are numerous to ensure cross-browser compatibility.  The most obvious is to actually install all browsers, or have several computers with the various browsers, but if you're like me and you want to use one computer to test all, here are some useful tools.  &lt;h4&gt;Useful Tools&lt;/h4&gt;&lt;ul&gt;&lt;li&gt; &lt;a href="http://www.spoon.net/browsers"&gt;Spoon&lt;/a&gt; is a nice browser plugin that allows a sandboxed version of various browsers.  There are some complications running this in a corporate environment where firewalls, proxies, and the like are interfering.  Worth a try.&lt;br /&gt;Supports: IE6, IE7, IE8, FF2, FF3, FF3.5, Safari 3, Safari 4, iPhone, Chrome, Opera 9, Opera 10.&lt;/li&gt;&lt;li&gt; &lt;a href="http://tredosoft.com/Multiple_IE"&gt;MultipleIEs&lt;/a&gt; is a nice installer that uses eVolt's standalone packages of older Internet Explorers.  I use this only for the IE6 option.  Works like a charm even in a corporate environment.&lt;br /&gt;Supports: IE 3, IE 4.01, IE 5.01, IE 5.5, IE 6&lt;/li&gt;&lt;li&gt; &lt;a href="http://tredosoft.com/IE7_standalone"&gt;IE7 Standalone&lt;/a&gt; is a standalone Internet Explorer 7 that is good to have.&lt;br /&gt;Supports: IE 7&lt;/li&gt;&lt;li&gt; &lt;a href="http://browsers.evolt.org/"&gt;eVolt&lt;/a&gt; has a nice repository of just about any browser you can think of.  Good resource.&lt;br /&gt;Supports: All&lt;/li&gt;&lt;li&gt; &lt;a href="http://browsershots.org/"&gt;BrowserShots&lt;/a&gt; is a website that will give you a screenshot of your specified webpage to show you how it will look on that webpage.  Good to get an idea, but not ideal for active cross-browser development.&lt;/li&gt;&lt;/ul&gt;There are many other solutions out there but I try to keep &lt;i&gt;this&lt;/i&gt; list limited to solutions that work, are unobtrusive, and easy to install and use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-4516039441345994594?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/4516039441345994594/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2009/10/cross-browser-testing.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/4516039441345994594'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/4516039441345994594'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2009/10/cross-browser-testing.html' title='Cross-Browser Testing'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-437637178892261027</id><published>2009-10-03T08:59:00.000-07:00</published><updated>2010-04-25T08:46:37.321-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>Javascript's with() function</title><content type='html'>There is a feature in JavaScript that is not widely documented yet very helpful: the &lt;i&gt;with()&lt;/i&gt; function.&lt;br /&gt;&lt;br /&gt;The function is effectively a shorthand that eliminates repetitive objects.  An example will best illustrate the benefit.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;with(window.open('', 'title',&lt;br /&gt; 'toolbar=0,scrollbars=0,location=0,statusbar=0,' +&lt;br /&gt; 'menubar=0,resizable=0,width=280,height=40').document)&lt;br /&gt;    { &lt;br /&gt;     open();&lt;br /&gt;     write(email);&lt;br /&gt;     close();&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;Without using with() this same code would look like this:&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;var winId = window.open('', 'title', &lt;br /&gt; 'toolbar=0,scrollbars=0,location=0,statusbar=0,' +&lt;br /&gt; 'menubar=0,resizable=0,width=280,height=40');&lt;br /&gt;   winId.document.open();&lt;br /&gt;   winId.document.write(email);&lt;br /&gt;   winId.document.close();&lt;br /&gt;&lt;/pre&gt;We can clearly see that by using &lt;i&gt; with() &lt;/i&gt; we can eliminate the repetitive "winId.document" and we don't have to do any explicit variable memory allocation.&lt;br /&gt;&lt;br /&gt;Using this lets us reduce the bloat of our JavaScript code by eliminating repetitive code, making it more maintainable.&lt;br /&gt;&lt;h4&gt;Usage&lt;/h4&gt;The key is that the &lt;i&gt; with() &lt;/i&gt; statement can operate on any &lt;i&gt;object&lt;/i&gt;.  In JavaScript everything is an object, so it makes it easy to implement just about with anything.  Let's take the next example where I use the &lt;i&gt; with() &lt;/i&gt; statement on a hash data structure.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;var data = {&lt;br /&gt;             hello : 'Guten Tag',&lt;br /&gt;             name : 'Milan',&lt;br /&gt;             cool : 'geil',&lt;br /&gt;             scores : {&lt;br /&gt;                       high : 2000,&lt;br /&gt;                       low : 1000&lt;br /&gt;                      },&lt;br /&gt;             run : function() { alert('Done') }&lt;br /&gt;            };&lt;br /&gt;&lt;br /&gt; with (data)&lt;br /&gt;  {&lt;br /&gt;   alert(hello + ' ' + name + ', this is really ' + &lt;br /&gt;         cool + ' and your scores are : \n' + &lt;br /&gt;         (function() { &lt;br /&gt;            with(scores) &lt;br /&gt;             { &lt;br /&gt;              return "  high score : " + high +&lt;br /&gt;                        "\n  low score : " + low &lt;br /&gt;             } &lt;br /&gt;          })());&lt;br /&gt;   run();&lt;br /&gt;  };&lt;br /&gt;&lt;/pre&gt;This shows that we can easily use this on code blocks where we refer anything that is repetitive, including data structures.  Furthermore, we can also have nested &lt;i&gt; with() &lt;/i&gt; functions as shown above.&lt;br /&gt;&lt;br /&gt;It should be noted that using &lt;i&gt; with() &lt;/i&gt; is discouraged however its use introduces ambiguous behavior if you do not know what you are doing and has a higher overhead due to this attempt of finding what to tie an object &lt;i&gt;with&lt;/i&gt;.  Handle with care, but be aware this is something you can use if you know what you're doing.&lt;br /&gt;&lt;h4&gt;Scope&lt;/h4&gt;The curly brackets do &lt;i&gt;not&lt;/i&gt; define scope.  Any variables declared within will assume the scope of where the &lt;i&gt; with() &lt;/i&gt; is called.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-437637178892261027?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/437637178892261027/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2009/10/javascripts-with-function.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/437637178892261027'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/437637178892261027'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2009/10/javascripts-with-function.html' title='Javascript&apos;s with() function'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-6592937414080411269</id><published>2009-09-30T13:11:00.000-07:00</published><updated>2010-06-05T11:13:20.674-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='development'/><category scheme='http://www.blogger.com/atom/ns#' term='ui'/><category scheme='http://www.blogger.com/atom/ns#' term='perl'/><title type='text'>Hash Arguments &amp; Return Pattern</title><content type='html'>&lt;p&gt;If best practices are followed when programming functions and methods, global variables are used sparingly if at all.  This then begs the question of what is the best way to pass data in and out from these functions and methods?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;In this article I will cover a pattern I've developed that is intuitive, flexible, and consistent.  The suggested pattern is used in my &lt;a href="http://plugins.jquery.com/project/FlyTabs"&gt;FlyTabs&lt;/a&gt; jQuery plugin that I released back in 2008 but have used a similar pattern in Perl long before then.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The &lt;i&gt;H&lt;/i&gt;ash &lt;i&gt;A&lt;/i&gt;rguments &amp; &lt;i&gt;R&lt;/i&gt;eturn &lt;i&gt;P&lt;/i&gt;attern is conveniently abbreviated to &lt;b&gt;HARP&lt;/b&gt;.&lt;br /&gt;&lt;/p&gt;&lt;h4&gt;Input Parameters&lt;/h4&gt;Passing arguments into a function or method can be done in many different ways.  This pattern relies on the flexible &lt;i&gt;hash&lt;/i&gt; data structure as the input data transport, or in other words a collection of keys and associated values.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;registerUser({&lt;br /&gt;                firstName : 'Milan',&lt;br /&gt;                lastName : 'Adamovsky'&lt;br /&gt;               });&lt;br /&gt;&lt;/pre&gt;The benefit of using a &lt;i&gt;hash&lt;/i&gt; is that we can change the number, order, or data type of parameters at any given time without having to mess with the function or method source codes.&lt;br /&gt;&lt;br /&gt;Most programmers prefer to explicitly list the individual parameters as shown below.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;registerUser(firstName, lastName);&lt;br /&gt;&lt;/pre&gt;The benefit to this traditional convention is that we ensure that only the expected input is passed.  Another benefit is that performance wise it will be better - though invisible to the human eye.  The drawback to this approach becomes visible when it comes time to augment the code.&lt;br /&gt;&lt;br /&gt;Explicitly listing every expected parameter means that when there is a change in the parameter list we need to search through the entire code and find every location where the function or method is called and ensure that we adjust it with the changes.  A &lt;i&gt;hash&lt;/i&gt; eliminates this since the &lt;i&gt;hash&lt;/i&gt; itself changes, but the function or method call remains the same regardless of a &lt;i&gt;hash&lt;/i&gt;'s contents.&lt;br /&gt;&lt;br /&gt;&lt;table style="width:100%; border: 1px solid silver"&gt;&lt;tr&gt;   &lt;td bgcolor="#EAEAEA" style="width: 50%; margin:0; spacing: 0"&gt;&lt;center&gt;&lt;b&gt;&lt;i&gt;hash&lt;/i&gt; approach&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;   &lt;td bgcolor="#EAEAEA" style="width: 50%; margin:0; spacing: 0"&gt;&lt;center&gt;&lt;b&gt;&lt;i&gt;list&lt;/i&gt; approach&lt;/b&gt;&lt;/center&gt;&lt;/td&gt;  &lt;/tr&gt;&lt;tr&gt;   &lt;td&gt;&lt;ul&gt;&lt;li&gt;No specific order&lt;/li&gt;&lt;li&gt;Flexible&lt;/li&gt;&lt;li&gt;Easy to maintain&lt;/li&gt;&lt;li&gt;Slightly slower&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;   &lt;td&gt;&lt;ul&gt;&lt;li&gt;Specific order&lt;/li&gt;&lt;li&gt;Rigid&lt;/li&gt;&lt;li&gt;Hard to maintain&lt;/li&gt;&lt;li&gt;Slightly faster&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;  &lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;Understanding the fundamental differences of the two approaches will let you decide which is best for your circumstances.  &lt;br /&gt;&lt;br /&gt;In an enterprise development environment one would usually want to opt for the &lt;i&gt;hash&lt;/i&gt; solution due to the larger development team, long term goals, and higher frequency of code upgrades.  Conversely, a &lt;i&gt;list&lt;/i&gt; approach should only be used in functions and methods where every ounce of performance is sought after, and where one knows the function's or method's interface will not change often if at all.  In other words, the latter should really only be used by a senior developer who understands all the implications of doing so.&lt;br /&gt;&lt;br /&gt;Up to this point I've been using functions and methods interchangeably.  It should be noted that in OOP one could use properties as data transports, but since a method can take parameters too we will continue using these interchangeably.  Keep this little caveat in mind though when using this pattern.&lt;br /&gt;&lt;br /&gt;A function or method would then be coded to accept only one parameter: a &lt;i&gt;hash&lt;/i&gt;.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function registerUser (args)&lt;br /&gt;   {&lt;br /&gt;    var firstName = args.firstName,&lt;br /&gt;        lastName = args.lastName;&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;We can see that the beauty of passing a hash as a sole argument is that we can now abstract the interface of the function or method and tap into the &lt;i&gt;hash&lt;/i&gt; for whatever data we need. &lt;br /&gt;&lt;h4&gt;Return Values&lt;/h4&gt;As with the input values I like to keep the output values just as simple: a &lt;i&gt;hash&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;That's right!  The interface to each function and method only returns one object and that is a &lt;i&gt;hash&lt;/i&gt; for the same good reasons the arguments use a &lt;i&gt;hash&lt;/i&gt;.  The one exception on the return &lt;i&gt;hash&lt;/i&gt; is that it follows a convention which I refer to as &lt;i&gt;tiered output&lt;/i&gt; and it is illustrated below.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function registerUser (args)&lt;br /&gt;   {&lt;br /&gt;    var code = 0,&lt;br /&gt;        message = '',&lt;br /&gt;        data = {}&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    return ({&lt;br /&gt;             code : code,&lt;br /&gt;             message : message,&lt;br /&gt;             data : data&lt;br /&gt;            });&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;It is a &lt;i&gt;tiered output&lt;/i&gt; in the sense that we have an interface with keys that will always be present.  Furthermore a &lt;i&gt;code&lt;/i&gt; will always be a numeric value (usually '0' for a failure, and '1' for a success).  A &lt;i&gt;message&lt;/i&gt; will always be a short string (usually only populated in the event of a failure code, indicating the actual error).  Finally, the &lt;i&gt;data&lt;/i&gt; is a hash that can contain anything that would traditionally be returned by the function or method.  &lt;br /&gt;&lt;br /&gt;A &lt;i&gt;code&lt;/i&gt; can return any numbers that can further be checked against.  The only two that should be reserved are the aforementioned ones.&lt;br /&gt;&lt;br /&gt;Transposing Apache's error code onto this approach would look something like this:&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;function pageNotFound (args)&lt;br /&gt;   {&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    return ({&lt;br /&gt;             code : 404,&lt;br /&gt;             message : 'Page Not Found',&lt;br /&gt;             data : {}&lt;br /&gt;            });&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;The above example is meant for clarity.&lt;br /&gt;&lt;br /&gt;Calling a function or method becomes pretty simple and predictable.  While the return &lt;i&gt;hash&lt;/i&gt; can be named anything, my personal habit is to name it &lt;i&gt;retVal&lt;/i&gt; (short for "return value").&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;var retVal = pageNotFound(...);&lt;br /&gt;&lt;br /&gt;  if (!(retVal.code))&lt;br /&gt;   {&lt;br /&gt;    alert(retVal.message)&lt;br /&gt;   }&lt;br /&gt;&lt;/pre&gt;Let's tie everything together into one complete example illustrating the full use of HARP working with the aforementioned examples.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;script&gt;&lt;br /&gt;  function registerUser (args)&lt;br /&gt;   {&lt;br /&gt;    var firstName = args.firstName;&lt;br /&gt;    var lastName = args.lastName;&lt;br /&gt;&lt;br /&gt;    var code = 0,&lt;br /&gt;        message = '',&lt;br /&gt;        data = {};&lt;br /&gt;&lt;br /&gt;    if (firstName == '')&lt;br /&gt;     {&lt;br /&gt;      message = 'First name is empty!';&lt;br /&gt;     }&lt;br /&gt;    else if (lastName == '')&lt;br /&gt;     {&lt;br /&gt;      message = 'Last name is empty!';&lt;br /&gt;     }&lt;br /&gt;    else&lt;br /&gt;     {&lt;br /&gt;      code = 1;&lt;br /&gt;      data.completeName = firstName + ' ' + lastName;&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    return ({&lt;br /&gt;             code : code,&lt;br /&gt;             message : message,&lt;br /&gt;             data : data&lt;br /&gt;            });&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;  var retVal = registerUser({&lt;br /&gt;                            firstName : 'Milan',&lt;br /&gt;                            lastName : 'Adamovsky'&lt;br /&gt;                           });&lt;br /&gt;&lt;br /&gt;  alert(retVal.code ? retVal.data.completeName &lt;br /&gt;                    : 'Error: ' + retVal.message);      &lt;br /&gt; &amp;lt;/script&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Copy and paste this and see how it works.  It's easy, amazing, and flexible!&lt;/p&gt;&lt;h3&gt;Exception Handling&lt;/h3&gt;&lt;p&gt;You may be wondering if this pattern is in competition with traditional exception handling and the answer is &lt;i&gt;no&lt;/i&gt;.&lt;/p&gt;&lt;p&gt;Exception handling's purpose is to handle exceptions.  This means that in the event of an exception, the handling of such is handled appropriately.  &lt;i&gt;HARP&lt;/i&gt; on the other hand focuses on the input and output of a function or method.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This means that a method can return a success or failure, but it doesn't necessarily have to be an exception.  In this case an exception handler would not be thrown.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-6592937414080411269?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/6592937414080411269/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2009/09/javascript-arguments-return-pattern.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/6592937414080411269'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/6592937414080411269'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2009/09/javascript-arguments-return-pattern.html' title='Hash Arguments &amp; Return Pattern'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-8750696161440465610</id><published>2009-09-23T19:03:00.000-07:00</published><updated>2009-09-23T19:07:17.869-07:00</updated><title type='text'>JavaScript Frameworks</title><content type='html'>&lt;p&gt;There are many JavaScript frameworks out there that each come with their own pros and cons.  There is &lt;a href="http://www.jquery.com"&gt;jQuery&lt;/a&gt;, &lt;a href="http://www.extjs.com"&gt;ExtJS&lt;/a&gt;, &lt;a href="http://developer.yahoo.com/yui/"&gt;YUI&lt;/a&gt;, &lt;a href="http://www.mootools.net"&gt;MooTools&lt;/a&gt;, &lt;a href="http://code.google.com/webtoolkit/"&gt;GWT&lt;/a&gt;, and &lt;a href="http://www.prototypejs.org"&gt;Prototype&lt;/a&gt; just to name a few.  With so many choices and each providing eye-popping features, it is not surprising that companies small and large simply tack on these frameworks to their existing library.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;This seemingly innocent practice slowly snowballs into a larger problem than it solves - and eventually slows development to a crawling pace rather than do what a framework's intent is: speed up development.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;How is this possible?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Whenever a framework is adopted by a company it usually does so on the recommendation of their developers who make it a personal choice rather than a sound decision for the business.  Understandably enough the developer will naturally choose a technology he or she is most comfortable with.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;This type of freedom should only exist once:  When no framework has yet been adopted.  Once a framework has been chosen, no more frameworks, period.  &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Here are some points that should be considered:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Performance&lt;/b&gt;&lt;br /&gt;Every framework comes at a performance hit since it has a lot of overhead code to run the framework.  As can be imagined loading all these frameworks unnecessarily increases the overhead and inversely decrease the performance of the website - eating away resources that could be used more effectively by other features of the website.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Compatibility&lt;/b&gt;&lt;br /&gt;Luckily today's frameworks have a level of decency and foresight in playing nice with other frameworks in the event of their presence.  Nonetheless this does not necessarily hold true for every framework out there.  This &lt;i&gt;could&lt;/i&gt; lead to namespace collisions of all types.&lt;br /&gt;&lt;br /&gt;The other problem becomes knowing what framework to code on what portion of the website.  A clever developer may advise to only load jQuery on one page, and YUI on another.  This means that depending on what page a feature is to be added to, the developer needs to adapt to the framework running on that page.  In turn, code becomes fragmented and cannot be easily re-used - losing most if not all modularity.  &lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Productivity&lt;/b&gt;&lt;br /&gt;Developers tend to specialize in one or two frameworks.  It is not impossible for a developer to learn a new framework, but doing so is like learning a new language: it takes time, trial and error, and experience to get it right.  This is wasted effort that could be used more efficiently.&lt;br /&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;Production Cost&lt;/b&gt;&lt;br /&gt;One of the most important yet least observed points of adopting a multitude of frameworks is the fact that the code base now becomes segmented into an equal amount of skills needed to maintain and improve that same code base.  This means either a developer must be familiar with all adopted frameworks, or the team has to grow to enough developers that will have the needed skills combined.  Evidently,  it will be costly either way one goes.&lt;br /&gt;&lt;/ol&gt;&lt;/p&gt;&lt;p&gt;It becomes obvious that the solution becomes to just have one and only one framework.  After all, learning &lt;i&gt;one&lt;/i&gt; framework takes a lot less effort than learning several.  &lt;/p&gt;&lt;p&gt;The above applies for &lt;i&gt;any&lt;/i&gt;  framework.  The moral of the story is to choose &lt;i&gt;any&lt;/i&gt; one, and only one, framework and stick with it.  It is worth spending time figuring out how to make things work under the selected framework, rather than adopting a whole new framework that will achieve the task, but also duplicate already existing features. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-8750696161440465610?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/8750696161440465610/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2009/09/javascript-frameworks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/8750696161440465610'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/8750696161440465610'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2009/09/javascript-frameworks.html' title='JavaScript Frameworks'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2908475840373457869.post-8380175170725809754</id><published>2009-09-23T13:40:00.000-07:00</published><updated>2010-04-24T20:14:54.135-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='css'/><title type='text'>CSS Localization</title><content type='html'>It is quite simple to achieve conditional content showing by way of pure CSS for localization purposes.&amp;nbsp; This may be ideal in some instances and not so much in others.&amp;nbsp; We will explore both, but first let's see how we can accomplish this.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;style&gt;&lt;br /&gt;   p {&lt;br /&gt;    display: none;&lt;br /&gt;   }&lt;br /&gt;   body:lang(en) p:lang(en) {&lt;br /&gt;    display : inline; &lt;br /&gt;   }&lt;br /&gt;   body:lang(cz) p:lang(cz) {&lt;br /&gt;    display : inline; &lt;br /&gt;   }&lt;br /&gt; &amp;lt;/style&gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;body lang="cz"&gt;&lt;br /&gt;   &amp;lt;div&gt;&lt;br /&gt;     &amp;lt;p lang="en"&gt;Hello&amp;lt;/p&gt;&lt;br /&gt;     &amp;lt;p lang="cz"&gt;Ahoj&amp;lt;/p&gt;&lt;br /&gt;     &amp;lt;p lang="ru"&gt;Privet&amp;lt;/p&gt;&lt;br /&gt;   &amp;lt;/div&gt;&lt;br /&gt; &amp;lt;/body&gt;&lt;br /&gt;&lt;/pre&gt;That's all there is to it!&lt;br /&gt;&lt;br /&gt;The concept is quite simple: Hide &lt;i&gt;all&lt;/i&gt; relevant elements, and selectively display only those of interest - with no scripting.&lt;br /&gt;&lt;br /&gt;Now that we understand the concept let's improve upon it a little.  The above example would hide &lt;i&gt;all&lt;/i&gt; paragraph elements unless it is attributed a particular language.  To overcome this little nuisance we simply create a &lt;i&gt;class&lt;/i&gt; for all language items that will be shown conditionally.&lt;br /&gt;&lt;br /&gt;It is pretty simple to do this and involves only a slight adjustment to the above code.&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;&amp;lt;style&gt;&lt;br /&gt;   p&lt;b&gt;.select&lt;/b&gt; {&lt;br /&gt;    display: none;&lt;br /&gt;   }&lt;br /&gt;   body:lang(en) p&lt;b&gt;.select&lt;/b&gt;:lang(en) {&lt;br /&gt;    display : inline; &lt;br /&gt;   }&lt;br /&gt;   body:lang(cz) p&lt;b&gt;.select&lt;/b&gt;:lang(cz) {&lt;br /&gt;    display : inline; &lt;br /&gt;   }&lt;br /&gt; &amp;lt;/style&gt;&lt;br /&gt;&lt;br /&gt; &amp;lt;body lang="cz"&gt;&lt;br /&gt;   &amp;lt;div&gt;&lt;br /&gt;     &amp;lt;p &lt;b&gt;class="select"&lt;/b&gt; lang="en"&gt;Hello&amp;lt;/p&gt;&lt;br /&gt;     &amp;lt;p &lt;b&gt;class="select"&lt;/b&gt; lang="cz"&gt;Ahoj&amp;lt;/p&gt;&lt;br /&gt;     &amp;lt;p &lt;b&gt;class="select"&lt;/b&gt; lang="ru"&gt;Privet&amp;lt;/p&gt;&lt;br /&gt;     &amp;lt;p&gt;World&amp;lt;/p&gt;&lt;br /&gt;   &amp;lt;/div&gt;&lt;br /&gt; &amp;lt;/body&gt;&lt;br /&gt;&lt;/pre&gt;The above will conditionally greet the user according to the language, but the word "World" will &lt;i&gt;always&lt;/i&gt; be visible regardless of language.&lt;br /&gt;&lt;br /&gt;Keep in mind that the &lt;i&gt;display&lt;/i&gt; needs to be set to &lt;i&gt;block&lt;/i&gt; or &lt;i&gt;inline&lt;/i&gt; however the given tag or element is intended to work.&lt;br /&gt;&lt;br /&gt;To &lt;i&gt;select&lt;/i&gt; what language's content the page should display, all that needs to be done is adjust the &lt;i&gt;lang&lt;/i&gt; attribute in the &amp;lt;body&gt; tag.&lt;br /&gt;&lt;br /&gt;The above example's output would be:&lt;br /&gt;&lt;pre style="background-color: #EAEAEA; padding: 5px"&gt;Ahoj &lt;br /&gt;  World&lt;br /&gt;&lt;/pre&gt;Needless to say the possibilities are endless.  This approach is not limited to just the conditional showing of content but it can effectively be used in applying the correct style accordingly.&lt;br /&gt;&lt;br /&gt;The disadvantage of this solution is that the server is pushing through all content for all languages.  If content localization (e.g. translations) is the sole purpose, consider using some sort of server-side localization solution and return only the content specific to that language.&lt;br /&gt;&lt;br /&gt;On the other hand this is great if one wants to give a user quick access to customizing the user experience.  &lt;br /&gt;&lt;br /&gt;Nothing would stop one from using a hybrid solution that would work with AJAX to conditionally inject the right content accordingly while having the CSS readily available to reformat the layout on-demand (e.g. changing from a left-to-right layout to a right-to-left).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2908475840373457869-8380175170725809754?l=milan.adamovsky.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://milan.adamovsky.com/feeds/8380175170725809754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://milan.adamovsky.com/2009/09/css-localization.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/8380175170725809754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2908475840373457869/posts/default/8380175170725809754'/><link rel='alternate' type='text/html' href='http://milan.adamovsky.com/2009/09/css-localization.html' title='CSS Localization'/><author><name>Milan Adamovsky</name><uri>http://www.blogger.com/profile/14821107775101468010</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='15' src='http://2.bp.blogspot.com/_7MiP2bsKJ-Y/S4nodP6azQI/AAAAAAAAABk/fU6ORAecxJw/S220/5.jpg'/></author><thr:total>0</thr:total></entry></feed>
