Archive for the ‘web 2.0’ Category

Found Code: Optimizing Large Form Performance in JavaScript

As I’ve covered before, ill-used JavaScript can lead to some serious performance problems, most of which are caused by simply not thinking about what the code is really doing. Recently I came across a site that provided digital photo printing, This site had a nice interface that allowed my to upload close to three hundred photos. On the resulting page, each photo was displayed with all of the available sizes as input boxes, which looked something like this. I liked the interface, but came across a very serious problem. The event handlers that updated the totals box ran on the keyup event and recalculated the total of the entire form! This worked fine with ten or twenty photos, but the 300 that I provided brought my browser to a screeching halt.

I’ve taken the liberty of creating a very simplistic mock-up of the form and a simplified version of the JavaScript, which is available in my examples section. The demo uses Firebug and Firebug Lite for logging just like I did in my dollar function article, and the benchmark class from that article as well. The site’s JavaScript was a bit more complex and actually did an AJAX lookup of the price on each keyup, but I’m more concerned with the JavaScript performance here, so I simplified the code to something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
var PhotoSelector = Class.create();
PhotoSelector.prototype = {
	initialize: function( name ) {
		var init = new Benchmark();
		init.start();
		console.debug( "Beginning Initialization!" );
 
		$A(document.getElementsByTagName("input")).each( 
			function( inp ) {
				inp.value = 0;
				if( Element.hasClassName(inp,"qtyInput") ) {
					inp.onkeyup = this.recalculate.bindAsEventListener( this );
				}
			}, this
		);
 
		init.end();
		console.debug( "Initialization Complete in " + init.inMillis() + " milli(s)." );
	},
 
	recalculate: function(e) {
		var calc = new Benchmark();
		calc.start();
 
		$("fourby").value = 0;
		$("fiveby").value = 0;
		$("eightby").value = 0;
		$("wallet").value = 0;
 
		var inputs = $("pictures").getElementsByTagName("input");
		for( var i = 0; i < inputs.length; i++ ) {
			var totalId = inputs[i].id.match(/([a-z]+)[0-9]+/|>)[1];
			var total = $(totalId);
			total.value = parseInt(total.value) + parseInt($(inputs[i]).value);
		}
 
		calc.end();
		console.debug( "Recalculation Complete in " + calc.inMillis() + " milli(s)." );
	}
}
var ps;
Event.observe(window,"load",function(e){ps = new PhotoSelector()});

Basically, on window load, this code grabs every input element, sets its value to zero, and binds an event handler to it. The event handler runs on key up and loops through every input box in the “pictures” list, and updates the totals inputs at the top of the page. As I said above, this code works fine with 20 pictures, but it starts getting slow around 300, and becomes almost unusable at 1000. Care to try 10,000? (Be careful, it crashes my browser!) To test it, simply enter values in the photo inputs and watch the totals boxes increment.

The main problem with this code comes from the recalculate function. Problem number one is my personal pet peeve, the dollar sign function is called at least six times! Well, I guess six times wouldn’t be terrible for the entire page, but it’s called at least six times on every key up event! Problem number two, the biggest problem, is the fact that this code re-crawls what amounts to the entire DOM every time the event fires. Obviously the larger the DOM, the more time this is going to take.

So, how do we fix it? Well, here’s how I fixed it, I’ll explain the details below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
var PhotoSelector = Class.create();
PhotoSelector.prototype = {
	initialize: function( name ) {
		var init = new Benchmark();
		init.start();
		console.debug( "Beginning Initialization!" );
 
		this.old = 0;
		var totals = {
			fourby: $("fourby"),
			fiveby: $("fiveby"),
			eightby: $("eightby"),
			wallet: $("wallet")
		};
		totals.fourby.value = 0;
		totals.fiveby.value = 0;
		totals.eightby.value = 0;
		totals.wallet.value = 0;
 
		$$(".qtyInput").each( 
			function( inp, index ) {
				inp.onfocus = this.enter( inp, this ).bindAsEventListener( this );
				inp.onblur = this.recalculate( inp, totals, this ).bindAsEventListener( this );
			}, this
		);
 
		init.end();
		console.debug( "Initialization Complete in " + init.inMillis() + " milli(s)." );
	},
 
	enter: function( inp, me ) {
		return function(e) {
			me.old = parseInt(inp.value);
		}
	},
 
	recalculate: function( inp, totals, me ) {
		var type = inp.id.match(/([a-z]+)[0-9]+/|>)[1];
		var total = totals[type];
		inp.value = 0;
		return function(e) {
			var calc = new Benchmark();
			calc.start();
 
			var newVal = parseInt(inp.value);
			if( me.old > newVal ) {
				newVal = ( me.old - newVal ) * -1;
			}
			total.value = parseInt(total.value) + newVal;
 
			calc.end();
			console.debug( "Recalculation Complete in " + calc.inMillis() + " milli(s)." );
		}
	}
}
var ps;
Event.observe(window,"load",function(e){ps = new PhotoSelector()});

