Coding with Jesse

Rich Text Editing in Opera 9

This happened a few days ago, but I didn't think to blog about it until now for some reason: Opera 9 has been released. There are a lot of changes to it, the most notable (to me anyway) is the presence of Rich Text Editing, otherwise known as contentEditable or designMode. Click here for a demo and documentation. I've had a chance to play around with it and it works very well using existing code from Firefox and Internet Explorer. It seems there are some minor differences for really specific things, but overall I was suprised at how compatible it was right out of the box.

Now if only Safari's rich text editing could get this sophisticated...

There are other big changes that look great, but I won't bother listing them all here. Go take a look at the release notes for that.

Published on June 23rd, 2006. © Jesse Skinner

addDOMLoadEvent

Update March 2014: This code is now available on GitHub

There has been a problem with using window.onload in JavaScript. This event handler waits until all the images and other files load before executing. If you need some JavaScript to execute when the page loads, you usually only need the HTML to be downloaded, not all the images.

The event to use for this is "DOMContentLoaded", but only Firefox (and recently, Opera 9) support this. There are different ways to do this in every other browser, and people have been working on finding a complete solution to this for some time.

Very recently, this problem has been solved by Dean Edwards, Matthias Miller and John Resig. There is a unique solution for Internet Explorer, Safari, and for W3C-compatible browsers (Firefox and Opera 9).

Very soon after, Dan Webb adapted the solution to prototype. Unlike the original solution, this code allows you to add more than one function to be executed when the DOM loads.

Inspired by Simon Willison's addLoadEvent function, I wanted to create a standalone generic solution that anyone could use without needing a specific framework.

So here's the js file: adddomloadevent.js, and here's the actual code:

/*
 * (c)2006 Jesse Skinner/Dean Edwards/Matthias Miller/John Resig
 * Special thanks to Dan Webb's domready.js Prototype extension
 * and Simon Willison's addLoadEvent
 *
 * For more info, see:
 * http://www.thefutureoftheweb.com/blog/adddomloadevent
 * http://dean.edwards.name/weblog/2006/06/again/
 * http://www.vivabit.com/bollocks/2006/06/21/a-dom-ready-extension-for-prototype
 * http://simon.incutio.com/archive/2004/05/26/addLoadEvent
 * 
 *
 * To use: call addDOMLoadEvent one or more times with functions, ie:
 *
 *    function something() {
 *       // do something
 *    }
 *    addDOMLoadEvent(something);
 *
 *    addDOMLoadEvent(function() {
 *        // do other stuff
 *    });
 *
 */
 
addDOMLoadEvent = (function(){
    // create event function stack
    var load_events = [],
        load_timer,
        script,
        done,
        exec,
        old_onload,
        init = function () {
            done = true;

            // kill the timer
            clearInterval(load_timer);

            // execute each function in the stack in the order they were added
            while (exec = load_events.shift())
                exec();

            if (script) script.onreadystatechange = '';
        };

    return function (func) {
        // if the init function was already ran, just run this function now and stop
        if (done) return func();

        if (!load_events[0]) {
            // for Mozilla/Opera9
            if (document.addEventListener)
                document.addEventListener("DOMContentLoaded", init, false);

            // for Internet Explorer
            /*@cc_on @*/
            /*@if (@_win32)
                document.write("<script id=__ie_onload defer src=//0><\/scr"+"ipt>");
                script = document.getElementById("__ie_onload");
                script.onreadystatechange = function() {
                    if (this.readyState == "complete")
                        init(); // call the onload handler
                };
            /*@end @*/

            // for Safari
            if (/WebKit/i.test(navigator.userAgent)) { // sniff
                load_timer = setInterval(function() {
                    if (/loaded|complete/.test(document.readyState))
                        init(); // call the onload handler
                }, 10);
            }

            // for other browsers set the window.onload, but also execute the old window.onload
            old_onload = window.onload;
            window.onload = function() {
                init();
                if (old_onload) old_onload();
            };
        }

        load_events.push(func);
    }
})();

Update: I added a demo page, as well as a compressed version (only 876 bytes).

Update: Thanks to Adam Schlag's suggestion, I fixed the memory leak in IE.

Update: Thanks again to Rob Cherny and Alistair Potts, I've updated the solution so that it works over HTTPS without any security issues. I also decreased the compressed size to 761 bytes. Now it's perfect! (I hope!)

Update: I've gone back and reworked the code to get rid of the global variables, and I've managed to reduce the compressed size to 563 bytes!

Update [Aug. 19, 2007]: Now the script preserves any existing window.onload function, and also executes functions instantly when called after the page has already loaded. But now the compressed version is a hefty 617 bytes.

Published on June 21st, 2006. © Jesse Skinner

This site is now XHTML 1.0

I just did some interesting reading that made me rethink the purpose of the different versions of HTML.

One of the first things I did when I launched this site was work to convert it to valid XHTML 1.1. I was excited about the potential of HTML served as XML, and I saw the doctype of my site as a vote towards moving forward. The more sites that start serving XHTML, the faster browsers will support it, right?

Well that might be true, but the fact is, we're not there yet. As I've mentioned before, this is required for delivering XML applications, even XHTML. The problem is, Internet Explorer just doesn't support the application/xhtml+xml mime type.

Previously, I used a workaround to send XHTML 1.1 to browsers that could support it (ie. Firefox), and XHTML 1.0 to browsers that couldn't. This is what I've done for the past year.

