Archive for the ‘Development’ category

Defining “Support” for Legacy Browsers

May 4th, 2009

Jonathan Snook recently posted an interesting article titled Old Browsers: Do they still exist that explores the often hotly-debated topic of when it's ok to pretend a legacy browser no longer exists.

My pragmatism comes into play, like that little devil and angel on my shoulders telling me each side of the story. The fact is, these are old browsers. Why haven't these people upgraded? Why are all these people still using Firefox 2? So what if it's a little (or a lot) broken for them. They should upgrade.

I think most of us as designers and developers would agree with that sentiment; they should upgrade!

The problem, as is often the case, comes from outside the design and engineering teams responsible for building these sites.  It comes from business folks and QA teams that truly believe that "support" means 100% equivalency across browsers.  Any designer or developer will tell you it's a pipe dream and inevitably some concessions are made--but I'd be very interested to hear how much money is spent every year in this industry on trying to come as close as possible to identical cross-browser experiences.  This problem can be defined simply as a lack of consensus on the definition of "support."

My classic argument has always been:

Cross-browser consistency is nice--but in no way critical.  The vast majority of any audience is only ever going to see your site in one browser so let's instead of striving for identical experience let's strive for working experience.

The core of the problem is that we, as stakeholders in our projects, are by definition not users.  As a stakeholder, we open the site in multiple browsers to test, we know the expeirence we want to deliver--and it's easy to become frustrated when one browser behaves differently.

But to focus on the differences across browser is to ingore the truth: Your users aren't going to see your site in every browser.   Users will experience your site in their chosen browser and any feature that is inaccessible in that browser will simply not exist in their eyes.  It's called Progressive Enhancement, and its not a revolutionary concept.

It is, however, what can allow us to deliver a consistently working and functional experience to all users while still providing the "bells and whistles" to those who stay up to date.

Macro-level Support, that is, support for a site, is not about cross-browser consistency--it's about cross-browser functionality.  It's an important distinction.

Motion Easing Equations for Script.aculo.us

November 20th, 2008

Animation and motion are becoming more and more commonplace in modern web application design.  It's no surprise then that many Javascript frameworks provide sets of tools that allow you to easily add this motion to your application.  MooTools and jQuery both integrate a set of easing equations to improve upon the look of linear animation.  Script.aculo.us, however, lags behind in that while it does provide some functions to help the animation appear more "natural," it lacks a truly elegant solution.

Quick Link: View a Demo

Back in 2003, Robert Penner wrote a book on animation using Flash and with that book released a set of "easing equations" that could create natural-looking motion in Flash.  These equations attempt to model real-world motion behavior on the screen; and they do a remarkably good job of it!  So well, in fact, that both MooTools and jQuery have adapted Robert's easing equations into their animation libraries.  After searching in vain for a while to find an implementation of these equations using Script.aculo.us, I decided the best thing to do was create my own--not an overly easy task since Robert's equations were not directly compatible with the "Script.aculo.us way" of handling animation.

Today I'm releasing easing.js for Script.aculo.us 1.8.  I consider this version to 0.8 of this plugin since it does not succeed in porting the entire range of equations from Robert's original set.  The missing equations are:

  • EaseInBounce
  • EaseInOutBounce
  • EaseInElastic
  • EaseOutElastic
  • EaseInOutElastic

The elastic functions should be fairly simple to port over; I simply haven't done them at this point.  The bounce functions, however, were originally written by Robert in such a way that they don't have easily identified counterparts in the Script.aculo.us world.  I will continue my efforts; but I do hope that in the true spirit of open source that others can contribute and improve upon my work.  Ultimately, I hope to submit this to Thomas for inclusion in the Script.aculo.us distribution.

I have provided a quick demo of each effect which is also included in the download package for your convenience.  Please feel free to provide any feedback in the comments.  I hope you find this contribution useful in your projects!

Download easing.js for Script.aculo.us 0.8

Don’t Love Writing Code

November 7th, 2008