To solve problem number one from above I created a simple object for storing references to all of the total input boxes (lines 9-14), now we have a simple associative array lookup whenever we need to update a total. Problem number two is mainly solved by recording the original value of the input on focus (line 22, 31-35), and then comparing them on blur (line 23, 37-54). Because we’re doing this on blur, we can update only the necessary total input (lines 45-49) instead of recalculating the entire form. I made one final tweak, mainly to make solving problem number one easier, and that is the recalculate function now returns a specific event handler for the given input so that the event handler itself does not need to call the dollar function.

So, comparing these in my regular, not-very-scientific fashion, I came up with the following results. I chose to measure the startup time, which will increase with the size of the page, as well as the event handler time. I also measured these times across a pretty decent amount of pictures, and across a few browsers.

Safari (OS X)

Optimized Time Unoptimized Time
Pictures Load Handler Load Handler
10 4 ms 0 ms 6 ms 3 ms
50 17 ms 0 ms 14 ms 13 ms
100 33 ms 0 ms 24 ms 26 ms
1000 365 ms 0 ms 452 ms 178 ms

Internet Explorer 7 (Windows Vista)

Optimized Time Unoptimized Time
Pictures Load Handler Load Handler
10 56 ms 0 ms 48 ms 9 ms
50 238 ms 0 ms 213 ms 76 ms
100 457 ms 0 ms 424 ms 235 ms
1000 4642 ms 0 ms 4584 ms 28110 ms

28 seconds!? Why!?

Firefox 2 (Windows Vista)

Optimized Time Unoptimized Time
Pictures Load Handler Load Handler
10 12 ms 0 ms 8 ms 7 ms
50 45 ms 0 ms 31 ms 30 ms
100 87 ms 1 ms 60 ms 59 ms
1000 985 ms 3 ms 584 ms 581 ms

The results pretty obviously speak for themselves, but there is one caveat, be sure to notice the initial load time. Since the event handlers still need to be assigned to each input on the page the more inputs there are the longer the page load takes, and the load time is even slightly slower on the optimized page. Be sure to consider this time, possibly by capping the number of inputs displayed, since the code itself is very processor intensive and appears to actually hang the entire computer while processing. Obviously, these fixes become more important as the number of inputs grows, but any speed increase when the user is directly interacting with the page is a good one!

Letting Google Help With Your Site Performance

Let’s face it, cross-browser JavaScript and AJAX without a helper library or framework is pretty difficult. However, these libraries can be pretty hefty when it comes to page download size, especially if sent uncompressed and un-optimized. Most of the libraries have a statement in their docs that says something along the lines of “grow up and compress your JavaScript” but not all of us have sufficient access to their web host to actually be able to do that. Enter Google. Google’s AJAX Libraries API serves as a content distribution network for providing pre-compressed versions of the web’s favorite Web 2.0 JavaScript libraries:

Access to these libraries is quite simple, in fact loading prototype can be accomplished with the following four lines of code:

<script src="http://www.google.com/jsapi"></script>
<script>
	google.load("prototype", "1.6.0.2");
</script>

Pretty simple, but let’s look at some metrics.

With Google Without Google
(no cache) (local cache) (no cache) (local cache)
KB Time KB Time KB Time KB Time
66 982ms 4 980ms 252 2.14s 0 1.19s

As you can see, the Google version is significantly faster and smaller on the initial load, subsequent loads a little less obvious, but still slightly faster. However, this test was not all that scientific, since I really only have the ability to do this with Firefox and Firebug, I only did it once, and my network speed can vary significantly from request to request. Despite all of that, testing this across a few other browser/OS combinations does reveal a pattern where the Google AJAX Library API pages do feel faster, even if only by a fraction of a second. I’ve provided my test pages, with Google and without-Google, for you to perform your own tests, and I’d love to hear what other people think and see their results.

