Main

Too much good stuff

Aug 30 by Andre
I've been pretty busy on a couple projects, and haven't done as much reading as I usually do. When you leave your RSS reader unattended for a week or so, it's seriously overwhelming to come back and try to catch up. There is just an insane amount of innovation going on right now. A few links from my reading this morning:

  • Unobtrusive Rails plugin (version 0.3) was released a week or so ago. Looking forward to trying it, and getting rid of some inline JS for my prototype-based projects.
  • jQuery went 1.0 -- congrats John Resig! Speaking of jQuery, there's a lively discussion based on the relative merits of prototype vs jQuery over here.
  • Here's a good overview of microformats.
  • Streamlined renders administrative interfaces for your Rails models with very little effort on your part. If you've ever wished scaffolding could deal with relationships, check out Streamlined. Although, I think Streamlined is designed to go much farther than you would ever go with scaffolding, i.e., create near production-ready administrative interfaces. Haven't tried it yet, but plan to.
  • For internal web apps that need to behave like desktop apps, check out the recently updated qooxdoo, a JavaScript library with all kinds of treeviews, dialogs, sortable tables, etc. It's heavy, but might be the right solution for a certain class of intranet applications.

Continue reading "Too much good stuff

Video tour of Equinix data center

Aug 27 by Andre
This is really a fascinating video on the Equinix data center, where a lot of big enterprise and consumer sites keep their data (Bank of America, MySpace, Yahoo, etc.). The facility consumes power "equivalent to a small suburban community." They have 28,000 gallons of diesel fuel on site to power the backup generators, which can power the center for up to two days. Link: http://news.com.com/1606-2_3-6109900.html

Continue reading "Video tour of Equinix data center

Unobtrusive tabs, Drag & Drop, and more

May 18 by Andre

You may know from my previous posts that I've been moving away from Prototype/Scriptaculous and toward jQuery for JS/AJAX programming, primarily for jQuery's powerful selectors, code-shrinking chaining model, and light weight.

jQuery also has an active development community, working off of a plugin architecture which allows incremental inclusion of only the modules you need. The community is coming out with some awesome plugins, which will further shrink the functional gap between jQuery and Prototype/Scriptaculous. Below are three exceptional ones from the jQuery mailing list:

Draggable, sortable lists
All the major functions are here: dragging, sorting, target outlines, drop zone highlighting, drag-time ghosting.
Selectables
Define a rectangle by clicking and dragging, and select the elements which fall within the rectangle -- just like selecting icons on your desktop or a group of photos in Picassa.
Accessible, unobtrusive tabs
Render a nice tabbed structure with one line of Javascript. The markup on which the plugin operates is very natural -- the tabs are rendered from a list of anchor tags, exactly how you would (for example) markup a table of contents.

Continue reading "Unobtrusive tabs, Drag & Drop, and more

RadRails

May 03 by Andre

