Thursday, December 15, 2011

Fastest Loop in JavaScript

UPDATE: Turns out that the benchmark yielded skewed results. The quest goes on for the holy grail of fastest loops.

See my benchmark here.

Friday, August 12, 2011

Leverage CSS when resizing HTML elements using JavaScript

The inspiration for this article comes from me seeing, to this day, major frameworks like ExtJS using JavaScript as a shortcut to re-size HTML elements on a page - a task that CSS is much better suited for.

You may now be asking yourself: What exactly is the problem?

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.

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 width or height 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.

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.

Web Page Load Sequence

This is an extremely high-level overview of the way a web page gets rendered on the screen:

  1. DOM
  2. CSS
  3. JavaScript

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 <head> 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.

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 CSS is applied faster than JavaScript - and this is key.

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.

JavaScript Re-Sizing

A simple example of re-sizing would be a two column layout where we want the left column to be re-sizable.

Needless to say when we re-size Column 1 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.

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.

Simply put, today, if we adjust A, 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 B, C, D, etc... on the page.

CSS Re-Sizing

Whenever I lead front-end development teams or conduct workshops there is a simple rule to developing websites that I promote: "Develop for fluidity or elasticity and then fix it (if necessary)."

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.

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 flexible layout.

I like disciplined development. This is the difference between coding and engineering a solution.

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 - as we should. CSS works so intimately with the browser, any changes to the styling of an element has a virtually immediate visual effect.

Normally however, elastic or fluid layout are usually reserved for the anticipation of a browser re-size (e.g. if we re-size the entire browser, we don't want the website to break.).

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 need to calculate the new width according to user's interaction.

Solution

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 need 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.

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 one value as opposed to however many values there are columns.

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 auto. This is where the magic happens.

Now because we leave the width or height value to auto we can now leverage the CSS engine to calculate the values for us - rather than have JavaScript do it.

This will give us something similar to this:

In the above example simply move the mouse on top of the drag bar (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.

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.

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.

Had we not done this we would have to set the explicit value to the one element, and then set another explicit value on all 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.

Step 1

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.

The markup is pretty straight forward.

The above example can be implemented with something simple as:

 <body id="index_container">
   <div id="menu_container">
     <div class="drag_content horizontally right">
     </div>
   </div>
   <div id="content_container">
   </div>
 </body>

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.

 <body id="index_container">
   <div id="menu_container">
     <div class="drag_content horizontally right">
     </div>
   </div>
   <div id="content_container">
     <div id="header_container">
       <div class="drag_content vertically down">
       </div>
     </div>
     <div id="main_content">
       <div id="sub_nav_container">
         <div class="drag_content vertically down">
         </div>
       </div>
       <div id="sub_main_content">
         <div id="body_content">
           <div id="navigation_content">
           </div>
           <p>
             Here goes some content
           </p>
         </div> 
       </div>       
     </div>
     <div id="footer_container">
       <div class="drag_content vertically up">
       </div>
     </div>
   </div>
   <div id="ad_container">
     <div class="drag_content horizontally left">
     </div>
   </div>
 </body>

Copy and paste this into an HTML file alongside the given CSS at the bottom of this article to see the output.

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.

You will notice a few elements that have the class drag_content. 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 control just like a button, drop-down, or scroll-bar would be.

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 direction 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 horizontally means the user can drag left to right, and a value of vertically will let the user know to drag top to bottom.

The last piece to the puzzle is to understand what the up, down, left, and right mean.

Each of these drag bars are actually inside the containers. This means that you have to decide in which 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.

Step 2

Naturally the next step becomes the actual definition of the various classes and ids. This means CSS is our next technology of concern.

Take a minute to go through the CSS below.

*
 {
  margin: 0;
  padding: 0;
 }

body
 {
  background-color: #bcbcbc;
  height: 100%;
  width: 100%;
 }

p 
 {
  background-color: #fff;
  border: 1px solid #000;
  left: 10px;
  padding: 12px;
  position: absolute;
  right: 10px;
  top: 50px;
  width: auto;
 }
 
.down
 {
  bottom: 0;
 }

.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;
 }

#ad_container
 {
  background-color: #a7a7a7;
  height: 100%;
  position: absolute;
  right: 0px; 
  width: 100px;
 }

#body_content
 {
  background-color: #fff;
  border: 1px solid #000;
  height: auto;
  position: absolute;
  left: 10px;
  right: 10px;
  top: 10px;
  bottom: 10px;
  width: auto;
 }

#content_container
 {
  background-color: #d6d6d6;
  height: 100%;
  left: 100px;
  position: absolute;
  right: 100px;
  width: auto;
 }

#footer_container
 {
  bottom: 0px;
  background-color: #bbb;
  height: 100px;
  position: absolute; 
  width: 100%;
 }

#header_container
 {
  top: 0px;
  background-color: #848484;
  height: 100px;
  position: absolute; 
  width: 100%;
 }

#main_content
 {
  background-color: #e0e0e0;
  width: 100%;
  top: 100px;
  position: absolute;
  bottom: 100px;
  height: auto;
 }

#menu_container
 {
  background-color: #a7a7a7;
  height: 100%;
  position: absolute; 
  width: 100px;
 }

#navigation_content
 {
  background-color: #fff;
  border: 1px solid #000;
  height: 20px;
  left: 10px;
  position: absolute;
  right: 10px;
  top: 10px;
  width: auto;
 }

#sub_main_content
 {
  background-color: #e0e0e0;
  width: 100%;
  top: 100px;
  position: absolute;
  bottom: 0px;
  height: auto;
 }

#sub_nav_container
 {
  top: 0px;
  background-color: #bbb;
  height: 100px;
  position: absolute; 
  width: 100%;
 }

The first thing that can be observed is the clean organization of the CSS. 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 this post.

We are not going to explore why we use all of the various CSS properties as that is out of scope for this post.

The main point to understand on the CSS is that with respect to sizing, it defines the default - 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 auto.

Let's break it down.

#content_container
 {
  background-color: #d6d6d6;
  height: 100%;
  left: 100px;
  position: absolute;
  right: 100px;
  width: auto;
 }

#menu_container
 {
  background-color: #a7a7a7;
  height: 100%;
  position: absolute; 
  width: 100px;
 }

The first thing to observe is the position. 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 position: absolute the containers that you are interested in be re-sizable.

The second thing to notice is that in our simple example above, our left container is the menu_container with a default width of 100px (which can be any value you desire) and our right container is the content_container that has a width set to auto.

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 auto.

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 Step 3.

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 subtract 80 pixels). In this case it would result at a final width of 180px - and we only did this one addition, no subtraction (or vice-versa). Neat.