The verdict, I like it, but I have a few caveats. First, as pointed out to me by the Unscrutable Designer, you’re relying on a third party site to host your scripts, in this case it means you need to trust Google to not be evil. Personally, I do, but that is a decision to be made on a case-by-case basis. Secondly, you have to trust the reliability of your content distribution network, can you risk your JavaScript functionality if Google’s server goes down? Thanks to progressive enhancement, having no library should be basically the same as no JavaScript, so my properly implemented site should still function, so this is personally not a show-stopper for me.

Now, one last thought. Keep in mind that this is not the most optimal solution since it still makes a request for each library you load and the libraries themselves are not optimized, but it does bring along with it an interesting benefit. The more sites that use this service the higher the chance of getting a local cache hit on one of these files, which of course means one less download.

Jack of Even More Trades, Master of Even Less?

I’ve been at my current employer for over four years. We do Java-based web application development. Four short years ago, this industry was a different world. Web 2.0 didn’t exist. Ajax was a cleaning product. A website that only worked in IE 6 was good enough for most clients. Tables were a viable solution of any HTML markup problem, and the semantic web had something to do with a children’s book about a pig. Four short years ago we were the Jacks of all web-application development and we had it mastered.

When I started here our tech stack was pretty small, we wrote J2EE applications and we deployed them to WebSphere Application Server (WAS). We wrote these applications using WebSphere Studio Application Developer (WSAD) using a home-brew framework of GoF patterns and JSP scriptlets. JSTL was just entering the scene and JavaScript was a dreaded task used only for fly-overs and submitting forms with more than one possible action. CSS was used for changing font sizes and a table-based layout was not just the norm, it was expected. SEO was using alt attributes on your image element. You could learn this stack in a few weeks while studying for your SCJP cert, be a useful resource on small tasks in a month, and be the lead architect of major subsystems in six. A true master in six short months.

For this career, at least here, a B.S. in computer science was required (emphasis on the BS), but that just got you through the door. Everything else you needed to know you learned in the first six months to a year. You learned how to read code. You learned how to search Google for solutions. You learned how to search the CVS repository for the way we solved it last time for some other client. More importantly you learned how to learn.

Now, here we are four years later, the Web has reached its next version, and discussion has started on the one after that. Our tech stack is now outlined on a four-page spreadsheet. Home-brew pattern implementations are now a thing of the past. We have Spring for IoC and MVC on the middle tier. Hibernate, JPA, iBatis and JDBC for DB persistence, plus web services and SOA, and even a little JCR. The view is now at least JSP/JSTL, sometimes Velocity, sometimes even JSF, and they just generate the markup. CSS is a part of life, tables are for data only, and we sometimes write more JavaScript for a project than we do Java. We deploy to WAS, WAS CE (geronimo), Tomcat, JBoss, WebLogic, and insanely configured combinations of them all. We develop in Eclipse, Rational Application Developer, IntelliJ IDEA, and we might even try NetBeans. We test on IE 6 and 7, Firefox and Safari, we test with and without JavaScript. We advise clients on search engine marketing, social networking, tag clouds, URL rewriting, XML sitemaps, feeds, microformats, link building, link bait, and duplicate content, not to mention semantic HTML with a clean structure and accessible markup. We do automated unit and integration tests, performance testing, code coverage reports, and are discussing a continuous build server.

Our training program remains basically the same. We simply throw more words at the newbies and hope they’ll take the initiative to at least look them up. Now they can write unit test and perform AJAX calls, but they don’t know how to methodically test a simple web form submission. They avoid SQL, especially on a terminal. They regularly check broken code into CVS or foobar a code-sync to the point that work has to stop for hours to clean it up. They have even mastered the ability to create unit tests that provide 100% code coverage but don’t actually test that anything works. They know enough about the technology stack to be literally dangerous.

