Archive for the ‘JavaScript’ Category

The Non-Standard Standards

While doing research for my post on extending the DOM prototypes, I started to wonder: What else do we commonly see in code that works in every browser, but isn’t a part of any official standard?

Here are just a handful of the commonly-used, but never-standardized, features that every browser and his brother support:

innerHTML

I can’t start this discussion without mentioning the granddaddy of all nonstandard standards: innerHTML. The ubiquitous innerHTML property has been around longer than the W3C DOM spec, but it wasn’t a part of any official specification until HTML5. innerHTML allows you to write raw HTML code into an element, and have the browser parse it:

element.innerHTML = "

Emphasis

";

Lightning fast compared to other forms of DOM manipulation (and infinitely more concise), innerHTML was an essential tool long before it was a standard.

Multi-line string literals

In IE, Firefox, Chrome, Safari, and Opera, you can write a multi-line string literal by “escaping” the line breaks with backslashes, like so:

var s = "hello \
world! I am \
full of code!";

According to the ECMAScript 3 spec, that’s illegal syntax. According to every major browser release of the last 10 years, you’re just fine.

offsetHeight and offsetWidth

These two useful Element properties indicate the height or width of an element including its padding and borders as rendered. You’ll find them in every browser, but not in a W3C spec.

if (element.offsetWidth > element.width) {
alert("The element has padding or borders applied!");
}

scrollHeight and scrollWidth

More than a few properties from Microsoft’s DHTML spec have found their way into other browsers. scrollHeight and scrollWidth measure the total number of pixels needed to show an element in its entirety without scrollbars and regardless of whether or not the element is visible. These two properties are lifesavers when trying to animate an element from a display:none state to a display:block state.

scrollTop and scrollLeft

These two properties are also from the MS DHTML spec (oh the things you can get away with when you have an unchallenged browser monopoly for years). scrollTop and scrollLeft define how far an element has been scrolled (the distance from its top or left boundary to the top-most or left-most visible content).

window.onbeforeunload

This event property is used to alert users before they navigate away from the page, and supplies them a chance to cancel navigating away. The property is commonly used to remind users to sign out or save changes before they leave your site:

window.onbeforeunload = function() {
return "Your unsaved changes will be lost if you leave this page.";
}

onbeforeunload was introduced back in IE4, and has since been included in every other major browser. Note that, unlike other onevent properties, you cannot listen for a “beforeunload” event using addEventListener. The reason? It’s not a real event property and operates outside of the normal event system – it’s just deceptively named to look like one.

With the HTML5 spec now specifying exact rules for parsing tag soup, the W3C has made a move back towards recognizing (and codifying) widely supported behavior that’s long existed in the wild. Given that the non-standard standards, like DOM Level 0, aren’t going anywhere–and could benefit from some definition for implementers–I wonder if they’ll eventually get the same treatment.

Rethinking DOM Extensions

I was recently asked my opinion about extending the DOM with JavaScript. Most browsers allow access to the prototype on DOM types, like Node and Element. Some of the earliest JavaScript libraries, most famously Prototype.js, took advantage of that fact to add functionality onto the core DOM types.

DOM extension has been a dirty word in the JavaScript community ever since, and even the Prototype.js team has sworn it off for their 2.0 release. (Juriy Zaytsev details the reasons why in his excellent post, “What’s Wrong with Extending the DOM”.)

Not long ago, I’d have agreed wholeheartedly that DOM extension does more harm than good, but a recent mobile project has got me singing a very different tune: DOM extension may well be the future. (more…)

Feel the Burn: Five Weightloss Tips to Keep Your JavaScript Trim

JavaScript minification is now commonplace on the web, thanks to tools like JSMin, YUI Compressor, Google Closure Compiler, and the Microsoft Ajax Minifier. These useful tools do things like strip out comments, remove unnecessary whitespace, and shorten local variable names to single characters.

There are a lot of little things that a developer can do to help them along with the goal of getting the slimmest, trimmest script file. Let’s take a look at five techniques that you can employ to get JavaScript to burn a little extra fat.

(more…)

Anything But Typical – Learning to Love JavaScript Prototypes

Big thanks to everyone who attended my SXSW 2010 presentation!

For all who couldn’t attend, check out the Anything But Typical slide deck (PPTX).

If you’re interested in digging deeper, here’s the demo and all source code:

A quick warning: The source code is standards-compliant, and thus will not work in IE. Modifications to the event handling and DOM lookups would be necessary to support Internet Explorer’s propriety models.

Detecting transition event support

PPK’s mantra, There is no WebKit on Mobile, has been ringing in my ears since I recently started working on a mobile site targeted towards iPhone 3+, Android 1.5+, and webOS 1.3+.

iPhone 3, Android 1.5, and webOS 1.3 all support easy-peasy CSS-based animations with -webkit-transition, but there’s a big gap with the implementation on webOS.

(more…)

Speaking at SXSW Interactive 2010

If you’re in Austin for SXSWi 2010, come check out my lecture,
Anything But Typical: Learning to Love JavaScript Prototypes. Here’s the skinny:

Frightened and confused by the term “prototype”? Tired of praying that there’s some plugin for a framework that will do exactly what you need to do? Unlock a whole new world of interactivity with object-oriented JavaScript programming. Learn how to design and implement classes that let you simplify and extend your work, and pick up tips on designing compact and reusable front-end code.

Detecting CSS transitions support

Progressive enhancement is one of the cornerstones of good web design: You build a solid foundation that supports a broad range of different browsers, and then add features either as you detect support for them or in a way that doesn’t interfere with less capable browsers.

One of the awesome new features that’s in recent versions of Safari, Safari Mobile (iPhone browser), Chrome, the Android browser, and in Palm’s webOS is CSS transitions. Transitions work by smoothly interpolating between two states of a CSS property over time. For example, using the simple style rules below, you could have a link gradually change from yellow to red when the user moves the mouse over it:

a {color: yellow; -webkit-transition: color 1s linear;}
a:hover {color: red;}

In a more complicated example, you could use CSS transitions to slide an element off-screen when a replacement element is introduced, like the way that the “pages” slide off-screen when you click through an iPhone’s contacts.

This introduces a problem: What if you’re using JavaScript to add the new element, and you want to remove the old element after it’s off screen, and you need to support multiple browsers?

You need to be able to detect that the browser supports CSS transitions so that you know not to remove the element until it’s done animating, and so that you know that it’s OK to remove the element right away for browsers that don’t support CSS transitions. Here’s how you can detect support using JavaScript:

var cssTransitionsSupported = false;
(function() {
var div = document.createElement('div');
div.setAttribute('style', 'transition:top 1s ease;-webkit-transition:top 1s ease;-moz-transition:top 1s ease;');
cssTransitionsSupported = !!(div.style.transition || div.style.webkitTransition || div.style.MozTransition);
delete div;
})();

The variable cssTransitionsSupported will be set to true when transitions are supported, or to false when transitions are not supported.

You can then either use the transitionend (or webkitTransitionEnd for WebKit) event to detect when the transition is finished, or else immediately perform the action when transitions aren’t supported.

Note: CSS transition support has not yet made it into a release version of Firefox. The Mozilla-related code in this post is built around the Gecko 1.9.3 spec.