The next step is to take that number (180px) and apply it to the other container (whose width is set to auto) but not to the width but rather to its left in this case (but it could be right, top, bottom depending on the direction of the drag bar). The reason we need to do this is to allow the width: auto 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.

You will notice that any container that has a width of auto has both a left and right value. This is necessary for width: auto to work as we would expect it to.

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.

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.

A great exercise is to try to add a new row or column that can be re-sized following the aforementioned principles.

Step 3

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.

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

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 $(this). The rest of the code is self-explanatory.

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.

Sunday, January 16, 2011

Internet Explorer 6's 1px Gap Bug Solution

If you are still coding for Internet Explorer 6 ("IE6") cross-browser compatibility, you may have encountered the 1px gap bug. In brief, this bug adds a gap on absolutely positioned elements when the parent container's width is an odd number.

Problem

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 this link 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.

In my case I wanted to create tabs that have a little 1x1 pixel div 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.

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.

As a reminder, this only happens in Internet Explorer 6 when the width of the container is an odd number (e.g. 155 pixels).

My initial code looked something similar to this:

<div id="tab_container">
   <ol>
     <li style="width: 155px">
       <div style="left: 0px; position: absolute; height: 1px; width: 1px">
         <!-- comment needed for 1x1px div in ie6 -->
       </div>
       <div style="right: 0px; position: absolute; height: 1px; width: 1px">
         <!-- comment needed for 1x1px div in ie6 -->
       </div>
       <a href="">
         Some random tab text
       </a>
    </ol>
 </div>

The idea was to have the two 1 pixel divs absolutely positioned in the upper corners without floating (though I did try with float: left and float: right just the same) - to no avail. The 1 pixel gap bug kicked in.

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 ol and li 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).

Solution

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.

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.

Having said that, what do we do in fluid layouts where widths can change dynamically? Simple. We stop and think.