How do you train people for Web 2.0? I could write and teach a year-long course that covers all of the technologies, but I’m beginning to doubt it would matter, and they’d never take me off of the projects that actually make money to teach it for that long. I’m sad to say, but I don’t think the problem is the training, I think it’s the mentality. You went through college, you know how to write code. If you know how to learn, the size of the tech-stack shouldn’t matter. The tech-stack makes you life easier if you learn how to use it. You don’t learn Web 2.0 from a book or a class, you learn it by living it. You want to design web apps, where’s your website? At least tell me about your idea for the next killer web-app. You want to write code? Show me. What open-source project(s) do you contribute to? Write an awesomely bad and ironic implementation of the fizz-buzz problem and explain to me with a smile on your face why you did it. Tell me why Joel is your new religious leader, how Zeldman and Meyer are your preferred deities. Try and convince me that the CSS Zen Garden is bad, or voice your opinion on the IE 8 version-targetting debate. Show me you have passion. I’m tired of code-monkeys, show me you’re a rock star.

*Smashes keyboard, steps down off the soap box, walks off stage.*

But seriously, is it that much different? We still have the same GoF patterns, we just use somebody else’s named, branded, and marketed implementation. Web 2.0 is just doing the web the right way, it’s using now-established best practices that were still being invented four years ago. We can still be the masters of all things java web-app development, we just need to continue reading and learning. So how do we make the next generation of masters? To that I say you can’t. You need to find them. You need to find the people that have the pre-bubble mentality, the people with the passion and drive to love this stuff. Those people can be groomed to masters simply by showing them where to look. As for the others? Teach them how to use source control. Teach them how to test a web-form. Teach them just enough html to make something look the way the client wants it to in IE. After that, let them work on the .Net and JSF drag-and-drop component-based development. Let them build boring intranet applications that can run on IE 6 until the ancient machines they were designed for finally die. Let them stagnate in the Web 1.0 mentality, and when they’re obsolete, get them out of the way.

Progressive Enhancement and LightWindow

Nothing says Web 2.0 like a lightbox, those nifty, little, modal dialogs that let you create pop-up-like functionality without the worry of pop-up blockers. There are quite a few variations of this concept, including Lightbox JS (and its many variants including Lightbox Gone Wild by the makers of Wufoo), Slimbox, and my personal favorite LightWindow. In general, they’re all pretty unobtrusive, but in this little tutorial I’m going to kick up the progressive enhancement a notch and make LightWindow even better!

Let’s start with a client who wants to use a lightbox to display a multi-view image viewer for an e-commerce site. In true progressive enhancement fashion, if JavaScript is disabled, the user should still be able to perform the basic functionality of the site. So, let’s assume our site has a simple layout with a header, a footer, and a main content area that looks something like this. When JavaScript is disabled the image viewer should show up with the header and footer, when it’s enabled, it should show up in a lightbox without the header and footer. So how do we do it?

LightWindow can be used to display any given webpage by simply setting the class of a link to that webpage to lightwindow. Simple enough. When the lightwindow.js file loads it searches your document for anchor elements with a class of lightwindow and adds the necessary onclick handler to make the link open in a lightbox instead of as a normal page, as unobtrusive as it gets. However, since we want our result page to look differently depending on whether it’s being displayed as a lightwindow or a regular page, we need some way to tell our back-end the display form-factor. To accomplish that we’ll add my own little progressive enhancement to the page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Event.observe( window, "load",
	function(e) {
		$$('.lightwindow').each( 
			function( elem ) {
				if( elem.href ) {
					if( elem.href.indexOf('?') == -1 ) {
						elem.href += '?';
					}
					elem.href += "lightwindow=true";
				}
			}
		);
	}
);

This is simple enough prototype.js JavaScript code that crawls the DOM for elements with a class set to lightwindow and adds a parameter of lightwindow=true to the href attribute. With this parameter in place, the back-end now knows which form-factor to use when rendering the page and we can accomplish our goal with some simple PHP code. (Pardon my PHP, I’m by no means a PHP expert, this is only meant to be a simple example.):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php if( $_GET['lightwindow'] != 'true' ) { ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" debug="true">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-16" />
	<title>Example Lighwindow (JavaScript Disabled)</title>
	<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" />
</head>
<body>
<?php } ?>
	<div class="container" <?php if( $_GET['lightwindow'] == 'true' ) { echo "style=\"width: 300px;\""; } ?>>
		<?php if( $_GET['lightwindow'] != 'true' ) { ?><h1 id="header">Header</h1><?php } ?>
		<p>
			This is my lightbox content, if JavaScript is enabled on your browser you should be seeing it in a LightWindow, 
			if it's not, you should see it with a header and footer similar to <a href="index.html">this page</a>.
		</p>
		<?php if( $_GET['lightwindow'] != 'true' ) { ?>
		<ul id="footer">
			<li><a href="/">Back to EricDeLabar.com</a></li>
		</ul>
		<?php } ?>
	</div>