Taking a break from code samples and examples today, I want to talk a little bit about my philosophy about development.  Though it may surprise those of you reading this, I don't like writing code.  Sure there's that little bit of excitement that comes from a particularly ingenious snippet; but in general I don't like the process of writing code.  However, I contend that my greatest strength as an engineer is that I don't like to write code.

Lots of code is not brilliant code

I see them (and their code) every day; people who genuinely enjoy and revel in writing code.  These people can get completely engrossed in solving a problem; spend hours and hours working on the problem, and churn out 500+ lines of code that are truly a marvel to look at.  You stare in amazement as you look at this code; how thorougly complicated it seems.  The natural instinct of many developers is to look at that code and say "Congratulations to the brilliant person who solved this obviously incredibly complex problem."  It's just that there's a larger issue: a truly adept engineer will look at their code and say "Well why didn't you just do this?" and proceed to write 10 lines of code that do the same thing in a far simpler, more understandable, and easier to maintain fashion.  I'm sure just about everyone working in any type of software development environment has seen this.  The problem, I contend, is that it doesn't happen enough.

Don't write the code; solve the problem.

Prototype Basics: Creating a Javascript Class

September 24th, 2008

Javascript is, by it's nature, not an object oriented language.  However, everything in Javascript is an object.  So what you have are using objects to write procedural code; a truly intriguing concept.  It brings to light that having objects does not make a language object oriented.  Today I want to talk about the other two important concepts of object-oriented programming in Javascript--classes and inheretance.

