Archive for the ‘JavaScript’ Category

Head JS

Head JS is a marvelous thing. 2.3K when gzipped, and look at all it does: screen width detection (with CSS support), HTML5 element injection (like Modernizr), parallel script downloading with serial execution… I haven’t checked how well it does performance-wise, but I hope it’s decent, because I kind of want to start using it everywhere.

Cross-browser JavaScript

I’ve been working on an internal project lately where I am the only presentation-tier developer, which is not unusual here. What is unusual is that the application is lots of JavaScript and Ajax; most of our stuff leans far more heavily on server-side Java.

There are certainly still differences in browser implementations; heck, dealing with cross-browser CSS is a lot of What I Do. And there are certainly differences with JavaScript methods as well. However, the brand-name JavaScript libraries exist, in part, to flatten out and deal with the latter. If you’re using one of those libraries, you can rely on it to account for those differences under its hood.

Thus it was with some surprise that I saw a code check-in yesterday that added client-side browser sniffing… and if you were on anything other than IE, would prohibit you from logging in.

After cleaning up the pile of exclamation points that streamed forward from my eyeballs and littered my desk, I began investigating. It seems that in developing the app, the team had hit a few points where IE and Firefox were behaving differently with regards to JavaScript. The team was concerned that having to do cross-browser development would add lots of development time, and since this is an internal project (and thus we can dictate what browsers are permitted), the team decided to settle on one browser, picking IE.

I feel pretty strongly about browser agnosticism, and also feel pretty strongly that browser-sniffing code is inevitably fragile and tricky (I prefer “duck-typing” based on feature). More importantly, I argued, while there are browser differences with JS, if you’re using a library (which we are, namely jQuery), those things don’t tend to come into play unless you’re dealing with something complicated. If you’re coding up Google Maps, sure — but our application is fairly modest and not at all bleeding-edge. The browser differences we were encountering involve straightforward features, the kinds of things that the libraries should be accounting for… so this suggested there’s an underlying, deeper problem. Blocking a browser to avoid these issues would just be putting a band-aid on a deep wound.

Sure enough, the problems were easily remedied. In one instance, the code was checking to see if a form field was enabled by seeing if the field had a value of “enabled”. The issue? The code should be checking for a boolean of true or false, not a string value of “enabled”. One of the browsers would let you get away with this; the other would not. Changing the code to check for a boolean solved the problem. In another case, updates to a page were showing up in Firefox but not IE. IE, it turns out, was caching Ajax data; a jQuery setting of "$.ajaxSetup({ cache: false });" took care of it.

Once we checked in with the business owner about browser preferences, fighting for browser agnosticism turned out to be the right thing to do. We learned that half the user base for this application uses Firefox, and we’d really have annoyed them if we’d forced them to use IE for this application. The browser-sniffing code got removed today, as did the prohibition on non-IE users. Glad I took a stand!

The lessons here:

  • Use a JS library, and take advantage of its features often. Let it deal with the annoying browser issues.
  • If you’re using a library and encounter a cross-browser JavaScript problem, more often than not this suggests an issue with your code, not the browsers.

Nightmareweaver

My friend Jeremy, a stellar screenwriter/game designer, decided he needed a professional Web site, and so asked our friend Angi Shearstone to do the design, because she’s a terrific artist who has done some beautiful work with professional sites. Jeremy’s site worked fine on his local machine and on Angi’s server, but when he uploaded it to his server, it broke all over the place, so he asked me if I could take a look.

The problem turned out to be some sort of CR/LF issue, where the uploaded files were getting their end-of-line characters stripped, presumably due to a configuration with his client. As a result, the whole page ended up all one line… meaning that everything after the first // in the script got treated as one giant comment. Result: JavaScript errors all over the place.

But I told Jeremy that I was professionally obligated to fix not just the particular problem, but to rework all the code for his site. You see, I’d looked at the source.

Angi admits she’s not a developer, and so uses Dreamweaver. I can hardly fault her for that. Dreamweaver is a tool aimed at, and marketed to, people like her, and so I don’t hold her at fault one bit. However, one peek under the hood and I wanted to drive out to Adobe’s offices with a crowbar. The resulting code looked pretty good… if it were 1998.

(To be fair, I don’t know which version of Dreamweaver Angi is using, but I feel pretty confident she’s not using a copy from the mid-Clinton administration, because the page was using an XHTML DTD.)

Tables for layout? You bet. Paragraph tags with nothing in them but a non-breaking space? Of course. Lots of whitespace in the images instead of neatly-trimmed images with CSS margin or padding? Uh-huh.

…but every single link with an href of “#”? Good God. Yes, every single link relied on its onclick handler to shift the user to the next page. (Needless to say, with most of the JavaScript inadvertently commented out, this caused quite a few problems.)

I know I’m a code snob, with high standards about, well, standards. I also recognize that an automated tool is going to have limitations and can’t do things as cleanly as a human. But this episode really served to demonstrate the value of semantic code and of MVC separation. By changing the headings to actual heading tags like H1 and H2, and by moving the layout into an external .css file, the resulting HTML was tiny… and very human-readable. And that was some pretty big added value for Jeremy, who will have to maintain these pages going forward; he’d have had a lot more trouble trying to deconstruct and reconstruct Dreamweaver’s piles of glop. By moving the complicated, heavy-geek part (the CSS) into an external file, the resulting HTML was small, lean, and manageable.