Today, I read on the Mozilla website, in the Web Developer FAQ:

... if you are using the usual HTML features (no MathML) and are serving your content as text/html to other browsers, there is no need to serve application/xhtml+xml to Mozilla. In fact, doing so would deprive the Mozilla users of incremental display, because incremental loading of XML documents has not been implemented yet. Serving valid HTML 4.01 as text/html ensures the widest browser and search engine support.

Geez, I thought, what have I done? I tried to make things better for Firefox users, but really I just made things slower.

There are lots of benefits to serving HTML as XML. The thing is, the browsers do a better job just working with HTML at the moment, so if you don't require the benefits of XML, you're better off sticking with HTML.

I read another article, Sending XHTML as text/html Considered Harmful. So let's get this straight: it's harmful to send XHTML as either text/html or application/xhtml+xml. Since these are our only two choices, this means it's harmful to use XHTML! Since the browsers don't properly support XHTML, there's no tangible benefit yet to using XHTML instead of just HTML 4.01 strict.

One day there will be a reason to move forward and start using XHTML in all its glory. Many of us have been trying to make this a reality as soon as possible. Okay, it's a nice idea to start using XHTML 1.0 so that the transition in the future will be as smooth as possible. But beyond that, beyond looking into the future, there's no sense in changing what we're doing today. If a version of Internet Explorer ever comes out (8? 9? 15?) that really supports XHTML, then things might change.

Anyway, long story short, this web site is now XHTML 1.0, and I'm considering just going back to HTML 4.01 strict.

Published on June 20th, 2006. © Jesse Skinner

File formats of the future

After reading Tantek write about file formats, I've been thinking about what will happen to file formats in decades or centuries from now. Tantek says,

"I feel quite confident storing files in the following formats: ASCII / "plain text" / .txt / (UTF8 only if necessary), mbox, (X)HTML, JPEG, PNG, WAV, MP3, MPEG"

I agree, for the short term. But will JPEG be around in a hundred years? What about MP3?

I think we can make some assumptions about the future. For example, disk space will continue to grow and get cheaper, and bandwidth will get faster and cheaper as well. This leads me to think that compressed lossy formats will disappear. Why store in a JPEG when a PNG or even RAW format will do? Why store in MP3 when a WAV will do?

Okay, I don't think we will necessarily store in the least compressed format. I think we will use a format which uses lossless compression, so that the sound/image doesn't change at all. It won't make sense to lose quality to gain disk space anymore.

What about HTML? Oh, I don't know. This is a big question. The web is very new and it's not clear the direction it's moving in. We are using HTML, CSS and JavaScript in ways it was never intended to create desktop-style applications. I think application markup languages like XUL, XAML or even HTML 5 will take off where HTML leaves off, and we'll have no reason to continue abusing HTML the way we have been.

For hyperlinked documents, I believe (X)HTML will stay around for a very, very long time. CSS can grow and change and add display functionality on top of HTML. Put does HTML need to change? Do we need anything more than headers and paragraphs, with span or div tags together with classes to accomplish anything not built into HTML? I don't believe so.

It will be interesting to watch formats and standards evolve over the coming years and decades. I think one day, people will look back at these times with a smile on their faces, enjoying our naivety in these early years as we try to figure everything out.

Published on June 19th, 2006. © Jesse Skinner

Carnival of the Web #1

Welcome to the first monthly Carnival of the Web. Below you'll find some of the best posts from the past month in the web professional blogosphere.

The next Carnival of the Web will be posted on Sunday, July 23rd. If you write about web design or development and want to contribute something over the next month, feel free to submit your blog posts.

The infamous Roger Johansson of 456 Berea Street reminds us to Use Ajax scripting responsibly. Be sure to check out the comments to discover just how intense (and long) comments can get.

Mike Papageorge of the ever popular Fiftyfoureleven suggests some very clever and not-so-obvious ways to optimize the load time of a web site in Reducing HTTP Requests.

Andy Hume at Bite Size Standards knows that Understanding "Any order columns" is difficult. In this wonderful tutorial, he explains why the order of columns in HTML can be different from their order on the screen using CSS.

Emil Stenström, web developer extraordinaire at Friendly Bit helps us remember where we've come from, the mistakes we've made and why it's taken us so long to start using standards again. See why Real hackers don't use CSS.

Dustin Diaz takes a different side in the ongoing debate and answers the question Why inline styles with strict doctypes?

Joe Kissell of Interesting Thing of the Day explains just what is so interesting about Cascading Style Sheets in the first place, with Cascading Style Sheets / Bringing sanity back to Web design.

At RotorBlog, Maris does a side-by-side user interface comparison of two similar personal web portals in Netvibes vs. Pageflakes - design and basic functions.

Artem points us over to Solution Watch to check out a review of something that should keep you distracted from work Up for Ajax Battleship? Play Sink My Ship.

Ohad of Ohad's Internet News offers a new way of writing blog posts that is an ongoing process reacting to user feedback in Evolutionary posts.

Craig at gridbuzz goes below the headlines on the Net Neutrality issue to explain What Net Neutrality is really all about.

Jon Swift takes a look at his recent Google Searches and realises that if the government is watching him, they're going to be in for a surprise.

And last but not least, Chris Quimby shares a humorous tale of helping his mother onto the information superhighway with Throwing Mom on the Highway.

Published on June 18th, 2006. © Jesse Skinner
<< older posts newer posts >> All posts