In object-oriented programming, a Class is used to define an object; that is, it defines what characteristics an object has (its properties) and what it can do (its methods).  Javascript does not allow for either of these concepts in its native implementation (though we can work around this limitation with some clever programming that I'll cover in another article).  Today I want to look at how the Prototype library provides an easy way for developers to create and extend classes and objects of those classes.

We're going to start with creating a basic class.  Most tutorials at this point degenerate into some silly example involving a car, or an animal.  Given that I'm trying here to provide some real world perspective, I want to look at something we might actually try to implement.  In this case, we'll use a photo viewer.  We want to set up a viewer that can be passed a photo and display it.  Then, we'll use inheretance to extend the class to allow for effects.

Creating a Basic Class

var PhotoViewer = Class.create({
    initialize: function(){
    }
});

There are two important things to note in this example:

  1. The Class.create() method is a prototype method that sets up a class for us.  The primary benefit we get from this is that the class can extend another class (which we will do shortly).
  2. When a new object of this class is created, it will automatically call its initialize method.  In Prototype, initialize is the class constructor.

Now we need to add some methods to our class:

var PhotoViewer = Class.create({
    initialize: function(){
        this.photoContainer = $('container');
    },

    showPhoto: function(url){
        var imgEl = new Element("img", {src: url});
        this._show(imgEl);
    },

    _show: function(imgEl){
       this.photoContainer.update(imgEl);
    }
});

So now we've created our first class using Prototype.  The showPhoto() method is a public method that can be called from outside the object.  A URL for an image is passed into it and a new image element is created using that URL.  The _show method is a "private" method that cannot (in this case, should not) be called from outside the object.  It handles the displaying of the element.

Note that Javascript has no concept of public vs. private methods; therefore users could technically call this method wherever they see fit.  The _methodname convention is sometimes used to denote that a class should be considered private by developers and thus not called.

Extending a Class

Now that we have created our basic PhotoViewer class, let's create a class called AdvancedPhotoViewer that extends PhotoViewer to add animation to the image loading.

var AdvancedPhotoViewer = Class.create(PhotoViewer, {
    initialize: function($super){
        $super();
    },
});

There are again two important new concepts introduced here:

  1. Notice that the Class.create() method now has two arguments, the first is the parent class.  By defining a parent class, our class now has access to all of the properties and methods of its parent.
  2. The $super() method calls the method within the parent class that has the same name as the method in the child class.  By calling $super() in the initialize method of our AdvancedPhotoViewer, we call the initialize method of the parent class.  Were we not to call $super() on a method that has an identically named method in the parent class, the method would overwrite the parent method (which there are many times you want to do, which is why this is left for you to decide whether or not you wish to perform all of the tasks from the parent method first). You will see an example of this in a moment.

Now we want to add some animation using Scriptaculous.  We want the element to begin hidden and then appear using a fade-in transition.  For this, we can override the _show() method to call our animation rather than simply calling update():

var AdvancedPhotoViewer = Class.create(PhotoViewer, {
    initialize: function($super){
        $super();
    },

    _show: function(imgEl){
        /* Notice we don't call $super as we want to override the original method */
        this.photoContainer.insert(imgEl.hide());
        new Effect.Appear(imgEl, {fps: 50, duration: 0.5});
    }
});

As you can see, we've added code which will cause the element to fade in rather than simply appearing.  Notice also that even though we never explicitly created it within the AdvancedPhotoViewer class, we can access the this.photocontainer property because we called the parent constructor that defines it.

So there you have it; a brief tutorial on creating and extending classes using Prototype. I hope you found this tutorial helpful. Please feel free to post any questions you may have in the comments section.

Which JS Framework is “The Best”

June 27th, 2008

After my recent tutorial was posted on NETTUTS, I found the feedback filled with comments such as:

Jquery is the best and can be used to do all of this stuff plus more.

and

Yeah, I agree NETTUTS should only go away from jQuery when it can’t perform something

Reader Tim commented:

Nice. but which is best? Scriptaculous, Mootools, jQuery, or Dreamweaver CS3 built in apps?

What amazes me is not the sentiment so much as it's the nearly religious zeal with which these people are dedicating themselves to a code library.  So I wanted to take a moment to examine the question without that same type of bias--Which JS Framework really IS "the best?"

To attack this problem, we should first really define what "the best" means.  After all, if some code library is worth this type of devotion, I want to be pretty damn sure that it's the best!  So what does it mean to be the best Javascript library?  Here are some thoughts:

  1. It's the smallest
  2. It's the fastest
  3. It provides the most functions
  4. It provides the strongest application structure
  5. It provides a plugin system
  6. It provides clean methods to implement Object-Oriented Programming
  7. It integrates with a powerful back-end development platform
  8. It provides easily maintainable and extensible code.
  9. It's the most widely adopted by the biggest sites

That list was literally written in 30 seconds off the top of my head; I'm sure the true criteria to establish which Javascript library is the best is a far longer list.  That said, we'll use these 9 criteria.   What do we notice about these requirements?  If you answered that some of them lie in nearly direct opposition to each other (such as 1 and 3) you're right.  If you answered that some of them can compensate for weaknesses in other areas (for example, 5 or 8 and 3) you're also right.  Even with a short list of 9 requirements, we know two things:

  1. No one library is going to meet all of these criteria
  2. Not all of the requirements are always requirements

If you're busy debating which Javascript framework is "best," you're fighting a religious war that cannot be won; simply put--no one Javascript library can be objectively defined as "the best."

Gee, thanks Brian.  But which should I use?

In my opinion, for every project, you should evaluate which library makes the most sense to use.  It is certainly reasonable to have a preference (for example, you may feel that jQuery works for about 75% of all the project work you do) and that's great.  You may even find areas of overlap where you continue to use your preferred framework simply because it makes sense. For example, if you know prototype very well but are less experienced with jQuery, you may want to choose to use Prototype in the interest of speeding development even if based solely on the requirements of the project jQuery would be a "better" choice.

My personal opinions

Since you're reading my blog, I will give you what I consider to be my reasonably well-informed personal opinions of the libraries I have worked with and when they make sense:

The library I'm most experienced with is Prototype.  The primary reason is that it is the library we have standardized on here at AutoTrader so I work with it extensively on a daily basis.  My feelings on Prototype are that it is a great library that provides a lot of great functionality, is for the most part reasonably quick (with some notable exceptions).  Both jQuery and MooTools have their roots in Prototype, so moving between those 3 libraries are probably easier than moving to and from others.  For general development, my familiarity with Prototype makes it my first choice.  The biggest thing Prototype has going for it is its implementation of classes and inheritance easing the transition for those very familiar with object oriented programming.

For everything I like about Prototype, I dislike Script.aculo.us.  The way its implemented seems silly to me (creating a new object for each effect is how you execute the effect?) and it doesnt "fit" well with Prototype's code style.  It lacks an implementation of Robert Penner's easing equations which make its animations look less impressive.

I have a strong love of jQuery; it's incredibly small, incredibly fast, and very much follows the paradigm of "get out of the way."  The plugin architecture is fantastic, and the jQuery UI library is great--fully integrated with the jQuery style of coding and integrates everything I'd expect from a fully-featured animation library.  These guys have taken the concept of dereferencing objects to an extreme level--and it can make jQuery code difficult to read at times when you have one line that chains 35 methods.  That said, once you understand its power; its actually quite elegant.

MooTools is another great library, and if you're looking to do a lot of heavy animation work, I'd even suggest it over jQuery.  MooTools began as an animation extension to Prototype that evolved into its own library--but their heavy focus has always been on providing the fastest, smoothest animations of any library.  Obviously its not limited to only animation work; but that's certainly where the bulk of its strength lies.

I'd also like to mention SproutCore--if your goal is to build a fully functional application within a web browser that relies less on Ajax and animation and more on solid application architecture, SproutCore appears to be an excellent choice.  I have far less experience with it than other libraries, but from what I've seen, it's MVC implementation is quite impressive!

I'll refrain from in-depth comments on other libraries with which I have no experience--but there are certainly a multitude of choices out there!

Always remember to take your requirements for the library into account on a project-by-project basis--and don't be afraid to work with multiple frameworks.  It only makes you that much more valuable to an employer!

Accordion Tutorial on NETTUTS

June 11th, 2008

Several of the websites produced by Eden have become perennial favorites in my RSS reader, including FlashDen, PSDTUTS, and most recently, NETTUTS.  Recently, I wrote a tutorial for NETTUTS that you can check out on their site, it's titled Create a Simple, Intelligent Accordion Effect Using Prototype and Scriptaculous.  While you're there, I highly recommend checking out some of the other great content they have.  Many talented folks have contributed tutorials for them, and the site is really establishing itself as one of the premier web development blogs online.

Method & Function Binding in Prototype Javascript

June 6th, 2008

Over the past few days, I've been asked by several colleagues about Prototype's bind() method; what exactly it does and when it should be used. In short, method binding in prototype allows you control the object that the keyword this references within a given context. Binding is a fairly complicated topic that, as I'm writing this post, can be as difficult to explain as it is to understand. However, once you grasp binding, it will seem perfectly natural to you.

To understand binding, you first have to understand a fundamental concept of Javascript: everything is an object. Every function, every element, every string, every array; at their basic level, they are all objects.

The next thing you must understand is what the keyword this means in object-oriented programming; this always refers to the current object. Consider this snippet:

Class TestClass{
  private int testInt = 0;
  public int getTestInt(){
    return this.testInt;
  }
  public void setTestInt(int myInput){
    this.testInt = myInput;
  }
}

In this brief Java example, we can see the use of the this keyword. In plain english, this corresponds to the object saying "This is my value."

This is where it becomes important to remember that everything in Javascript is an object. That means any time we create a function, we are creating an object. The keyword this will refer to the function; not its class. So when does this affect us using prototype? Most often, if affects us any time we use a closure such as in this example:

var Person = Class.create({
  initialize: function(name){
    this.name = name;
    var myArray = $('submitform').getInputs('text');
    myArray.each(function(textbox, i){
      /* this.processFormFields doesn't exist, because "this" refers to the
         anonymous function we've created as a closure */
      this.processFormFields(textbox);
    });
  },
  processFormFields: function(textbox){
    /* do some stuff here */
    /* This will not work, because in this case, this will refer
       to the closure, not the class object */
    textbox.value = this.name;
  }
});

In this case, we can't access methods of our person-classed object from within the closure object. So how can we run the class method from within the closure? Method binding!

Prototype's bind() method allows us to specify the object with which to associate the this keyword. Most often, you'll want to bind the method to the classed object you're working with as in this modified example:

var Person = Class.create({
  initialize: function(name){
    this.name = name;
    this.age = 0;
    var myArray = $('submitform').getInputs('text');
 
    var boundProcess = this.processFormFields.bind(this);
    myArray.each(function(textbox, i){
      /* boundProcess() is a copy of processFormFields that is
         specifies that THIS refers to the class object--not the closure */
      boundProcess(textbox);
    });
  },
  processFormFields: function(textbox){
    /* do some stuff here */
    textbox.value = this.name;
  }
}

Notice two important things here. First, we've used the bind() method. It has created a copy of the processFormFields method that will be able to be used from within the closure (since it does not rely on the this keyword to be called). Second, it has associated itself with the class object; which means that within the method, this.name will refer to this.name within the class object and not look for it in the closure (which would simply be undefined).

The general rule: any time you need to use one of your class methods within a closure and that class method will refer to any class properties using the this keyword, you need to bind that method to the class object.

One of the times that this becomes the most obvious is in event handling. Suppose we add this method to our class above:

eventHandler: function(e){
  this.age = e.element.identify();
}

And we observe it on a click of the "myButton" element:

$('myButton').observe("click", this.eventHandler);

In this case, the context of the event handler will be the element on which the event handler was called. Since myButton does not have a property called this.age, an error will be generated. We need to bind the method to the class object, not the myButton object. However, because this is an event handler, we will use prototypes bindAsEventListener() method which works exactly like bind--except the returned function automatically accepts the event object as its first parameter.

$('myButton').observe("click", this.eventHandler.bindAsEventListener(this));

Now, using this.age in the eventHandler() method will reference the class property age rather than a property of the element on which the eventHandler() was fired.

It's all about context!

Remember, the purpose of method binding is to ensure that you can make use of the "this" keyword. Without access to this, you lose the ability to work effectively with your class objects.

Performance is in the Details

May 29th, 2008

This past week, some colleagues and I sat around a brainstorming table trying to isolate what was causing a particular page to load incredibly slowly in Internet Explorer 6. Drawing on our combined years of experience, and our mutual disdain for IE6, we came up with what we believed to be a solid list of potential bottlenecks that included (among other things):

  1. DOM Parsing (the DOM is very large for this particular page)
  2. Slow / Inefficient Ajax requests
  3. Parsing large JSON strings returned by Ajax request
  4. Too many event handler assignments

We tested each of these theories among the 5-6 others that we had collected and could not find any particular area that was acting particularly slow. Unfortunately, the lack of any serious profiling tools for IE made the task of doing real benchmarks almost impossible. We scratched our heads and adjourned for our 3-day weekend.

In the process of fixing random software defects, one of our other lead engineers stumbled across this line of code that one of our more junior engineers had checked in:

for(var i=0; i < $$('div.contents').length; i++)

My head was spinning just looking at that one statement. For those unfamiliar with Prototype, the $$ method is a sometimes useful, but horribly inefficient means of searching the DOM. In plain English, this method will walk the entire DOM of your document, and check if it matches the CSS selector contained within, and add a reference to that element to an array if it does. When the traversal is complete, the array is returned. Do you see the problem now? Each time the loop ran (conceivably 50+ times in this case, however many elements matched div.contents) it would have to do an entire DOM traversal. Additionally, it would have to calculate the length of the returned array each time!

For reference, as a service to all of the other engineers-those who don't yet know as well as those who have had to clean up after someone who didn't know, better practice would be:

var contents = $$('div.contents');
var length = contents.length;
for(var i=0; i < length; i++)

However, it would be far more advisable to restrict your search of the DOM using prototype's Element.select method to only check the portions of the DOM.

The important take-away here is that you need to exercise extreme caution when using any method that traverses the DOM; especially as long as IE6 is a large player in the browser market as its DOM traversal is notoriously slow. Prototype's $$ is an especially dangerous method (even when used properly) and should only be employed in cases when it truly makes sense—that is, when you need to check the entirety of the document. Far more often, you will know a containing element from which to base your search:

var oddRows = $("container").select("li.odd");

Finally, always remember to calculate all of your parameters outside of a for statement (as in example 2 above). Doing so as part of the statement frankly reeks of the kind of amateur development practice one might get from reading a collection of some of the worst technical books on the market as for some reason they all seem to advocate this kind of thing.

DOM Traversal is expensive. Know what you're looking for and determine the best way to find it; not the easiest.

Keeping Track of Focus

May 22nd, 2008

It's come to my attention that the code contained on this page does not function correctly. I've created an updated post on keeping track of focus which works correctly in all browsers.

One annoying limitation of Javascript is that there is no easy way to track which element currently has focus. In general, we don't really need this information; however, I've recently run across a case where it would be a good idea to be able to know which element currently has focus. Here's a little prototype based Javascript that provides a simple way to track focus throughout your document using event delegation:

var FocusReader = Class.create({
 
    initialize: function(){
 
	this.currentFocus = null;
        var focusRead = this.focusRead.bindAsEventListener(this);
        document.observe("focus", focusRead);
    },
 
    focusRead: function(e){
        this.currentFocus = e.element();
    },
 
    getCurrentFocus: function(){
        return this.currentFocus;
    },
 
    getCurrentFocusId: function(){
	if(this.currentFocus.identify) return this.currentFocus.identify();
    }
 
});

Notice how we've used event delegation to ensure that we can see the focus anywhere in the document without having to add an event handler to every element that may receive focus. We've also provided two ways to represent the focused element--a pointer to the element itself as well as its ID.

Download: focusReader.js (1kb)

An Introduction to Javascript Event Delegation

May 19th, 2008

As development in Javascript moves further away from rollovers and other simple effects into developing true Rich Internet Applications, the number of events we have on our pages increases seemingly exponentially. Catch a left click, a right click, focus, blur, etc.--we're constantly pushing the boundaries of the Javascript event model. Through all of this, one aspect of Javascript events very often gets overlooked: event bubbling and it's power for enabling event delegation.

Reading the specification is often overly complicated, so I will summarize. Event Bubbling specifies that a Javascript event will not only register for the actual element on which the event occurred, but on all of that elements ancestors all the way up to document. For example say we have a form with a text box and we want to perform some action when a user clicks on the text box:

<form onclick="handleClick()">
    <fieldset>
          <input id="bubbleexample" type="text" />
    </fieldset>
</form>

Notice that our event handler has been set on the form and not on the text box itself. When the text box is clicked, the event generated will first be called on the text box itself. Then it will move up to the fieldset. Next it will hit the form element. It will continue to affect each ancestor element until it reaches the root element (document). This is called event bubbling.

Notice also that we are handling that event on the form element and not on the the text box itself. This is called event delegation.

You may, at this point, be asking yourself: what's the advantage of this technique? In the case above where we are only looking at a single event, there is no advantage. However, as the number of event handlers on your page grows, you can see significant performance increase both in terms of processing time and memory use. A complete discussion as to the exact reasons why is beyond the scope of this tutorial; but the important aspects are:

  1. The event handler only has to be applied to one element (reduces processing time)
  2. Only one copy of the event handler will reside in memory (reduces memory consumption)

In this example, I've applied event handlers using event delegation, and included metrics regarding processing time differences between using delegation and adding an event handler to each item individually.

There is, of course, a caveat to using event delegation: events you had no intention to handle will likely need to be handled gracefully by your handlers. Notice on line 12, of the example, the event handler checks to make sure it is not acting on the parent container; only the elements within that container. Obviously, as the DOM becomes more complicated beneath your chosen delegator element, so too will become the handler that must check what element it is being called on.

That said, the benefits do outweigh this potential pitfall. As you'll notice the code for the handler itself merely determines which element it was called on, checks that the element qualifies for action, and passes the element to another function which performs the actual action. This is good architecture; as the code to determine what to do with a particular event grows and multiple paths become possible, your code will be much easier to read and work with when you separate the actual action from the event handling.

So there you have it; a very brief introduction to using event delegation and its advantage over the more traditional paradigm.