Look for yourself. Note: as of right now, we still haven’t solved the CR/LF issue. Also note: since Jeremy needed the site up and running before a conference this week, what you’re seeing is not the finished product, but rather what I could deliver to him in time. I still need to add more SEO, address accessibility issues, and get it to format nicely on an iPhone. But as a first cut, from only a couple hours’ worth of work, it’s a big improvement over the bad dream that came from Dreamweaver.

Underscore.js

jQuery is lighter (and often easier to use) than Prototype, but it doesn’t have as rich of a set of functions. That’s why I’m intrigued by Underscore:

Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects. It’s the tie to go along with jQuery’s tux.

Underscore provides 44-odd functions that support both the usual functional suspects: map, select, invoke — as well as more specialized helpers…

Not that every site needs one more framework, mind you, but there are select places where I can see this being useful.

Date.getReal()

In JavaScript, the Date.getDate() method, for the day of the month, returns a number between 1 and 31, as you’d expect.

Date.getMonth() returns a number between 0 and 11.

This means that January 1 is neither 0,0 nor 1,1 – but 0,1.

I have select, unkind words for whoever made this genius decision.

(It’s gotta be worse on those countries that use Roman numerals, rather than names, for the months. It means that the month “IV” returns a value of 3.)

jQuery UI and Scriptaculous

We use Scriptaculous at my day job, so we’re pretty excited about Scripty 2‘s release. We chose Prototype and Scriptaculous because, at the time, they had the best options for visual effects, and arguably Scripty still does, especially with version 2. Still, I’ve been curious about jQuery UI, which was still nascent at the time we picked a library, and has come a long ways since.

Recently I was thinking about the jousting minigame from the classic 1986 video game Defender of the Crown, because I’m that kind of nerd, and realized that I could probably do a decent simulacrum of it nowadays with DHTML. Well, with DHTML and a decent effects library. So I decided to use this as an excuse to play around with jQuery UI and kill two birds with one stone.

The result isn’t finished yet; I’ve got the basics down, but still need to fine-tune the effects and transitions and add a lot of chrome. But I’ve been pleasantly surprised at the positive transfer between jQuery UI and Scriptaculous. This shouldn’t be a surprise, really, since the two libraries are cousins, each learning from and copying the other to their mutual benefit, and they frequently have similar syntax. Moreover, their lists of basic effects are pleasantly similar.

There’s been some negative transfer as well; Prototype’s $ function, for instance, extends the native DOM object that it returns – while jQuery’s $ function only provides jQuery features, meaning that you can’t use methods like innerHTML(). (Not that you should often have to, given jQuery’s html() method, but still, this threw me off.)

Frustrating, though, has been the discovery of how often I get an animation working great in Firefox, only to watch it fail horrendously in IE7. One of the big advantages of using a library is to let the library take care of browser differences (e.g. CSS opacity) for you, and it’s always disappointing when the library doesn’t carry through. (Not, mind you, that I lay the fault here at the feet of jQuery, since I’ve run into the same problems with Prototype/Scripty.) One animation read in the background color value of an element whose CSS class explicitly defined a color; Firefox returned the correct value, while IE insisted its value was “rgb(0, 0, 0)”. Thanks, IE.

MVC separation and our FAQ

I aim to code up my HTML semantically. There are a number of reasons to do so:

  • It’s part of good MVC separation, which is always a win when you reach the inevitable re-design of how the site looks;
  • It’s better for search engine optimization;
  • It makes your page more forwards-compatible, since Web devices that haven’t yet been invented will reliably display your page with some semblance of accuracy;
  • It’s simply the Right Thing to do.

For similar reasons, my workplace espouses unobtrusive JavaScript, again for good MVC reasons.

All of this came to mind when I recently built a new FAQ page for work. There’s nothing about this page that’s particularly revolutionary or awe-inspiring, but it did occur to me that this was a great example of how my own coding principles have improved over time.

Take a look at the page. The designers wanted a list of questions, each a clickable link, with an arrowhead next to each question. Click on a question and the answer would “pop open” below, with the arrowhead now pointing downward to indicate the “open” state. Click the question again and it closes.

Here’s how I would have done this five years ago: each question and answer would be a <div>, with ids with similar names, e.g. question2 and answer2. The questions would have hyperlinks in them, with an inline onclick handler like
<a href="#" onclick="javascript:toggleAnswer('2');">
That handler would take the argument and append it to the word “question” or “answer”, then use that result as the document ID to set style.display to "display" or "none". It would also change the src on the arrowhead image.

Yuck.

Instead, I did it the right way. First off, I recognized that this FAQ is a bullet list, so I coded it as a <ul>, using CSS to hide the standard bullets and instead use the arrowhead image. Each list entry has two elements inside it, with classes “q” and “a”; by default, “a” is hidden with display:none. Class “q” has CSS to make it blue and underlined so that it looks like a hyperlink. (Since it’s not actually a link, just a clickable element, I avoid the <a> tag here.)

Then I made a CSS class, li.open. That class uses the other arrowhead instead, and furthermore has
li.open .a {display:block}
Now we have a class that, when set on a list entry, puts it into its “open” state, with the proper arrowhead and with the answer visible.

Finally, we add the click handlers dynamically, using a JS library (in our case, Prototype). We take each element with class “q” in the list, and add a click handler that sets or removes class “open” as appropriate:

$$('#faqs .q').each(function(s) {
s.observe('click', function() {
this.parentNode.className = (this.parentNode.className=="open") ? "" : "open";
});
});

And that’s it. Clean HTML, CSS to handle the visuals, dynamically-added handlers to keep M, V and C separate. It’s a thing of beauty, baby.