Things I love about RadRails

  • Integrated SVN support
  • Easy tailing of development logs
  • Development Rails servers right there in the IDE
  • Control-shift-R (it's the little things!)

Things I wish RadRails had

  • Integrated FTP ala Dreamweaver (come on, you don't use Capistrano for EVERY little update). Note: may be coming in v0.7
  • . . . integrated Capistrano support (may be coming in v0.63)
  • a debugger! Why do they tease us with a debugging view :-(

Continue reading "RadRails

Google Sketchup goodness

Apr 27 by Andre
Google's free version of the sketchup 3D modeling tool includes two awesome features:
  • the warehouse, an online repository of 3D models of any scale, which are downloadable and reusable by anyone. And anyone can upload to the warehouse as well. There's a great example in the video below of a user who uploads a gate, and someone using the gate model in their house.
  • Google Earth integration -- anyone can "find their house in Google Earth, import the aerial photo and terrain into SketchUp, model their house (or apartment, or whatever), and send it back to Google Earth —for free".
Furthermore, everything can be tagged to a real-world location:
Models shared in the 3D Warehouse will even be able to be geo-referenced, meaning that they'll "know" where they belong in the world. When you submit your models to the warehouse, you'll have the option of including geo-referencing information
Watch the video, you will be impressed: http://download.sketchup.com/downloads/training/tutorials50/The_Story/The_Story.html

Continue reading "Google Sketchup goodness

Lightbox for modal dialogs

Apr 25 by Andre
I'm working on a project which incorporates some AJAXy modal-dialog-like popups. Which prompted me to look into the lightbox-type projects there that would fit the bill. These are the three main projects I found:

Continue reading "Lightbox for modal dialogs

Six key JavaScript techniques

Apr 20 by Andre

These are six techniques I have found to be invaluable in my JavaScript/AJAX development. If you are using library like Prototype.js, these techniques will help you better understand what's going on behind the scenes. On the other hand, if you don't want to use one of the pre-baked JS libraries (for example because you are building a very lightweight page, and don't want to incur Prototype's 50K download), then these techniques provide a very lightweight toolkit to make your JS coding more efficient.

Continue reading "Six key JavaScript techniques

Craigslist "for sale" Google toolbar button

Apr 12 by Andre
Do you live in San Francisco? Use Craigslist.org a lot? Why don't you have a Google toolbar button to take out the drudgery of actually going to the craigslist site?

This button can save you SEVERAL MOUSE CLICKS each time you look on craigslist for something to buy! What the hell are you waiting for?! Download it!

Continue reading "Craigslist "for sale" Google toolbar button

$10K/page for corporate sites

Apr 12 by Andre
This has been dugg so you may already have read it. What caught my eye was the statement:
If many businesses approached space planning the way that they approached web sites their staff would be sitting on milk crates in an unheated concrete room and sales people would meet with customers at the Greyhound Station.
I agree, a good corporate site is an integral part of your business and your messaging, and it is a key touchpoint for your brand. Does such a thing really take $10,000/page? And if it really does in practice, does it have to be that way?

 http://christacy.blogspot.com/2006/03/10000-is-magic-number.html

Continue reading "$10K/page for corporate sites

How to take advantage of web 2.0

Feb 05 by Andre
Dion Hinchcliffe has an excellent post on ten Ways To Take Advantage of Web 2.0 (web2.wsj2.com)

Continue reading "How to take advantage of web 2.0

IBM, others take opensource approach to Ajax

Feb 02 by Andre
The story is here. A few notable excerpts:

In Ajax's case, there is little need to spur emergence of a market, because the market is already there. In most cases, it's been a situation of web developers taking the laws into their own hands, a strategy that Google Maps legitimized.
Very true, and I think precisely one of the reasons developers have been so enthusiastic about Ajax -- when there are no ground rules, it opens up a lot of creative options for developers.

. . . but with battle lines drawing on the future of rich Internet clients, something was bound to give. Like Linux previously, Ajax has become too popular for vendors to ignore.
Also true. The commercial market for Ajax tools and skills is about to explode.

The article goes on to talk about the proliferation of Ajax toolkits (70 at last count), Ajax support in Eclipse, and more.

Continue reading "IBM, others take opensource approach to Ajax

Javascript: Event broadcasting/listening

Feb 02 by Andre

A key advantage of OO programming is reuse. The more broadly useful an object is, the more likely it is you will need to "wire it in" to your page (or other objects) in unanticipated ways. But, if you want the object to trigger event X when Y happens, how do you do it without changing the actual methods in your object?

To connect up your object up to other objects without violating its integrity, you need event broadcasting/listening.

To make this concrete, imagine a simple object representing a tri-state checkbox. HTML checkboxes are two-state (either checked or unchecked), and you need one with three states (checked, unchecked, and grayed out). You will program this as an image which responds to onClick events by cycling the image source through a series of three graphics. So far so good?

What do you want to invoke when the checkbox object changes state? If you're programming it in a non-reusable way, you can hard-code the action directly into the onclick event: if (state==checked) do X; if (state==grayed_out) do y; etc. If you're programming it as a reusable component, you need a more flexible solution.

First, in psuedo-code, for the onClick event:

// PSUEDO CODE!
method onClick() {
  if (state == unchecked) {
    update graphic src to "checked";
    broadcast "checked" event; 
  } else if (state == checked) {
    update graphic src to "grayed_out";
    broadcast "grayed_out" event; 
  } else if (state == grayed_out) {
    update graphic src to "unchecked";
    broadcast "unchecked" event; 
  }
}

Now, your page just needs a way to listen for the events, and you're set -- you can have anything on the page react to an event in the checkbox instance, without changing code inside the checkbox class itself.

How to do it

We're going to create an Observer object, which takes care of both event management (adding and removing events which can be broadcast) and notification (registering functions to be called in the case of a specific event).

/*
Event handler, intended to be used in composition with other objects
*/
function Observer () {
  this.add=add;
  this.remove=remove;
  this.notify=notify;

  this.oObservers = new Object();

  function add (sEvent, fObserver) {
    // must be one of the event types already defined in observers
    if (this.oObservers[sEvent] != null) {
      this.oObservers[sEvent].add(fObserver);
    } else {
      alert("attempted to add an observer for an event which doesn't exist. "+
       "Event Name is "+sEvent);
    }
  }
  
  function remove (sEvent, fObserver) {
    // must be one of the event types already defined in observers
    if (this.oObservers[sEvent] != null) {
      this.oObservers[sEvent].remove(fObserver);
    } else {
      alert("attempted to remove an observer for an event which doesn't exist. "+
        "Event Name is "+sEvent);
    }
  }
  
  function notify(sEvent,oArgs) { 
    if (this.oObservers[sEvent] != null) {
      var aTemp = this.oObservers[sEvent];        
      for(var i = 0; i < aTemp.length; i++) {
        aTemp[i](oArgs);
      }
    } else {
      alert("attempted to invoke an event which doesn't exist. "+
        "Event Name is "+sEvent);
    }
  }
  
  //initialization. If there are any arguments passed, 
  // add them and the associated arrays
  if (arguments.length >0) {
    for (i = 0; i< arguments.length; i ++) {
      this.oObservers[arguments[i]] = new Array();
    }
  }
}

Now, the tri-state checkbox can hold a reference to an instance of Observer, register the necessary events, and broadcast as appropriate. For this class, there is only one event (clicked), but you could have as many events as you want -- just separate them in a comma-delimited list.

// in the constructor for the checkbox class:
this.observers = new Observer();
this.observers.oObservers = {
	"clicked": new Array()
};

. . . .

// the "click" event for the checkbox 
// Pseudo-code except for the Observer.notify() part
onClick() {
  if (state == unchecked) {
    update graphic src to "checked";
    this.observers.notify("clicked",{"sNewState":"checked"});	
  } else if (state == checked) {
    update graphic src to "grayed_out";
    this.observers.notify("clicked",{"sNewState":"grayed_out"});	
  } else if (state == grayed_out) {
		update graphic src to "unchecked";
    this.observers.notify("clicked",{"sNewState":"unchecked"});	
  }
}

This code broadcasts the "clicked" event for each of the three states the checkbox can be in. The first argument to the observer.notify() method is the event name -- recall that for this example, only the "clicked event is defined.

The second argument to the observer.notify() method is a set of key-value pairs, allowing you to pass whatever information you want to the listener. The listener can use these values or discard them, but it has to know the key to access them. In this case we pass only one key (sNewState), but we could pass as many as we like in a comma-delimited list inside the {}'s.

Attaching listeners to events

So far, we've prepared an object for event broadcasting. All that's left to do set up listeners. Attaching listeners to the events the object broadcasts will let us utilize the class in unforeseen ways, without changing the internals of the class.

// assuming you have an instance of checkbox called oCheckBox:
oCheckBox.observers.add("clicked", 
  function(oArgs) {
    alert("You clicked it! New state is: "+oArgs.sNewState);
});		

The "function(oArgs)" is the event handler. We associated it to an instance of the CheckBox class by calling oCheckbox.observers.add(). We're specifying the "clicked" event in the first argument to the observers.add() method.

oArgs is the object we passed in the observers.notify() method. Recall that we specified just one key, sNewState. sNewState is used in the event handler alert().

Of course, in actual usage the object would be more complex, and it would broadcast more events. Handlers tend to stay relatively simply, however -- their main purpose is "wiring together" different objects, so an event in one triggers an action in another which is appropriate for the current page.

A final note: you can add as many event handlers as you like for any event on any object! Just call [object].observers.add() as many times as needed -- the handlers will be executed in the order you add them!

Event broadcasting/listening can add a huge about of flexibility to your Javascript OO programming, and allow you to utilize classes in diverse environments without changing their internals.

Continue reading "Javascript: Event broadcasting/listening

The world is your programmable oyster

Jan 30 by Andre
Programmable Web is a repository of Web 2.0 APIs and mashups. I found this via TechQuik.

Continue reading "The world is your programmable oyster

Good stuff in XHTML 2.0

Jan 27 by Andre
Part two in The Future of HTML series talks more about XHTML2.0. APIs are likely to include:
  • An API for dealing with the browser Window object
  • DOM Level 3 Events and XPath specifications
  • An API for timed events
  • APIs for non-HTTP networking, such as XMPP or SIP
  • An API for client-side persistent storage
  • An API for drag and drop
  • An API for monitoring downloads
  • An API for uploading files

[XHTML2.0 will] allow any element to have a src attribute. A browser will then replace the element's content with that of the content at the URI. In the simple case, this is an image. But nothing says it can't be SVG, XHTML, or any other content type that the browser is able to render.

Continue reading "Good stuff in XHTML 2.0

Javascript: Object Orientation

Jan 22 by Andre

An OO approach is a key part of your Javascript/Ajax programming arsenal. There are multiple ways to program Javascript in an object-oriented way. The Prototype library adds some helper constructs to facilitate object orientation, as do many other Javascript libraries. Regardless of which framework you use (or if you choose to use none at all), an object-oriented approach can make your Ajax programming easier.

Here, I'm demonstrating a basic syntax for OO; you can use this syntax literally, or use it to enhance your understanding of the various framework-based OO approaches available out here.

Defining the Class

In Javascript, classes are defined as functions. The "new" keyword together with the function gives you new instances of the class. Here's an example:
// a Person class
function Person (sName, nAge) {
	this.sName = sName;
	this.nAge = nAge;
} 

// add a method to the class by adding a function to its prototype
Person.prototype.tellMe = function() {
  return ("My Name is "+this.sName+". I am "+this.nAge+" years old");
}
That's all there is too it. You have now defined a class (Person), with one method (tellMe).

Using the Object

To use the Person class we just defined:
var oPerson = new Person("Bob", 28);
alert (oPerson.tellMe());
. . . will give us:

Where's the Constructor?

In this example, all the code inside function Person() is the constructor -- this code gets executed each time you use the function to create a new instance of the class, and sets the members of the instance (sName and nAge) to the values passed to the function.

There's lots more to OO Javascript programming

You can model inheritance and more with Javascript. A good place to learn more is webreference's Object-Oriented Programming with JavaScript series.

Continue reading "Javascript: Object Orientation

Javascript: Adding functionality to built-in classes

Jan 20 by Andre
Strings, arrays, and all other classes in Javascript are extensible, and it's extremely easy to add methods to them. An example is the best way to demonstrate; this example shows a "trim" method (strip whitespace from the beginning and end of string) added to the built-in "string" class:
String.prototype.trim = function () {
  var sNew = this.replace(/^\s*/, ""); // strip whitespace from the beginning of the string
  sNew = sNew.replace(/\s*$/, ""); // strip whitespace from the end of the string
  return sNew; // return the mutated string
}
You can call the method on any instance of string:
var sString = "a value from an HTML form . . . ";
sString = sString.trim();

What you need to know: Prototypes and the "this" keyword

Everything in Javascript has a prototype. Any functions you add to the prototype are automatically available to each and every instance of the class. Accessing the prototype is as easy as specifying [class].prototype. So in the example above, we added a function (trim) to string's prototype: string.prototype.trim=function(){...};

The other key is the "this" keyword. Whenever you are coding a "prototype" function, you need access to the particular instance. The "this" keyword lets you do it. At runtime, the "this" keyword resolves to the actual instance of the object, in this case a String.

Note that this example does not mutate the string on which you called the method. Rather, it returns a new string with whitespace removed. The original instance is left unchanged. If you were to do the following:

var sString = " a value from an HTML form . . . ";
sString.trim();

. . . sString would not change. Calling the trim() method would produce a new string, which would then be thrown away because it isn't being assigned to anything.

Continue reading "Javascript: Adding functionality to built-in classes

Javascript: optional, defaultable function arguments

Jan 18 by Andre
This is an incredibly useful real-world construct for your Javascript and Ajax programming efforts. As you make your Javascript code encapsulated and reusable, you inevitably need to parameterize your functions so that some of the arguments are optional. There are multiple of ways of doing this, but my coding has benefited greatly from a consistent methodology and syntax. Here's an example:
function doSomething (sWhatever, oOptions) {
  var oOptions = augment({
      sOptOne: "foo",
      bOptTwo: false
    }, oOptions );

  // sWhatever is a regular argument. We assume it's always going to be passed
  alert(sWhatever);

  // sOptOne and bOptTwo are optional;
  // they are defaulted to "foo" and false, respectively
  alert(oOptions.sOptOne);
  alert(oOptions.bOptTwo);
}
The function defined above can be called in a number of different ways:
  • doSomething("First value"); -- this invokes the function without either of the optional arguments, so sOptOne and bOptTwo both get their default values ("foo" and false, respectively).
  • doSomething("First value",{bOptTwo:true}); -- in this case, the bOptTwo argument is specified in the functional call, so it's value is true, rather than the default value of false.
  • doSomething("First value",{sOptOne:"Yahoo",bOptTwo:false}); -- here, both the optional arguments are provided.

The key here is that the optional arguments are specified by name, rather than position. Therefore, you can leave any of them out, and they assume the default value you specified in the function itself.

The augment() Function

The "augment()" function is what makes it all happen. This function takes two or more objects, and augments the first object with properties from the second (or subsequent, of you pass more than one) object(s).

For defaultable arguments, the first object is the default values ( that's the {sOptOne: "foo", bOptTwo: false} part, and the second object is the oOptions object passed into our function.

Here is the augment function:

/*
  Augment an object by replacing its key:value pairs with those
  from other object(s), and adding pairs from other object(s) that don't
  exist in you.  Key:value pairs from later objects will
  overwrite those from earlier objects.
  
  If null is given as the initial object, a new one will be created.
  
  This mutates and returns the object passed as oSelf. The other objects are not changed.
*/
function augment (oSelf, oOther) {
    if (oSelf == null) {
        oSelf = {};
    }
    for (var i = 1; i < arguments.length; i++) {
        var o = arguments[i];
        if (typeof(o) != 'undefined' && o != null) {
            for (var j in o) {
                oSelf[j] = o[j];
            }
        }
    }
    return oSelf;
}

Optional, defaultable arguments are a powerful Javascript programming technique. They make it much easier to evolve your code, especially when you build "visual" objects -- objects that correspond to visual elements on the page.

Continue reading "Javascript: optional, defaultable function arguments

Programmatically setting the "float" CSS property in Javascript

Jan 11 by Andre
IE and Firefox have different ways of doing this, and neither one is what you would expect.

In IE, it's myDiv.style.styleFloat="left";

In Firefox, it's myDiv.style.cssFloat="left";

Here's a full code block, with primitive browser detection included. This will work in both IE and Firefox:

if (document.all) {   // very basic browser detection
  var sFloat="styleFloat"; //ie
} else {
  var sFloat="cssFloat"; //firefox
}
var oMyDiv=document.getElementById("myId");oMyDiv.style[sFloat]="left";

Continue reading "Programmatically setting the "float" CSS property in Javascript

What's in *your* Javascript try-catch blocks?

Jan 04 by Andre
For me, one of the best things about the Ajax movement is that it has legitimized usage of the Javascript language, which I have always enjoyed programming in anyway. With JS's new legitimacy comes recognition that we need more of the "real-world" constructs and practices that we all apply to other languages. Like Logging. And better error handling.

And try-catch blocks.

Which brings us to the question, what's in your try-catch blocks? What are you doing when you catch an error?. In some cases you want to take some specific action (redirect the user to another page, show a clear user-visible error, tell the user there's no point going on, etc.), but in other cases there's nothing you can really do for the user -- you just want to record the error so you can debug the problem as quickly as possible. If this was Java, PHP, Ruby, C#, or whatever, you would log an error and that would be that.

With Javascript, you can use JSLog, and log an error in your catch block. The code looks like this:
try {
    var foo = somethingRisky();
} catch (e) {
    jslog.error("Something risky failed! foo="+foo+"; error is "+e.message);
}


Which in turn would give you a JSLog display of:


This works great during development, when you probably have JSLog enabled, and are using it for debugging output anyway. As your code matures into production, you can leave the jslog.error() call there, even as you disable JSLog. If the page is behaving unexpectedly, you can temporarily expose JSLog output (either by switching the config_enabled setting back to true, or by including &enablejslog in the url; see here for details) and see the problem as it was logged in the catch block.

Basically, the problem is that output from the catch block needs someplace to go. JSLog gives it someplace to go, where it can be easily retrieved and inspected, in either a development or production environment. Read more about JSLog here.

Continue reading "What's in *your* Javascript try-catch blocks?

Leave logging statements in your production code

Dec 30 by Andre
A good logging tool is crucial during Ajax development. But it needs to go farther than that -- you need a graceful way of carrying your logging-enabled code through development, into a production environment. The solution should support:

  • No changes to your code: you shouldn't have to comb through your code to remove or comment out your logging statements.
  • Negligible performance impacts: your "productionized" code shouldn't suffer any performance impacts for having the logging system in place.
  • Negligible page weight impacts: likewise, your productionized pages should incur a negligible page weight penalty for including the logging code.
  • Easy troubleshooting in production: once you are in a production environment, you should be able to easily re-enable logging output, to troubleshoot in a pinch.

With JSLog you can leave your logging statements in, even in production code. Here's how to do it:

1. Quick and Easy: Disable JSLog site-wide via a configuration setting

As your code matures into production quality, continue to include jslog.js in your pages, but set config_enabled=false in jslog.js file.

Impact: the logger panel will no longer be visible, and you can leave all of your JSLog calls in your code. The calls become nullops, so the runtime penalty is negligible. However, your users will still be downloading the 6K jslog.js file.

Need to revisit your logging output? If you need to make the debugging panel visible on a page-by-page basis, you can include the string "enablejslog" in the url. Example: http://localhost/mypage.do?foo=bar&enablejslog. Including the string "enablejslog" overrides the "config_enabled=false," and you can see any JSLog output the page generates.


2. Production Grade: Replace the jslog.js file with a stub

Replacing the jslog.js file with a stub makes both the page weight and performance impacts of leaving your logging statements in your code negligable. Here's how:

A) rename jslog.js to jslog_real.js. The jslog_real.js file will continue to contain the full 6K JSLog implementation, but it will no longer be included in your pages because it has been renamed.

B) create a new jslog.js file with the following:

var jslog = {debug:function(){},info:function(){}, 
	warning:function(){}, error:function(){},
	text:function(){}}; var debug=function(){};
	if (location.href.match(/enablejslog/)){
		document.write('<script type="text/javascript"
		src="/includes/scripts/jslog_real.js"></script>');};

The part starting with "if" means you can enalble logging on a page-by-page basis, for example: http://clientsite/page.php?foo=bar&enablejslog, and the stub will dynamically include the real JSLog object, so you can see JSLog output in the JSLog panel as usual. You can leave out the part starting with "if" if you don't need/want that cabability, or just want to save a few extra bytes.

This really gives you the best of all worlds: 1) the ability to leave your logging statements in your code, even as you deploy it to a client; 2) negligible performance impact of leaving the logging statements in; 3) negligible impact on page weight for everyday use; 4) immediate access to the JSLog output if you need to troubleshoot in the production environment.

Recap

JSLog can be part of your strategy as your Ajax code matures from development to production. Even when your code is ready to be fully productionized, it's often helpful to leave your logging code in, for two reasons: 1) it's a pain to remove it, and you can inadvertently introduce errors in your code just be remove logging statements; 2) there is no such thing as code that is completely "done!" At some point you will need to go into that code and make changes, and go through another round of debugging/testing/deployment -- and when you do, it will help to have the logging and debugging statements there.

The configuration setting to turn of JSLog output (by making all JSLog calls null ops) is one easy way to productionize your code without having to remove your logging statements. If pageweight is a concern, you can replace the jslog.js file with a 133-byte stub, which can easily be swapped out if you need to troubleshoot your code. Furthermore, with one additional line of code in the stub file, you can provide the ability to dynamically include the JSLog functionality by typing "enablejslog" in any url. You can use this to help troubleshoot code even after it has been deployed in a production environment.

Continue reading "Leave logging statements in your production code