Elements of Javascript Style

Javascript is a very forgiving language to program in. As such, everyone has their own way to program it.

My personal Javascript style is continuously evolving thanks to everything I learn from watching YUI’s Crockford videos.

At the moment, I try to approximate most of Yahoo!’s design choices when creating a custom library for a site.

I begin by creating a namespace I will use for all scripts within the site. for example, if it was a script for this site I might go with Ebetan (I am a lazy typist), for the Widget Company, I might go with Widget or Widgetco. the idea is to have a Unique name for a global (Singleton) javascript object where all the scripts and objects you create can reside to avoid any naming collisions with other libraries / scripts you might use (or hack together on the fly). Javascript operates in global scope by default, which can easily create problems for programmers that are new to the environment.

[code lang=”javascript”]
var Foo = {};
[/code]

right above that, I like to create a $ function that is simply a wrapper for YAHOO.util.Dom.get. This makes syntax much cleaner than the typical document.getElementById. Its a convention that I copied from ProtypeJS.

[code lang=”javascript”]
var $ = function( elementId ){
return YAHOO.util.Dom.get( elementId );
};
[/code]

just below the declaration of the base class, I like to have commented out prototype methods for built-in classes. It makes it very easy for add a prototype method to a class just by commenting out the required lines, but at the same time I don’t weigh my code down with a bunch of prototypes I’m not actually using, and since I usually minify my javascript before closing out a project, I don’t have to worry about slowing down the download of the files(comments will just get removed). Here are most of the prototypes that I use (for the sake of appearance, I removed all of the ones that were more than one line, and a few of the longer ones

[code lang=”javascript”]
// Array.prototype.forEach = function(f){var i=this.length,j,l=this.length;for(i=0;i<l;i++){if((j=this[i])){f(j);}}};
// Array.prototype.contains = function(element){for(var i=0;i<this.length;i++){if(this[i]==element){return true;}}return false;};
// Array.prototype.clear = function(){this.length=0;};
// Array.prototype.shift = function(){for(var i=1;i<this.length;i++){this[i-1]=this[i];}this.length=this.length-1;};
// Array.prototype.unshift = function(item){this[this.length]=null;for(var i=1;i<this.length;i++){this[i]=this[i-1];}this[0]=item;};
// Array.prototype.sort = function(){var tmp;for(var i=0;i<this.length;i++){for(var j=0;j<this.length;j++){if(this[i]<this[j]){tmp=this[i];this[i]=this[j];this[j]=tmp;}}}};
//
// String.prototype.scan = function(pattern,iterator){this.gsub(pattern, iterator);return this;};
// String.prototype.strip = function() {return this.replace(/^s+/, ”).replace(/s+$/, ”);};
// String.prototype.stripTags = function(){return this.replace(/]+>/gi, ”);};
// String.prototype.escapeHTML = function(){var div=document.createElement(‘div’);var text=document.createTextNode(this);div.appendChild(text);return div.innerHTML;};
// String.prototype.unescapeHTML = function(){var div=document.createElement(‘div’);div.innerHTML=this.stripTags();return div.childNodes[0] ? div.childNodes[0].nodeValue : ”;};
// String.prototype.toArray = function() {return this.split(”);};
// String.prototype.toDom = function(){var div=document.createElement(‘div’);div.innerHTML=this;return div.firstChild;};
// String.prototype.trim = function(){return this.replace(/^s+|s+$/g,”);};
// String.prototype.reverse = function(){return this.split(”).reverse().join(”);};
[/code]

at the bottom of the file, I like to cover myself for browsers that have not implemented console.log

[code lang=”javascript”]
try{console.log(”);}catch(e){var console={log:function(){}};}
[/code]

If my project will be using Ajax (most of them have at least a little) I like to occasionally use a modal loading window when something sensitive is changing on the screen. Luckily, YUI has some sample code on how to use their libraries for just this purpose, I of course integrate this code into my class.

[code lang=”javascript”]
loading_window:{},
loading:function(){
Foo.loading_window.show();
},
end_loading:function(){
Foo.loading_window.hide();
},
init:function(){
var modal = true;
Foo.loading_window = new YAHOO.widget.Panel(“wait”, {
width:”240px”,
fixedcenter:true,
close:false,
draggable:false,
zindex:50,
modal: modal,
visible:false,
shim:true
});
Foo.loading_window.setHeader(“Loading, please wait…”);
Foo.loading_window.setBody(‘<img src=”http://us.i1.yimg.com/us.yimg.com/i/us/per/gr/gp/rel_interstitial_loading.gif” />’);
Foo.loading_window.render(document.body);
},
[/code]

you should notice I have also created an “init” method, the idea behind this is to execute this method once the page is done loading (when the DOM becomes available). to do that I make this the last line of the javascript file

[code lang=”javascript”]
YAHOO.util.Event.onDOMReady( Foo.init, null, Foo );
[/code]

Now that I have this nifty little loader, I want to have an easy way to show it and hide it whenever i make an Ajax call. To do that, I have an minor abstraction of Yahoo!’s Ajax implementation. I add these two methods to my javascript file.

[code lang=”javascript”]
makeAjaxCall: function( url, params, parser, method, args ){
params = params || ”;
parser = parser || function(o){void(null);};
method = method || ‘GET';
args = args || {};
args._ajax_call_url = url;
Foo.loading();
var callback =
{
success:function(o){
parser(o);
Foo.end_loading();
},
failure:function(o){
Foo.log(‘There was an Ajax Communication Error calling : ‘+o.argument._ajax_call_url);
Foo.log(‘The Status was: ‘+o.status+’ ‘+o.statusText);
Foo.end_loading();
},
argument:args
};
YAHOO.util.Connect.asyncRequest( method, url, callback, params );
},
sendFormByAjax: function( form_id, url, parser, method, args ){
parser = parser || function(o){void(null);};
method = method || ‘GET';
args = args || {};
args._ajax_call_url = url;
Foo.loading();
var callback =
{
success:function(o){
parser(o);
Foo.end_loading();
},
failure:function(o){
Foo.log(‘There was an Ajax Communication Error calling : ‘+o.argument._ajax_call_url);
Foo.log(‘The Status was: ‘+o.status+’ ‘+o.statusText);
Foo.end_loading();
},
argument:args
};
YAHOO.util.Connect.setForm( form_id );
YAHOO.util.Connect.asyncRequest( method, url, callback );
}
[/code]

Now that we have this very useful base class, we want a way to easily hang second level classes from it (namely, now that I have Foo, I want to create Foo.Bar under it, and have methods like Foo.Bar.drink_beer(‘corona’). The ideal solution is to wrap up the logic for testing for existence of parent classes and creating the ones that don’t exist in a simple clean method. So we add a namespace method to Foo.

[code lang=”javascript”]
namespace: function() {
var a=arguments, o=null, i, j, d;
for (i=0; i<a .length; i=i+1) {
d=a[i].split(“.”);
o=window;
for (j=0; j<d.length; j=j+1) {
o[d[j]]=o[d[j]] || {};
o=o[d[j]];
}
}
return o;
}
[/code]

Now, even though I have made sure console.log is declared for browsers that don’t support it, sending code to production that uses console.log actively is not a good idea (certainly a better one that “alert();”, however. What I like to do is implement a log method, in this case Foo.log(), that simply wraps console.log. What the heck is the advantage of that? Simple, I also create a class property called “debug_on”. Foo.log will test if the value of Foo.debug_on is “truthy” if so, then log, if not do nothing. Now when I publish my code, I can just set debug_on to false. If I need to debug in production, a bookmarklet, firebug command, or greasemonkey script can override my personal client instance of the “debug_on” setting without disrupting the experience of other users. (I’ll show you how to do this in a later post).

[code lang=”javascript”]
debug_on:true,
log:function(msg){if(Foo.debug_on){console.log(msg);}}
[/code]

In the first level of the javascript class, I typically also have alot of convenience classes. For example, I have a standardized set of feedback divs and styles that I use, and I like to be able to easily use them from Javascript for Ajax and other interactions. I have a few class members for browser detection, and a few other utilities for form manipulation, dynamically determining the relative path of the script for other resources (css and images for example). Each of these items will also be covered in later posts

If you were playing along with the walkthrough, you probably pasted everything above in your text editor. If you are getting errors, check the commas between methods and properties, OR you could just download the sample file I created above from here. (see! laziness does pay off! At least once in a while!)

How I Use TextMate

All Programmers swear by their editor. Its like a religion. You only need to think about the ongoing joke of emacs vs vi in the Unix world to get a sense of the fact that its not something we take lightly.

One very popular choice of editor on Mac is Macromates’ TextMate. Just like the two iconic Unix editors, the power of TextMate lies not within the application itself, although, it IS an incredible application, it fits in just seemlessly with the rest of the User Experience in OS X, and it integrates pretty nicely with popular Mac FTP client Transmit . No, the REAL power of TextMate lies in its plugin architecture. These plugins are called “Bundles”. And TextMate comes with a million of these right out of the box. This leads to people having different methodologies for how they like to use TextMate.

My career is in Web Development, so that is going to be the workflow I describe here. I also plan to use TextMate more for Cocoa / Objective-C as I learn the language, but for now I code that mostly in XCode.

I typically program in a very web-centric list of languages: PHP, Javascript, HTML, CSS, XML, SQL. The syntax highlighting for all of these is very good, its even smart enough to notice if I have SQL being set into a PHP variable and highlight that string appropriately. For example:

Picture 6.png

I would like drop-down autocompletion like what you see in alot of bloated IDE’s, but really, I know all these languages so well, that would just be indulging a lazy typist. For Javascript, YUI is typically my framework of choice, I have installed a Bundle for it that offers parameter help, tons of macros / code snippets whatever you want to call them, and highlighting of built-in YUI classes / methods.

I almost always work in “project mode”, not sure if thats the real name, but its what I call it. Its what happens when you open a folder with TextMate, you can do this by dragging the folder to the icon, through the command line utility (mate foldername/ ) or through Quicksiver (my personal favorite)

Picture 11.png

this will give you the “Project Drawer” which is the file browser type thing you are used to seeing in a lot of desktop text editors / IDEs:

Picture 10.png

If its a folder you work with frequently, you can save this as a project through File > Save Project As… , and then just open that file whenever you want the same folders loaded in your project drawer. You can use this project trick to get all your Transmit (FTP client) files to open in TextMate with tabs (instead of each file in its own window.)

I like to use the TextMate TODO Bundle to track points in my code where I have something to do(as the name implies), I can also flag code to fix with “FIXME” and mark any of these items as done with the keyword “CHANGED” in my comments. (I actually modified the plugin to use the word DONE instead, but CHANGED is the default) . The bundle works by placing specially formatted comments like so (either manually or by triggering the code snippet by typing “todo” followed by a TAB):

Picture 1.png

also works in HTML:

Picture 2.png

the bundle is smart enough to know the appropriate kind of comments for the language you cursor is currently sitting in.

you can then get a list of all your outstanding action items (or “Next Actions” for you GTDers out there) with a simple CTRL+SHIFT+T:

Picture 3.png

This methodology allows me to track what I need to do WHERE I need to do it. And the filenames you see on the left with the line numbers next to them are links that will jump right to that line in the file, and put your cursor there. (for the image above, note that I added my own “DELETE” comment and renamed “CHANGED” to “DONE” as I mentioned above..its amazing how easy this is to do if you go to Bundles > TODO > Preferences )

Picture 12.png

The only down side to this integrated work environment is that I’m not the only one using it. This way of working is also quite popular at Yahoo! (and apparently so is TextMate). The guys working on Ruby on Rails are also fans of TextMate, and its TODO Bundle. Especially its creator David Heinemeier Hansson and his team at 37 signals, if you have ever seen any of their rails screen-casts, you will notice they are working in TextMate. Cool, its a popular way to work, what’s wrong with that? Well, whenever I work in a project where I use YUI or Rails, and hit CTRL+SHIFT+T I not only get MY to-dos I also get all of the to-dos from those projects! Luckily I found the solution in this blog post:

Ex dolo with intent: exdolo.com

if you’re too lazy to click through to the post:

Go to Preferences → Advanced → Folder References and change the Folder Pattern from:

!.*/(.[^/]*|CVS|_darcs|{arch}|blib|.*~.nib|.*.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$

to:

!.*/(.[^/]*|rails|CVS|_darcs|{arch}|blib|.*~.nib|.*.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$

the equivalent expression I use for YUI:

!.*/(.[^/]*|yui|CVS|_darcs|{arch}|blib|.*~.nib|.*.(framework|app|pbproj|pbxproj|xcode(proj)?|bundle))$

Your milage may vary, I put all the YUI modules in the /js/yui/… directory of my projects, so filtering for the yui folder works for me.

The final piece of the puzzle is, of course, source control. I have a Subversion repository hosted at DreamHost. I simply followed these instructions for setting up a subversion repository, and just for kicks set up a Trac server. I really recommend using the HowTo and script posted here.

I then import / checkout my subversion repository from the command-line. It is very important to do your first checkout with username and password. A lot of Mac GUI clients try to make life too easy for you, and they will use the authentication credentials used to create the repository. I then install the Subversion plugin for Finder, and use the Subversion Bundle for TextMate (you knew that was coming, didn’t you).

Also, the subversion plugin for finder adds a little badge overlay to the icons in finder. Which is nice, because that same badge shows up in your title area in TextMate. see the little green dot with a check mark in the lower left corner of the html icon that tells me this is the latest working version of the file, a red dot with an “X” means my file has been locally modified, Yellow dot with questionmark means it doesn’t exist in the repository (needs to be added), and so on.

Picture 8.png

The subversion TextMate bundle has alot of advantages. For instance, I tend to work in a lot of different files in just a couple of hours. MVC development and Ajax work quickly increase the number of files you are touching. One Ajax call can involve the HTML page its its made from, a separate Javascript file, the PHP page receiving your Ajax call, and the controller underlying that page (hopefully you don’t need to touch the model.) After 3 or 4 hours of this, I have probably modified at least 10 files. This is where TextMate and the Subversion bundle make my life very easy. I can get the subversion status, which tells me what is modified, what files are not in the repository ( have a ? ), are added to the repository, but not had their first commit, etc. I can pull this status at the root of my project. With the project drawer open select the top-level folder and hit CTRL+SHIFT+A to get a context-type menu:

Picture 7.png

from this hit “0”…thats a zero, not a letter “o”. TextMate will generate a nice little report like this for you. And as an added bonus, its a completely interactive HTML form, you can add, diff, revert your files directly from the report, and then hit the commit button to commit all your work to the Subversion server!

Picture 4.png

Working with TextMate is absolutely the best experience I have had with a text editor / IDE. And I have tried more than a few, was actually quite happy with Zend Studio, and use it for its debugging, remote debugging capability, but I look forward to the day I can do this from within TextMate as well! If you are trying out TextMate, I recommend taking a look at the bundle it includes for the language you typically work in, by going to Bundles in the Menu, there are all sorts of cool stuff, for instance, PHP can execute the files and show you the output, or verify the file for syntax errors. Every couple of months I try a new editor (Alot of Ajax IDEs are coming out now a days!) but always find myself coming back.

Love TextMate? Hate it? Think I’m an idiot and should use BBEdit instead? Tell me in the comments!