Thought Process

To many programmers CSS is a step away from black magic. We tend to want to solve problems programmatically and when that fails we just keep throwing more and more patchwork to the mess until something sticks. Some will actually stop and think, and solve the logical 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 not 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.)

So let's break down the issue.

  1. We know the problem only happens in Internet Explorer 6.
  2. We know the problem only happens when the width of the container is an odd number.
  3. We know the problem only happens on elements within the container that have an absolute position.
  4. We know of the solution presented by Paul O'Brien where we statically position the element within a container of a fixed width.
  5. We know there is no known solution to the problem.

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.

Let's break down what we are going to try to achieve for a solution.

  1. The one technical cause to the effect we know that we cannot rely on is position: absolute. This CSS attribute is off the table.
  2. 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.
  3. Do not use JavaScript for a CSS problem!! JavaScript is off the table.

We have pretty much cornered ourselves into a seemingly impossible dilemma: solve a seemingly unsolvable problem. 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 stop and think.

What we have to do is see what other alternatives we have to absolute positioning, and that would be static and relative positioning. We know that the solution by Paul O'Brien relies on the static 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: relative positioning.

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:

  1. Fixed width content - content whose width will never change
  2. Dynamic width content - content whose width may change based on content

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.

The new code will then simply look something like this:

<div id="tab_container">
   <ol>
     <li>
       <div style="float: left; height: 1px; width: 1px">
         <!-- comment needed for 1x1px div in ie6 -->
       </div>
       <div style="float: left">
         <a href="">
           Some random tab text
         </a>
       </div>
       <div style="float: left; height: 1px; width: 1px">
         <!-- comment needed for 1x1px div in ie6 -->
       </div>
    </ol>
 </div>

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.

This is where the beauty of negative margins come in.

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.

<div id="tab_container">
   <ol>
     <li>
       <div style="float: left; height: 1px; width: 1px">
         <!-- comment needed for 1x1px div in ie6 -->
       </div>
       <div style="float: left: margin-left: -1px; margin-right: -1px">
         <a href="">
           Some random tab text
         </a>
       </div>
       <div style="float: left; height: 1px; width: 1px">
         <!-- comment needed for 1x1px div in ie6 -->
       </div>
    </ol>
 </div>

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 1 pixel wide, my dynamic content div's margin will take a negative 1 pixel width on the left and right. This will yield the result as shown to the left.

We have effectively mimicked the effect of position: absolute by using position: relative. 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!

I hope you enjoy it, and feel free to leave your questions in the comments section below.

You can see a demo page by clicking here. You can download a copy of the demo page by clicking here.

Tuesday, November 16, 2010

jQuery Plugin Pattern 2.1

After having release the jQuery Plugin Pattern 2.0 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!

Goals

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.

  1. Backward compatible with jQuery standard plugin authoring method
    1. Syntax would be $(selector).plugin(args)
    2. Make plugin chainable
    3. Allow this to refer to the selected element
    4. Allow methods to be called the jQuery way (as parameters to the plugin)
  2. Allow Object Oriented Programming inside plugin
  3. Allow to expose the OOP object instead of the jQuery object
    1. Allow classical OOP concepts such as inheritance
  4. Allow n-depth levels of methods a la OOP
  5. Allow plugin to act as a namespace
    1. Syntax would be $(selector).plugin.method()
    2. Make namespace easily changeable in the event of a naming conflict
  6. Allow plugin to be called as a hybrid of standard jQuery mixed with OOP
    1. Syntax would be $(selector).plugin(args).method()
  7. Make version a publicly exposed attribute as a standard
  8. Allow for an easy way to expose public interface
  9. Allow for a plugin initializer
  10. Encourage use of closure based getters and setters
  11. Promote a standardized persistent config accessor

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 and to be able to internally take advantage of jQuery's magic - such as its selectors.

Barebone Pattern

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 [BEGIN YOUR CODE] and [END YOUR CODE]. Take a time to study the code below and then we will examine a real-life example.