<?php if( $_GET['lightwindow'] != 'true' ) { ?>
</body>
</html>
<?php } ?>

Problem solved, have a look here and click on the “this link” link. Of course there are a few more programming alternative along these lines, including modifying the LightWindow object at runtime to prevent a second crawl of the DOM for elements with the lightwindow class, theoretically improving performance, but I’m going to leave that for another article.

As an interesting side benefit to this technique, web crawlers like the Googlebot, which don’t interpret JavaScript, will follow the link to the lightbox page and receive a full page as opposed to just the page content. This Allows the robot to continue crawling your site through the navigation and also allows it to see your page title and meta tags. Now, just a little forewarning, be careful with this technique, if you abuse it, it may be considered cloaking any you could have your site delisted for violating the webmaster guidelines. So in other words, use this technique to provide context and don’t try and stuff the pages with keywords or do anything underhanded.

Found Code: JavaScript getElementById, Performance, and the $ Function.

From what I’ve seen, most of the popular JavaScript frameworks out there provide some form of the $ method. This method is usually a cross-browser translation of document.getElementById with a few extras. What this means is instead of always having to type document.getElementById("myId") you can now type $("myId"). All-in-all it’s a very nice shortcut and will probably cut quite a bit of typing out of your JavaScript projects. My problem is with the number of times I’ve come across inefficient uses of this helper function because it’s easier to type. This usually manifests itself as something along these lines (this example written using prototype.js):

1
2
3
4
5
6
if( $("myId").style.display.toLowerCase() == 'none' ) {
	$("myId").style.color = 'red';
	$("myId").style.height = '10px';
	$("myId").style.width = '100px';
	$("myId").style.display = 'block';
}

This code looks pretty concise, if you know what the $ function does it’s also pretty simple, but take a second to think about performance. In this code it’s possible that you’re calling document.getElementById five times! Ignoring whatever else the $ function does, the document.getElementById function could traverse the entire DOM on each call. (I’m not saying it does, but you really don’t know what the browser is doing under the covers and since you’re designing for all JavaScript enabled browsers, it’s better safe than sorry!) If you actually had to type out the document.getElementById you would probably consider something like this:

1
2
3
4
5
6
7
var myId = document.getElementById("myId");
if( myId.style.display.toLowerCase() == 'none' ) {
	myId.style.color = 'red';
	myId.style.height = '10px';
	myId.style.width = '100px';
	myId.style.display = 'block';
}

With this code, you’re only calling document.getElementById once, and therefore only traversing the DOM once. Makes a little more sense right? Let’s look at some metrics.

For this experiment, let’s make the assumption that the larger your document is the longer it will take to perform a DOM traversal, so in order to see some results we’ll need a decent sized document. For that we’ll go to wikipedia and grab something off the front page, in this case it’ll be Harry Potter. To get my test document I viewed the source, grabbed the main body content, and pasted it into a new HTML document. I also removed all of the images since I didn’t want broken images or to be hitting wikipedia’s servers for my experiment. I wrote a quick JavaScript class that will do my benchmarking, and a quick test case that calls my two methods above as well as two other methods and single calls to both the $ function and the document.getElementById function. To perform the benchmark, I run each method 1000 times. I initially tried smaller numbers but there was not enough visual difference to prove my theory since JavaScript is only accurate to the millisecond. You can find the test code here, the benchmark class here, and you can run the test here. I’m using Firebug Lite for the console logging, but if you have Firebug installed it will use the Firebug console. As I said before I just wrote the benchmarking class, but look for a future post and improved version now that the seed has been planted.

I have successfully run the test on Safari 3.1 on OSX 10.5, Firefox 2.0.0.13 and IE 7.0.6000.16643 on Windows Vista Business 64-bit, and IE 6.0.2900… and Safari 3.0.4 on Windows XP Pro. My results were as follows:

getElementById $ function Un-optimized $ function Optimized $ function Un-optimized getElementById Optimized getElementById
Safari Mac 1 ms 4 ms 67 ms 37 ms 42 ms 33 ms
Firefox 7 ms 9 ms 177 ms 121 ms 154 ms 118 ms
IE 7 273 ms 291 ms 1829 ms 364 ms 1688 ms 337 ms
IE 6 312 ms 297 ms 1960 ms 484 ms 1735 ms 375 ms
Safari Windows 0 ms 0 ms 94 ms 47 ms 47 ms 46 ms

Across the board the optimized functions performed better, and in most cases the $ function was slightly slower than the document.getElementById function. The most surprising result is Safari on Windows because it’s actually the slowest machine that these tests were run on. The only problem that I can think of with this test is that it does quite a bit of looking up by id, and that’s probably not an accurate test case, but even if you’re cutting out only a few milliseconds on an event, somebody will notice the improvement. I’m welcome to any suggestions or comments on my testing methodology.


Identity and OpenId

It all started last week when I read an article on Vitamin about the launch of ClickPass at SxSW. I’d noticed OpenID before, mainly on the Ma.gnolia login page, but I never really saw a reason to get one for a single site. Today, I finally decided to check it out.

I started at ClickPass, which lead me to OpenID.net, which listed a page containing all of the OpenIds that I already have. Not really wanting to tie myself to a particular web app, I choose myOpenID because I liked the logo. I quickly created an account, then noticed that you could get a myOpenID for a domain, since I own delabar.org, openid.delabar.org was born. After some quick configuration, I had my open personal OpenID that was easy for me to remember and ready to use. Very cool.

Looking into the topic further, I found Sam Ruby’s instructions for setting up OpenId without using a service, interesting from a privacy perspective since you’re in complete control of your information, but at the same time you lose the third party verifying your identity. Leaving that debate for another day, the best part of the post was the first section where Sam talks about using delegation to claim your blog. With a simple block of code in your html head, something like the following, you can use your blog as your OpenID.

10
11
<link rel="openid.server" href="http://www.myopenid.com/server" />
<link rel="openid.delegate" href="http://openid.delabar.org/eric" />

Using this quick test I verified this, and I can now use my blog URL as my OpenID. Now, what is my reason for doing that? I really don’t have one, since I’m already using my own domain as my OpenID. However, if I was using some other OpenID, like my Flickr URL for example, I would have a level of redirection that would allow me to swap Flickr out for Technorati without having to go and re-authenticate at all of my sites that use OpenID. Now, let’s bring in the Social Graph, a quick bit of XFN code in my link above, and now my OpenID identification page is part of my social graph.

The Web Framework Battle Royale

As you have probably guessed from the subtitle of this blog, I’m a Java guy at heart, in most cases I live and breathe Spring. This doesn’t mean my eyes aren’t open to the fact that there are other web frameworks out there, in fact I’ve done my share of experimenting with RoR, CakePHP, and even Django; as soon as I get a chance I’ll also be playing with Grails. With that said, I’m going to step into the ring.

At the Philly Emerging Tech conference last week there was a panel I wish I would have attended entitled “Battle of the Frameworks! A Roundtable Debate - Which Framework Will be Left Standing?” An amazing topic, but with a fundamental flaw; why does only one need to be left standing? There’s a framework for every budget, language, and style of programming out there; different frameworks are what makes the industry grow and innovate. I work for a company that works for big companies, big companies seem to have a tendency of throwing unreasonable amounts of money at simple problems because some other big company has attached their name to a so-called solution. Is this the right way to make a website? Probably not, but I can’t argue with it because it pays my salary.

Once you step away from the “Enterprise” languages and app-servers you find yourself wandering through an interesting new world of start-ups, consultants, and hobbyists. These are the people who push the new breed of framework, they’re also the ones that push innovation on the web, these are the people that invented web 2.0, and the people that will discover web 3.0 right around the time the “enterprise” figures out what web 2.0 really means. The new frameworks are for innovating entrepreneurs, the old ones are for corporate behemoths. If you fall in between, my personal money’s on the solution with the least amount of risk, and I highly doubt that it’s the one that requires a rack’s worth of servers and $250,000 worth of software licenses.

That’s my two cents; for a different perspective, check out Giles Bowkett’s commentary on the web-framework panel, there’s nothing quite like bringing a little Plato to the table when discussing a near-fistfight at a conference panel. (I saw Giles’ presentation on Metaprogramming at the conference, and I have to say, the more I think about it the more interested I’m becoming in the topic, even if it is a Rails thing.) On a related topic, Giles mentions Obie Fernandez in his post, who’s company Hash Rocket offers the service where they design version 1.0 of you website in three days on rails. Mind you, I’m sure this is version one from the 37signals perspective, but do you really need to risk hundreds of thousands of dollars and months of time to find out your idea is not going to make it? Besides when was the last time you saw a full-featured Java EE app built in three days? Ladies and gentleman, there’s plenty of room for plenty of frameworks and all of the competition and debate that goes with them; I for one cannot wait until the next contender steps into the ring.