/* jQuery Plugin Pattern 2.1
 * Author: Milan Adamovsky
 *
 * This pattern allows you to write jQuery plugins a lot faster, more consistently,
 * and less error prone.  Furthermore it allows namespacing, OOP integration, along
 * with other technical benefits.  
 *
 * There are two "global" (but local) helper methods available throughout each plugin
 * and they are:
 *
 *   getPluginClass() 
 *   getPluginName()
 *
 * The getPluginClass() returns the definition of the entire plugin code.  Usually 
 * this is not needed by the plugin author (you), but in the rare event you would
 * need it, here it is.  It is used internally by the plugin pattern.
 *
 * The getPluginName() returns the name of the plugin's jQuery namespace as defined
 * by the initPlugin() method (which is something you, the author, defines).
 *
 * Attention to JSLint users: this code will not pass due to some advanced paradigms
 * in use, though efforts have been taken to minimize these.  Priority was given to
 * functionality and syntax correctness so that YUI Compressor can properly minify
 * the code.
 */ 

(function($)
  {
   initPlugin({
               name : 'asyncLoader'  // plugin name 
              });
   
   //----plugin class -- BEGIN--------
   function getPluginClass()
    {
     return function (args)
      {
       // Version - directly exposed to be access via $(...).plugin.version
       this.version = '1.0';
      
       // Public Methods - wrappers containing a reference to the actual function 
       this.someMethodA = someMethodA;   // non-chainable method
       this.someMethodB = _(someMethodB);    // chainable method
       
       this.rc = jQuerify;       // required plugin pattern code

       // getConfig - always used to contain class/plugin arguments
       function getConfig()
        {
         return undefined;       // we define this via setConfig()
        }
  
       // setConfig - always used to set class/plugin arguments, usually used indirectly via initConfig
       function setConfig(args)
        {
         getConfig = function()
                      {
                       return (args);
                      };
        }      
  
       // initConfig - sets default values via jQuery's extend()
       function initConfig(args)
        { 
         setConfig($.extend({
                             chainable : true,     // false - this allows us to do something like $(...).plugin(args).method()
                                                   //         this returns the object as the output
                                                   // true  - otherwise, by default, it will assume jQuery native functionality of chainability
                                                   //         this returns what jQuery expects for chaining
                             properties : {}       // any properties that you want to be passed to the plugin.
                            }, args));
         return (this);
        }
  
       //---[BEGIN YOUR CODE below]-------
       //   [Class methods / properties]

       function someMethodA(args)
        {
         alert('This is our non-chainable method!');

         return (this);    // we return this to allow classic OOP
        }
        
       function someMethodB(args)
        {
         alert('This is our chainable method!');

         // we don't have to return anything since the _() takes
         // care of chainability. 
        }
     
                
       // initConfig - gets called to set defaults for plugin
       initConfig(args);   // Pattern code - usually just copy/paste
       
       // we put our logic after the method definitions to keep JSLint a
       // little happier.
        
       //---[END YOUR CODE above]----

       function _ (fn)      // local function that facilitates chainability
        {
         return function (args)
                 {
                  return this.prototype.rc(function () 
                                            { 
                                             fn.call(this, args); 
                                            }); 
                 };
        }
        
       function jQuerify(args)  
        {
         if (typeof args == 'function')
          {
           return $.fn.curReturn.each(args);  // handles chaining of method
          }
         else
          {
           initConfig(args);
           
           return getConfig().chainable       // checks for chaining in main plugin
                   ? $.fn.curReturn           // returns chainability hook
                   : $.fn[getPluginName()];   // returns OOP object hook
                                              // getPluginName() is defined in initPlugin()
          }
        };
      };
    }

   if ($.fn.curReturn === undefined)          // checks if a plugin has already loaded environment
    {
     $.fn.extend({                            // if not then it extends jQuery object.
                  curReturn: null,            // declares placeholder
                  jQueryInit: jQuery.fn.init  // saves original jQuery init method
                 });
      
     $.fn.extend({                            // now we overwrite jQuery's internal init() so we
                                              // can intercept the selector and context.
                  init: function( selector, context ) 
                         {
                          return jQuery.fn.curReturn = new jQuery.fn.jQueryInit(selector, context);
                         }
                 });
    }
        
   function initPlugin(args)
    {  
     getPluginName = function()
                       {
                        return args.name;    // sets getPluginName() to return jQuery plugin name
                       };
                       
//     console && console.log(["Initialize", args.name, "plugin."].join(' '));                    

     try                                       // meat 
      {
       var classCode = getPluginClass(),       // get a reference to the plugin OOP code
       _p = new classCode({});                 // instantiate plugin Class (which is OOP)
       $.fn[getPluginName()] = _p.rc;          // insert instantiated plugin into jQuery namespace
       $.extend($.fn[getPluginName()].prototype,_p);  // augment jQuery internals
       $.extend($.fn[getPluginName()],_p);            // same here.
      }
     catch (error)
      {
       alert(error);                           // in case something breaks let us know.
      }

    }
   
  })(jQuery);

Saturday, November 13, 2010

Pros & Cons of JSLint

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. JSLint is one such contribution and this article will explore it very briefly.

JSLint

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 static code analysis tool which basically means that it does not execute the code but rather analyzes it without actually running it for any potential problems. This is good and bad.

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.

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.

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.

Pros

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.

The tool comes with various switches that allows for fine-tuning to achieve a tailored level of restriction.

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.

Cons

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:

  1. Douglas Crockford
    1. The Good Parts
    2. JSON
  2. Code Quality
  3. and the list goes on...

Essentially what it boils down to is follow the leader. 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.

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.

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 guess your intentions correctly.

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.

  1. Problem at line xx character xx: 'xxxxx' is a function.

    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.

  2. Problem at line xx character xx: 'xxxxx' was used before it was defined.

    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.

  3. Problem at line xx character xx: Expected an identifier and instead saw 'package' (a reserved word).

    JavaScript has many reserved words and amongst them is the word package. So while you should refrain from using reserved words, this error even pops up in a hash key being a reserved word.

     var myPackage = args.package;
    

    It is clear to us that this can never be in conflict with the reserved keyword since it will never occupy the same namespace.

  4. Problem at line xx character xx: 'xxxxx' used out of scope.

    This is an example where JSLint fails to identify proper scoping of a variable. If you declare a variable inside an if statement, followed by a condition that checks against that variable, this error emerges.

    if (1)
     {
      var x = 1;
     }
    if (x)
     {
      ...
     }
    

    As we can see the variable is not scoped (since if statements don't scope a variable in JavaScript), so the above code should not throw an error.

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 one size fits all solution.

Finally The Big Bang

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.

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 the code (minified), jQuery uncompressed, YUI uncompressed, 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.

Points of Argument

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.

JSLint isn't intended for minified code

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.

Friday, November 12, 2010

Closure based Getters & Setters in jQuery

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.

Problem

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.

One of the most abused features of jQuery in this domain, is coincidentally the most used feature of jQuery: selectors (e.g. $(element)). Let's take a look at a silly example.

$(function() 
   {
    for (var x = 10; x > 0; x--)
     {
      x % 2 
       ? $('#someDivId').hide() 
       : $('div#someDivId').show();
     }
   });

In the above example we can see that we select the same div (assuming we follow the W3C standard of assigning unique ids).

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.

Best Practices

Before I dive into how a closure based solution could help, I will illustrate the commonly used solution as a best practice.

$(function() 
   {
    var divSelector = $('#someDivId');
    for (var x = 10; x > 0; x--)
     {
      x % 2 
       ? divSelector.hide() 
       : divSelector.show();
     }
   });

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.

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?

Let's take the next example.

$(function() 
   {
    var divSelector = $('#someDivId');

    aFunction(divSelector);
    bFunction(divSelector);

    function aFunction(args)
     {
      for (var x = 10; x > 0; x--)
       {
        x % 2 
         ? args.hide() 
         : args.show();
       }
     }

    function bFunction(args)
     {
      for (var x = 20; x > 0; x--)
       {
        x % 3 
         ? args.hide() 
         : args.show();
       }
     }

   });

The above example is extremely silly in its functionality, but we merely want to illustrate a concept.

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 divSelector available to aFunction and bFunction globally if we wanted to completely ignore the passed in argument to each function respectively. In other words, we could directly access divSelector from within either of these functions instead of reading args. What is the problem you might ask?

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 modify it - circumventing any error handling logic that may have been defined either in a getter or setter.

Solution

This is where we use a closure based getter and setter as described in my earlier blog post.

$(function() 
   {
    function getDiv()
     {
      var divSelector = $('#someDivId');

      getDiv = function()
                {
                 return (divSelector);
                };

      return getDiv();
     }

    function setDiv(args)
     {
      getDiv = function()
                {
                 return (args);
                };
     }

    aFunction();
    bFunction();

    function aFunction()
     {
      var args = getDiv();

      for (var x = 10; x > 0; x--)
       {
        x % 2 
         ? args.hide() 
         : args.show();
       }
     }

    function bFunction()
     {
      var args = getDiv();

      for (var x = 20; x > 0; x--)
       {
        x % 3 
         ? args.hide() 
         : args.show();
       }
     }

   });

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 new code. Take a minute to understand it.

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.

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.

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.

Finally I will leave you with a clean version of the code as I would implement it.

$(function() 
   {
    aFunction();
    bFunction();

    function aFunction()
     {
      var div = getDiv();

      for (var x = 10; x > 0; x--)
       {
        x % 2 
         ? div.hide() 
         : div.show();
       }
     }

    function bFunction()
     {
      var div = getDiv();

      for (var x = 20; x > 0; x--)
       {
        x % 3 
         ? div.hide() 
         : div.show();
       }
     }

    function getDiv()
     {
      var div = $('#someDivId');

      getDiv = function()
                {
                 return (div);
                };

      return get();
     }

    function setDiv(args)
     {
      getDiv = function()
                {
                 return (args);
                };
     }
   });

Pitfall

There is one pitfall when using this with jQuery: The selected jQuery object gets frozen in time.

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.

Let's look at an example.

$(function() 
   {
    function getDiv()
     {
      var divSelector = $('#someDivId');
      divSelector.html('Hi');

      getDiv = function()
                {
                 return (divSelector);
                };

      return getDiv();
     }

    function setDiv(args)
     {
      getDiv = function()
                {
                 return (args);
                };
     }

    aFunction();
    bFunction();

    function aFunction()
     {
      var args = getDiv();

      args.html('Hello');
     }

    function bFunction()
     {
      var args = getDiv();

      alert(args.html());  // this will say 'Hello' but the element on the page
                           // will still say 'Hi'.
     }

   });

Thursday, October 28, 2010

Closures with Getters and Setters in JavaScript

Whenever we are working on Object Oriented code the best practice is to have getters (also known as accessors) 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.

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.

Problem

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.

function StudentClass(args)
  {
   this.greet = greet;

   var _data = {
                firstName : '',
               };
   
   function getFirstName()
    {
     return _data.firstName;
    }

   function greet()
    {
     alert(getFirstName());
    }

   function setFirstName(args)
    {
     _data.firstName = args;
    }

   setFirstName(args && args.name ? args.name : '');

  }

  var student = new StudentClass({ name : "Milan Adamovsky" });
  student.greet();

Best Practices

Above we observe a few good conventions and practices:

  1. Proper Class naming convention (PascalCase as per Java de facto convention)
  2. Constructor
  3. Private Getter
  4. Private Setter
  5. Exposed public interface (this.greet)
  6. Alphabetized functions
  7. Used underscored variable to imply private variable
Can we see an issue with the above implementation? We sure can: The namespace is cluttered with a private variable that can be accessed directly if we choose to bypass the getter and setter. Urgh!

Solution

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 :)

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.

function StudentClass(args)
  {
   this.greet = greet;

   function getFirstName()
    {
     return undefined;
    }

   function greet()
    {
     alert(getFirstName());
    }

   function setFirstName(args)
    {
     getFirstName = function ()
                     {
                      return (args);
                     };
    }

   setFirstName(args && args.name ? args.name : '');

  }

  var student = new StudentClass({ name : "Milan Adamovsky" });
  student.greet();

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. _data in the first example).

Break Down

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.

Step 1

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 :

function getFirstName()
    {
     return undefined;
    }

We want getFirstName 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 to come.

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. _data).

Step 2

This leads us into the setter that happens to be the closure for the getter.

function setFirstName(args)
    {
     getFirstName = function ()
                     {
                      return (args);
                     };
    }

Take a minute to look at this and it will make sense.

Essentially what is happening is when we set the value we overwrite the respective getter with a new function that returns the passed in parameter to the setter. In our example, that would be the args variable.

The args variable, you will notice, is passed in via setFirstName(args) and captured in the anonymous function that is then assigned to the variable getFirstName which occupies the same namespace as the getFirstName function. VoilĂ ! There is no way to access args unless you use the getter.