Debugging the Client Side

By my definition of Web 2.0, one of the key requirements for any application is cross-browser compatibility. As a company, my employer defines this as IE 6+, Firefox 2+, and Safari 3 beta; all tested on Windows. It’s not ideal, but it covers a huge chunk of the market. This stack is pretty easy to test, but occasionally one of the browsers will throw a curve-ball and that’s where a typical the members of my team, or J2EE developers in general, get lost.

When somebody comes across some weird client-side error and they come looking for my help, I start with three questions:

  1. Does it validate? (Is it a strict doctype?)
  2. Is it in quirks mode?
  3. Did you separate content from presentation from behavior?

I think one and two are pretty obvious, if you’re not following the standards the browser can (and will) do what it wants with your page. Follow the rules and your playing field becomes a lot more level. Number three is a design choice that I prefer for keeping things clean; if your layers are separated, you know what behavior is coming from where. What does this mean? It means style is always stored in an external StyleSheet, JavaScript is always stored in an external JS file, and your HTML markup has no inline event handlers, script blocks, or style attributes. Not only does this make things easier to find and debug it also encourages progressive enhancement and accessible design.

Now that you’ve made sure those three cases are taken care of, do you still have the problem? I’d say 50% of the time the problem is solved, for the rest, here’s what I do. (First things first, make sure your toolbox is in order.)

For debugging CSS, use Firebug’s Inspect tool to make sure the correct CSS rules are applying to your element, this will show you which rules are applying and more importantly, which one is winning in the case of a conflict. If the problem is not showing up in Firefox, I’m guessing it also works in Safari, so it has be an IE issue. Check your floats, check your widths, and make sure you’re not relying on anything IE doesn’t support, like min-height or max-height. If you’re still not sure what’s going on, checkout the Microsoft Developer Toolbar. To get it, go to Microsoft.com and search for “Developer Toolbar,” I’d post a link, but every time I try bookmarking the page it moves, so it’s probably just easier to search for it. The Developer Toolbar works similarly to Firebug, but is definitely lacking. If your problem is in Safari, get a copy of the Webkit Nightly and enable the Web Inspector. It’s definitely better than the IE Developer Toolbar, but still not Firebug. In a pinch, try out the WestCiv XRAY and MRI bookmarklets which are easy enough to install and uninstall on a workstation that is not your own.

If you’re debugging JavaScript, the Firebug console is definitely the way to go for tracing, and you can even make it work on other browsers with their handy JavaScript-based utility. For IE specific errors you can try your luck with the Microsoft Script Debugger (again, search for it), but I find it to be a little bloated. At the time of this writing Webkit offers its own debugger in the form of Drosera, but it’s Mac-only, so unless you’ve got one you’re out of luck there. Finally, you can try out Aptana Studio which offers JavaScript debugging in Firefox (also in IE if you’re willing to pay for it), but I haven’t had a chance to really give it a test drive and at initial glance it seems a little clunky when working with J2EE.

There’s a ton of tools out there for debugging client-side problems, and with a little practice you’ll be debugging like a pro in no time at all. But please, remember one thing, the best offense is a good defense, separate your layers, avoid CSS hacks, and do things the right way the first time.

In the beginning there was DOCTYPE

Alright, in the beginning there wasn’t DOCTYPE, it didn’t come along until about the time XHTML was released; however, if you want to do the Web 2.0 thing right, it helps to start on a solid base.

My goal here is to get a brand-new HTML document up and running as a good base for designing a Web 2.0 application. Today, we’ll look at the parts of a document that the typical user doesn’t actually see, but play a huge role in how a user finds your site and how it’s actually rendered on their screen.

First things first; make your DOCTYPE the first line of the file. That’s right, line number one, no XML definition, no spaces, no server-side code, the first line of the file. This ensures that you don’t end up in quirks mode accidentally. Now, as far as DOCTYPE’s go, I really only see two options, HTML 4.01 Strict and XHTML 1.0 Strict. There are theoretically valid arguments for not using XHTML, most of which have to do with the simple fact that most web servers don’t serve it as XML and most browsers don’t read it as XML, but that’s a different article for a different day. Today, we’re using XHTML 1.0 Strict because the client insists that we use the latest technology regardless of whether or not it’s appropriate; so this is what the DOCTYPE definition for XHTML 1.0 Strict looks like:

1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">


Remember, that’s the very first line of your file!

Next, let’s get the basic xhtml in there:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 <head>
  <meta http-equiv="Content-Type"
        content="text/html; charset=UTF-8"/>
 </head>
 <body>
 ...
 </body>
</html>


Next, let’s get some very basic SEO framework in there and add some meta elements. Meta elements are sometimes called meta tags, but since we’re working in an XHTML document we’ll use the XML terminology. We’ll use description and keywords, and throw author in the for good taste.

5
6
7
<meta name="keywords" content="page, site, title, keyword, doctype"/>
<meta name="author" content="Eric DeLabar"/>
<meta name="description" content="A short description of the page content."/>


Great, now there’s a place for keywords and a description, but why do we need them? Keywords are old-school, I don’t even know if modern crawlers still look at them, but I do know that like all meta elements they should be specific for the page you’re writing them for. So, as a means of guiding my SEO, I usually choose the 5-10 keywords that I want to apply to my current page, then make sure that as I’m writing the page copy I use those keywords.

The description meta element is slightly different, because it’s visibly used. It is displayed by some search engines as a description of your page when it occurs as a result. As a guide to writing a description, keep it short, around 128-256 characters. Keep in mind that if it’s too long it will most likely by truncated, so just write a sentence describing the current page.

Now, we’ll have a look at the page title:

8
<title> Descriptive Page Title - EricDeLabar.com</title>


Like the meta description, the title element is displayed as part of a search result list, so a descriptive title can be very helpful for drawing users into your site. Some SEO experts also believe that keywords in your title are more heavily weighted in search rankings. Keep the title shorter than your description, and maybe consider including your branding at the end. I like the branding at the end because if it does get truncated by the search engine more of my more important descriptive title is displayed.

Finally, let’s add the stylesheets:

9
10
11
12
<link rel="stylesheet" type="text/css" href="/style/screen.css" media="screen"/>
<!-- [if lte IE 6]>

  <link rel="stylesheet" type="text/css" href="/style/iefix_screen.css" media="screen"/>
<![endif]-->


Now I’m a bit of a purist, and I’ll have a later post describing my process for styling a page, but notice for now, I usually have a minimum of two stylesheets. The first being a clean stylesheet (as in NO Hacks/Filters/Whatever you like to call them) that handles all of the (mostly) standards complaint browsers, then an Internet Explorer conditional comment for handling older versions of IE. In this case, my iefix stylesheet is for lte IE 6 which translates to Less than or equal to Internet Explorer 6. Notice that the iefix stylesheet comes after the other stylesheet(s), this is so that any rules in the iefix stylesheet with equal or greater CSS specificity will overwrite the rules in the standard stylesheet. (More on specificity in a later post.)

That’s it! Congratulations, you have a nice, clean base to start your web 2.0 website on! If you’re curious, the finished product looks something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
  <meta name="keywords" content="page, site, title, keyword, doctype"/>
  <meta name="author" content="Eric DeLabar"/>
  <meta name="description" content="A short description of the page content."/>
  <title>Descriptive Page Title - EricDeLabar.com</title>
  <link rel="stylesheet" type="text/css" href="/style/screen.css" media="screen"/>
  <!--[if lte IE 6]>

    <link rel="stylesheet" type="text/css" href="/style/iefix_screen.css" media="screen"/>
  <![endif]-->
 </head>
 <body>
 ...
 </body>
</html>

Web 2.0 — Religion & Politics

First, a separation of church and state. I did not coin the term Web 2.0, and I have no particular feelings towards it (either for or against.) What I do feel is that the idea of Web 2.0 has put a few very important issues onto the map.

  • Standards Compliant and Semantic HTML
  • Cascading Style Sheets (CSS)
  • Client Side Scripting (JavaScript)
  • Usability
  • Accessibility
  • Ajax

This blog aims to discuss these issues and more from a technical aspect. I hope to provided tutorials, insights, and best practices for front-end development; but where necessary, back-end code will be provided in either Ruby-on-Rails or Java.

So that’s it, let’s see where it goes from here!