Recently in javascript Category

Method Chaining Part 2

The comments on my last post about method chaining in JavaScript were spectacular, and I want to publicly thank all who took the time to read my code and think about it. The final version of the code (which you can see below the fold) is much stronger thanks to their comments.

In the 5th edition of my JavaScript book I made the embarrassing mistake of recommending a constructor and method chaining technique that only works for shallow class hierarchies--it works when class B extends A, for example, but not when C extends B and B extends A.

The technique I recommended was to put a superclass property in the prototype object of a class, and then to chain to a superclass constructor by calling this.superclass(). To see why this fails, imagine that we're creating an instance of class C (which extends B which extends A). The constructor C() chains to B() by calling this.superclass(). The constructor method B() is invoked on the same instance of C, however, so when it attempts to chain to A() by calling this.superclass(), it just ends up invoking itself. This incorrect chaining technique is discussed in sections 9.5.1 and 9.5.2, and is also used in example 9-10 and 9-11 at the very end of the chapter. I blogged about this mistake and a possible workaround almost two years ago.

Now, however, O'Reilly is preparing to do a reprint of the book, and I have an opportunity to fix this mistake. Below is a revised code from examples 9-10 and 9-11. I've renamed the defineClass() method to Class() and have modified it so that it automatically does constructor chaining (I was inspired by dojo for this change). More importantly, I've simplified method chaining by defining a global method named chain() for method chaining. If a method overrides a method defined by a superclass (or a "mixin" class) it can invoke that overridden class by invoking chain() like this: chain(this,arguments). (The second argument must be the arguments array of the overriding method, and the first argument must be the object on which that method was invoked.)

The code is below the fold. I think this is interesting JavaScript, and I'd love to have it checked for errors before it goes into print again... Please leave a comment if you think it could be improved! Update: comments are now closed; spammers have struck.

Dashed lines in the <canvas> tag

| 1 Comment

The <canvas> tag supports all of the normal line attributes (width, join style, cap style, miter limit) except for dashes. Given that Apple's original implementation of <canvas> seemed a little bit rushed, I have always assumed that this was a simple oversight, and that it would soon be corrected in newer implementations.

I did, however, submit a comment about it to WHAT-WG. I was quite surprised to find out that they have no intention of supporting dashed lines. I've argued and argued with Ian Hickson about this, but he is unmoved. Supporting dashed lines would be non-trivial, he believes, and there haven't been enough requests for them.

So, this post is a public service announcement. If you were assuming, as I did, that dashed lines would be supported by the official specification of the <canvas> tag, you should be aware that they will not be. If, like me, you think that it is a mistake to define a graphics library that cannot natively draw dashed lines, then you can submit a comment to that effect to whatwg@whatwg.org.

More on IE and window.event

| 6 Comments

Julien Royer sent me an email today following up on this post. Try the following code in IE:

<script>
window.onload = function() {
  alert(window.event == window.event)
}
</script>

When I run this in IE6 on a Windows XP machine, I get false. This is just weird. The window.event object thinks that it is not equal to itself.

This probably does not have any impact on real-world code. I bring it up, however, because in that last post about IE and events, my commenters and I decided that the event object passed to an event handler registered with attachEvent is not the same as window.event. The code shown here calls that into question. Perhaps they are the same objects, but the weird behavior of window.event causes them to appear unequal.

In the 5th edition of my book, I propose a convention for constructor chaining:

  • When you define a class B as a subclass of A, set B.prototype.superclass=A
  • Then, in the constructor B(), you can chain to the superclass constructor with the natural syntax this.superclass()

Reader Bruce Wallace has just pointed out a serious flaw in this approach: you can only use it once. If you use this trick twice in the same inheritance hierarchy, you end up with infinite recursion. (If you don't see why, you can try to work out an example that includes C as a subclass of B. Or just forget it, since I think I have a better approach below.)

I'm feeling pretty embarassed to have suggested this defective method of chaining, and to have committed my suggestion to print! However, I hope to make up for it by proposing a better alternative. Here is my new convention:

  • First, define the following function:
    function super(o, args) {
        if (args.callee.superclass)
    	return args.callee.superclass.apply(o, args);
    }
    
  • For each constructor B that subclasses A, set B.superclass=A;
  • Do the same thing if a method of B overrides a method of A. For example:
    B.prototype.toString.superclass = A.prototype.toString;
    
  • In the B() constructor, chain to your superclass constructor like this:
    super(this, arguments)
    
  • And in a method like B.toString(), chain to A.toString() with exactly the same syntax.

This works because arguments.callee is the function that is currently running. Note that this chaining convention passes all the arguments of the subclass constructor or method to the superclass constructor or method, even if some of them are unused. So it won't work if a subclass constructor expects its arguments in a different order than the superclass constructor.

Note that the work of setting the superclass property on constructors and methods can be done by a suitable class definition utility method (such as example 9-10) in my book. This means that when writing your constructors and methods, you don't have to worry about linking the chain together; you can just call the super() method whenever you want to.

Anyone see any flaws in this approach? Comments? Suggestions? There is a simple test case defining a class hierarchy C extends B extends A below, but I haven't tried to test this extensively yet, and I''ve only run it in Firefox. Firefox is letting me use the function name "super" even though that is one of the identifiers that is unused but nominally reserved by ECMAScript v3. I choose super because Java uses that, but "chain" would probably be a safer choice.

Here is my test code:

// Magic constructor and method chaining function
function super(o, args) {
    if (args.callee.superclass)
	return args.callee.superclass.apply(o, args);
}

// Class A
function A(a) { this.a = a; }
A.prototype.toString = function() { return this.a + "" };

// Subclass B
function B(a, b) {
    super(this, arguments);
    this.b = b;
};
B.superclass = A;
B.prototype = new A();
B.prototype.toString = function() {
    return super(this, arguments) + this.b;
};
B.prototype.toString.superclass = A.prototype.toString;

// Sub-subclass C
function C(a,b,c) {
    super(this, arguments);
    this.c = c;
}
C.superclass = B;
C.prototype = new B();
C.prototype.toString = function() {
    return super(this, arguments) + this.c;
}
C.prototype.toString.superclass = B.prototype.toString;

// Create an instance of C and call toString() should display "123"
var c = new C(1, 2, 3)
alert(c.toString());

Nifty DOM output stream class

| 7 Comments

I was porting some JavaScript code that used the TrimPath template library. The templating system was too much for my needs, so I came up with the simple little class below. It simulates a Java-style output stream. Pass the id of a DOM element to the constructor to get started. Call the clear() method first, if necessary. Then call the write() method as many times as needed. Finally, always remember to call flush() to force your output to appear.

// A little class for outputting HTML into a DOM element
function DOMStream(id) {
    this.elt = document.getElementById(id);
    this.buffer = [];
}
DOMStream.prototype.clear = function() { this.elt.innerHTML = ""; };
DOMStream.prototype.write = function() {
    for(var i = 0; i < arguments.length; i++) this.buffer.push(arguments[i]);
};
DOMStream.prototype.flush = function() {
    this.elt.innerHTML += this.buffer.join("");
    this.buffer.length = 0;
};

If it is not obvious, an important point of this class it to avoid inefficient repeated string concatenation. This is why it uses an array as a buffer, and why the write() method accepts multiple arguments--so you don't have to concatenate them yourself.

Here's a sample usage:

var out = new DOMStream("placeholder");
out.write('<h2>', section_title, '</h2>');
outputTable(out, data);  // Function defined elsewhere
out.flush();

With this class defined, I ported the trimpath template to equivalent JavaScript functions, and ended up with a modest reduction in the number of lines of code (not counting the substantial reduction in lines of code I got by no longer using the templating library.)

Notable New JavaScript Books

The 5th edition of my book was not the only notable JavaScript book released this summer. I'd like to draw your attention to these two as well:

The authors of these two books, Christian Heilmann and Peter-Paul Koch, were kind enough to serve as technical reviewers on my book, and were also kind enough to send me copies of their own books.

I cannot actually review their books, however, since I have not had the time to read them. Nevertheless, the author's reputations speak well for the books. Both Christian and Peter-Paul are active web developers, members of the DOM Scripting Task Force (of the Web Standards Project) and advocates for unobtrusive scripting, accessibility, and other modern scripting practices.

Neither of these books aims to be "definitive" in the way mine does, but both are written by authors who have a lot of valuable experience with todays best practices. Since I haven't read the books myself, I can't tell you whether they share that experience effectively in these books. But I hold the authors in high esteem and want others to be aware of their work.

Rhino cover in Weird Al Music Video

| 1 Comment

Musician Weird Al Yankovic has released a music video for his song "White and Nerdy". The cover of my JavaScript book appears in it. (I can't tell if its the fifth edition, though.)

You can find the video at the musician's MySpace site, and also by searching YouTube.

The JavaScript reference is 1 minute 14 seconds into the video.

What's New in the 5th Edition

| 2 Comments

At another blog I saw someone comment that they'd been looking for a list of what is new in the 5th edition of JavaScript: The Definitive Guide. I guess I haven't blogged about this yet. If you were looking at the book in a bookstore, you'd just turn to the Preface and read the section titled "What's New in the Fifth Edition". But if you're considering an online purchase, you can't do that. So, here's what I say about the new edition in the preface:

Book Metrics: 1 kilopage

| 3 Comments

In yesterday's post, I promised to stop plugging my new book. But I've got a copy in my hands now, and I just can't stop myself. This post will contain only trivia, without links or exhortations to BUY IT NOW!

The first thing I noticed about 5th edition is that it is thinner than the 4th edition. Apparently it is printed on thinner (also noticeably whiter) paper than the 4th edition. Rest assured, however, that this new edition is longer (and better) than the old. The 5th edition is 10% longer (in page count). It has 92% more examples (125 examples instead of 65) and the new examples are 169% longer (lines of code) than the old ones.

But here's my favorite fact about the 5th edition: if you count the regular numbered pages, the roman-numeral preface pages, and the unnumbered filler pages at the back, the book is exactly 1024 pages long. One kilopage: I couldn't be prouder!

The 5th edition of my JavaScript book is finally shipping! (From amazon.com, anyway. Amazon.ca and amazon.co.uk don't seem to have it yet.) Interested?

  1. Read a sample chapter.
  2. Study the examples.
  3. Order it from Amazon: see the ad in the left column.

I think this is the last time I'll plug my book on this blog!

Sample Chapter: JavaScript and XML

| 3 Comments

O'Reilly has posted a PDF file of Chapter 21, JavaScript and XML, from my book

This chapter shows you how create, load, parse, serialize, transform and search XML documents using JavaScript. It includes a portable HTML templating system like IE's data island stuff.

Examples for this chapter, and all chapters of the book are also available.

I'm told that the book will be in bookstores by the end of the month. And you can pre-order it from Amazon today:

JavaScript Examples

| 5 Comments

My JavaScript book has been sent to the printer! I'm told it should be in bookstores by the end of the month. You can always pre-order it, though:

Meanwhile, you can get your hands on the examples from the book now.

10 Years of JavaScript

| 1 Comment

I just had the chance to review the copyright page of the 5th edition of my JavaScript book and noticed that its publication date (August, 2006) is exactly 10 years after the August, 1996 publication date of the first, "beta" edition of the book.

Thus inspired, I put together the following timeline of the JavaScript language, the client-side DOM, and of JavaScript: The Definitive Guide. I'm sure it is incomplete: additions in the comments are very welcome.

1996 March

JavaScript 1.0 released in Netscape 2.
document.write() and form manipulation are possible

1996 August

JavaScript: The Definitive Guide beta edition

1996 August

JavaScript 1.1 released in Netscape 3.
Adds array support to the core language.
Image rollovers become possible.

1996 August

IE 3 released: JScript 1.0/2.0

1997 January

JavaScript: The Definitive Guide second edition

1997 June

ECMAScript v1 standardized

1997 June

JavaScript 1.2 released in Netscape 4.
Adds switch and regexps to the language.
<layer> tag supports rudimentary DHTML

1997 October

IE 4 released: JScript 3.0
DOM based on document.all[] allows DHTML

1998 June

JavaScript: The Definitive Guide third edition

1998 June

ECMAScript v2 standardized (minor corrections only)

1998 October

JavaScript 1.3 released in Netscape 4.5.
Compliant with ECMAScript v1

1998 October

W3C publishes DOM Level 1 standard

1999 March

IE 5 released: JScript 5.0

1999 December

ECMAScript v3 standardized

2000 July

IE 5.5 released: JScript 5.5
partial support for W3C DOM

2000 November

JavaScript 1.5 released in Netscape 6.
Compliant with ECMAScript v3
Basic support for DOM, <layer> tag abandoned

2000 November

W3C publishes DOM Level 2 standard

2001 October

IE 6.0 released: JScript 5.5
substantial support for W3C DOM, except Events module

2002 January

JavaScript: The Definitive Guide fourth edition

2002 June

Mozilla 1.0 released

2004 November

Firefox 1.0 released

2005 February

Jesse James Garrett coins the term Ajax

2005 July

DOM Scripting Task Force forms,
publishes The JavaScript Manifesto

2006 August

JavaScript: The Definitive Guide fifth edition

Two final notes. First, Amazon is still saying that they'll be shipping copies of the book around August 1st. I can say for sure that the book won't be ready by the beginning of August. I don't actually know much about the printing process, but it seems reasonable to suppose that the book will be available later in August.

Second, I've lost my only copy of the 10-year old Beta edition of my book. If you have a copy, in reasonable condition, with the word "BETA" stamped across the rhino, and are would like to swap it for a brand-new copy (signed, if you want) of the 5th edition, send me an e-mail and we'll arrange a trade.

Update: comments closed. Comment spammers have discovered this entry.

Jitsu: new framework for web apps

| 3 Comments

Jitsu is a new web application framework. They call themselves "a next-generation user interface toolkit for building rich web applications"

Jitsu was developed by ATTAP, but has been open-sourced. The website is slick, and there is a well-written tutorial. Its a complete application framework, not something you can just add onto an application, so you really have to adopt it from the start. But its got a lot of nice features, and particularly strong bi-directional data-binding capabilities.

I haven't actually used it myself, but it looks very promising.

New Edition of my JavaScript Book!

| 5 Comments

At long last, the 5th edition of JavaScript: The Definitive Guide is complete! Amazon is accepting pre-orders, and O'Reilly should be releasing a sample chapter soon.

I'm pleased with how this edition came out. In Part I, which covers the core language, the material on functions, closures, and classes has been strengthened, and there are new chapters on namespaces and on embedding JavaScript in Java 6 programs.

The biggest changes are in Part II of the book, which covers client-side JavaScript. Two new chapters on scripted HTTP and XML processing cover Ajax. Another new chapter on scripted client-side graphics covers the <canvas> tag, SVG, and alternatives. The chapter on cookies has been extended to discuss other client-side persistance mechanisms. And the chapter on scripting Java applets has been extended to also cover scripting Flash movies.

All these changes should bring the book up-to-date for "Web 2.0"

When are document elements available to scripts?

| 9 Comments

As far as I can tell, the DOM and HTML specifications are silient on the issue of when DOM elements become available to scripts embedded within the document. That is, if you have an element <div id="foo">, when can you call getElementById('foo') and be sure that you'll get a valid result?

To be safe, we typically wait for the onload() event. (Although the specifications don't explicitly guarantee that, either.) It appears to be common practice for browser vendors to make the DOM available while it is being parsed. That is, any script in the body of a document can access any elements that appear before it in the document.

Can anyone with more knowledge of the specifications, or with more experience writing production code comment on this issue?

This is, of course, related to the "onload problem" which Dean Edwards purports to have solved. In the comments to that post, Dean asserts that placing scripts at the very end of the body does not guarantee that those scripts will have access to the whole document. Dean's experience carries a lot of weight, but he does actually have code that demonstrates that this technique is unreliable.)

Comments are open.

Flash Persistence: one more try

| 4 Comments

[Update: this may be a false alarm. See how I resolved the problem.]

I'm still trying to find a workaround to the Flash persistence security hole that opens up when you script your flash movies from JavaScript.

What I want to try now is to code my ActionScript so that it compares the URL of the Flash movie of which it is a part (something like _root.movieClip._url) to the URL of the web page in which the movie is embedded. If they are not the same, then the actionscript knows that it is being hotlinked, and can refuse to return any persistent data.

My problem is that I don't know the ActionScript programming environment or API well, and I can't find a way to find the URL of the document in which the movie is embedded. It seems like there ought to be a way, but I don't know...

Anyone know how to do it?

More on the Flash Persistence Security Hole

| 5 Comments

[Update: this may be a false alarm. See how I resolved the problem.]

I've been looking for a way to work around the security hole in the flash persistence mechanism that I described in the previous post.

Since the hole occurs when one site hotlinks a Flash movie on another site, it seemed to me that the obvious solution would be to prevent hotlinking. So I set up a .htaccess file using the Apache mod_rewrite module and the HTTP_REFERER header. It worked: offsite links to the SWF file were prevented.

But this wasn't good enough. I didn't take caching into account. Suppose user has just visisted Site A, and that site uses a scriptable Flash movie to store persistent data locally. The user then visits Site B, which is the malicious one. Site B hotlnks the movie on Site A and scripts it to gain read access to the persistent data. My .htaccess file on the server was supposed to prevent this kind of hotlinking. But the server never gets involved: Site B doesn't need to ask the Site A server to send it the movie: the movie is already in the browser's cache, and Site B can read Site A's persistent data with no trouble.

Anyone have a solution to this problem? I'm ready to give up and declare that Flash-based persistence is only good as a cache for information that is already publically available on the network.

And as a meandering aside, let me say that there are some interesting uses of it there. I gather that XMLHttpRequest bypasses the browser cache, at least in certain browsers. Flash persistence could be used to create a persistent cache for XMLHttpRequest. This might be useful for a web site that had a bunch of pages that all did XSLT using the same stylesheet, which was retrieved with XMLHttpRequest.

Adam Vandenberg has an XMLHttpRequest caching solution but the cache only persists for the lifetime of the current page. Flash persistence might be an interesting addition to his caching code. (Of course, we'd have to confirm that this Flash security hole only gives read access to the cached data; otherwise any website could corrupt the Flash cache of any other.)

Security Flaw in Flash-based Persistence

| 4 Comments

[Update: this may be a false alarm. See how I resolved the problem.]

Inspired by Brad Neuberg's AMASS project, I've been experimenting with using the Flash plugin as a client-side persistence mechanism, as an alternative to cookies. It allows the storage of much more data, and that data doesn't have to be uploaded to the server for every webpage that uses it. This seems important, and projects like AMASS seem like they have breakthrough potential.

However, I've discovered something I'm worried about. Persistence in Flash is done with the SharedObject class. By default persistent data is not shared among Flash movies: it is only accessible to the movie that stored it. SharedObject has a way to loosen this up, like the path attribute of a cookie. You can specify that all Flash movies in the same directory can share persistent data, for example. Or you can specify that all Flash movies from the same website can share data.

This may be fine when the data is locked inside the Flash movies. But when Flash movies are scriptable, we run into problems. Both AMASS and my own experiments with Flash-based persistence use a simple invisible movie to make the necessary calls to the SharedObject. Both script the Flash plugin with JavaScript so that we can persist client-side JavaScript data.

And this is where the problems arise. Flash governs access to the data based on the URL of the movie; it doesn't seem to care about the URL of the document within which the movie is embedded. Suppose, therefore, that Site A uses a scriptable Flash movie to persistently store some data from JavaScript. Site B can hotlink that scriptable movie right off of Site A, and the JavaScript code on Site B can read the data stored by the JavaScript code on Site A. (In my experiments, Site B cannot overwrite or delete the data stored by Site A, but it can read it.)

My testing was done using Firefox 1.0.6 using the Linux version of the Flash player 7.0 r25.

Update:I have now obtained the same results using Firefox 1.02 and Flash version 8 on a Windows machine.

I think this is a problem. I suspect that it is a big problem and that Macromedia needs to fix it. I'm only beginning to dabble in Flash and just learning about how to script Flash movies. I don't know if this security problem will affect movies that use SharedObject but do not explicitly open themselves up to scripting of that SharedObject. It could be that if you play a Flash-based game at Site C, site D could figure out a way to read your high score in that game.

Your thoughts are welcome in the comments, especially if you understand Flash and Flash scripting better than I do!

Client side sparkline images

| 2 Comments

Sparklines are a new graphical concept championed by Edward Tufte, author of a number of very cool books that you have probably already heard about. Sparklines are an idea from his forthcoming book, and he explains them in a draft chapter from that forthcoming book at sparklines.org.

If you're using a browser that understands the data: URL, here's an example of a sparkline:

Server load: 16.

Note, that this particular sparkline is hard-coded in this blog entry. The demos below show how they are dynamically generated.

As part of my newfound obsession with client-side drawing techniques (I really think it could change the web) I've created a way to generate sparkline images using client-side Java and JavaScript. This is proof-of-concept stage, but if you're running Firefox and have the Java plugin installed, click on these links to try out the demos:

  • spark.html: this demo uses LiveConnect to script Java directly. It does not use an applet at all. This means it will not work in IE. I don't know about other browsers' support for this kind of direct scripting of Java classes. This demo returns a PNG image encoded in a data: URL. This also means it won't work in IE, since IE does not support the data: scheme.
  • spark2.html: this demo uses a SparklineGenerator applet to create the PNG image, which it returns as a javascript: URL. This is supposed to be for compatibility with IE, but it still doesn't work in that browser for me. It could probably be made to work somehow... This demo also moves toward an unobtrusive JavaScript technique in which sparklines are coded with a new <sparkline> tag, which gets replaced by the image after document load by JavaScript and the applet.

You'll need to understand both Java and JavaScript to make use of this stuff. But if it interests you, you can use my code for any purpose as long as you attribute it to me.

Flash for client-side vector graphics!

| 7 Comments

In my previous entry, I asked about the possiblity of using Flash as a vector graphics engine, for scripting by client-side JavaScript code. With help from Geoff Stearns and his blog Deconcept I've figured out how to do it.

I've figured out how to do it in Flash 8, at least. Flash 8 has a new ExternalInterface API that transparently makes ActionScript methods callable from JavaScript. (It is possible, though not nearly so simple to do similar things in earlier versions of Flash.) Here is my trivial ActionScript file, which I named Canvas.as:

import flash.external.ExternalInterface;

class Canvas {
    static function main() {
        Stage.scaleMode = "noScale";
        Stage.align = "TL";
        ExternalInterface.addCallback("beginFill", _root, _root.beginFill);
        ExternalInterface.addCallback("beginGradientFill", _root,
                                      _root.beginGradientFill);
        ExternalInterface.addCallback("clear", _root, _root.clear);
        ExternalInterface.addCallback("curveTo", _root, _root.curveTo);
        ExternalInterface.addCallback("endFill", _root, _root.endFill);
        ExternalInterface.addCallback("lineTo", _root, _root.lineTo);
        ExternalInterface.addCallback("lineStyle", _root, _root.lineStyle);
        ExternalInterface.addCallback("moveTo", _root, _root.moveTo);
    }
}

I compiled this code with the open-source mtasc ActionScript compiler like this:

mtasc -swf Canvas.swf -main -version 8 Canvas.as

This produced the file Canvas.swf which you can download by clicking the link.

The ActionScript code doesn't do anything except make the Flash drawing API accesible to JavaScript. If you embed this SWF file in your web page, it is simply blank, until you draw something to it yourself. Here is a demo:

<embed src="Canvas.swf" quality=high bgcolor=#FFFFFF width="400" height="200"
name="canvas" align="" type="application/x-shockwave-flash"
pluginspage="http://www.macromedia.com/go/getflashplayer">

<p><button onclick="draw()">Draw in the Canvas</button>
<script>
function draw() {
    document.canvas.beginFill(0xAAAAFF, 100);
    document.canvas.lineStyle(5, 0x0000FF, 100);
    document.canvas.moveTo (10, 10);
    document.canvas.lineTo (200, 100);
    document.canvas.lineTo (10, 190);
    document.canvas.lineTo (10, 10);
    document.canvas.endFill();
}
</script>

This demo uses the <embed> tag instead of the <object> tag, so it won't run in IE. But I have tested it in Firefox, and it works. But only if you have Flash 8 installed. And Flash 8 is not available for Linux yet. If you've got Flash 8 running in Firefox (or Safari?) give the demo a try!

Comments, suggestions, improvements, or whatever are very welcome. I plan to tweak Canvas.as a bit to expose methods for adding text, but I think that will be straightforward. I was disappointed to discover that the Flash drawing API is not nearly as robust as that of the <canvas> tag or of SVG of VML. In particular all curves must be done with quadratic beziers. Cubic beziers, circles, arcs and so on must all be approximated with a single curveTo() function. So it might be worth adding some basic shape-drawing primitives (circles, rounded rectangles, etc) to Canvas.as as well.

Feel free to use this code (and the swf file) for any purpose, with attribution.

Flash for client-side vector graphics?

| 6 Comments

I know very little about Flash, but it seems to me that it would make a good substitute for the <canvas> tag as well as SVG and VML. From a basic perusal of the Macromedia web site, it appears that it is possible for client-side JavaScript to communicate with the ActionScript interpreter in the Flash plugin. If so, JavaScript ought to be able to get ActionScript to draw lines, curves, and do other vector-graphics type things.

ActionScript has an eval() function. I would think that it would be possible to create a tiny SWF file that does nothing more than define a hidden TextField object and an onChanged event listener for that field. The event listener would take the new value of the TextField and pass it to eval(). Client-side JavaScript would then set the value of the TextField with the TSetProperty method that is exported by the Flash player. And voila! Client-side JavaScript can then make pass arbitrary ActionScript commands to the Flash Player. This gives us scriptable client-side vector graphics that work anywhere Flash is installed.

Can anyone tell me why this wouldn't work? Is anyone already doing it? If you make this work and release your code openly, you'll get a link and an attribution in the next edition of my JavaScript book!

Canvas tag in Java and XBL

| 6 Comments

I think 2D graphics are a lot of fun, and have always loved the Java2D API. How cool is it, then, that Safari includes and Firefox 1.5 will include a new <canvas> tag that exposes a drawing API very, very similar to the Java2D API?

The canvas tag has the potential to revolutionize a lot of web applications. But for this to happen, it needs to be ported to browsers other than Safari and Firefox 1.5. I'm sure it can be done for IE, somehow, but I don't want to tackle that right now.

Instead, my contribution is to begin implementing the canvas tag for Firefox 1.0 using a Java applet and Mozilla's XBL binding language. This is just at proof-of-concept stage, but it is usable enough to make simple demos work. The java applet and XBL files are here. The canvas.html file in that directory is a simple demo. It doesn't seem to work online, but if you copy the files to a local directory, it should work. (I suspect, but don't know, that XBL bindings have to be installed locally to work for security reasons.)

To use this, compile the .java file to a .class file. Then define a simple stylesheet that tells Firefox to use the canvas.xbl file to implement the canvas tag. This is what I use:

<style>
canvas {
    -moz-binding: url('canvas.xbl#canvas');
    display:block;
}
</style>

Anyone want to take over work on this? You need to know Java and JavaScript, and know more about XBL than I do. And if you know something about whatever IE uses instead of XBL, that would be a big help, too... Drop me a line if you're interested!

XMLHttpRequest with <script> and PHP

| 7 Comments

Here is a very simple XMLHttpRequest utility function:

/**
 * Use XMLHttpRequest to fetch the contents of the specified URL using
 * an HTTP GET request.  When the response arrives, pass it (as plain
 * text) to the specified callback function.
 */
HTTP.getText = function(url, callback) {
    var request = HTTP.newRequest();
    request.onreadystatechange = function() {
	if (request.readyState == 4) {
	    if (request.status == 200) callback(request.responseText);
	}
    }
    request.open("GET", url);
    request.send(null);
};

This function assumes the presence of a HTTP.newRequest() function to abstract away the differences in creating an XMLHttpRequest object in IE and other browsers. (You've seen a function like this in every Ajax utility library you've looked at...)

Since XMLHttpRequest uses ActiveX in IE, it is unavailable if the user has disabled ActiveX for security reasons. In this situation, we can try to fall back on other means of scripting HTTP. Both <iframe> and <script> tags have src attributes that can generate HTTP GET requests when dynamically set. Let's start there and see if we can use these tags to create an analog to the HTTP.getText() method shown above. (Full compatibility with XMLHttpRequest is not possible with these techniques, however.)

The Back Button is not an Undo Button

| 9 Comments

When a web application uses XMLHttpRequest to retreive content for display to the user, no page load occurs, and therefore, the browser's Back button cannot be used to step backwards through the user's browsing history within the application. Much has been made of this Back button problem in Ajax applications. But I'm not convinced that it is anything to worry about.

Maybe usability testers who have worked with Ajax applications can tell me otherwise, but it just doesn't seem that confusing to me. When I zoom a map in Google maps, for exmaple, I simply don't expect the Back button to unzoom it. If I've just clicked the "+" button to increase the magnification of the map, why would I expect a button named "Back" to decrease the magnification? I'm zooming in and out, not back and forward...

One small insight I've had about thi s is that the browser's Back and Forward buttons are not, and should not be, Undo and Redo buttons for web applications. I expect that all but the most inexperienced users have internalized this distinction. Or they will, unless the designers of Ajax applications insist on making Back work like an undo function within their application.

As a corollary, allow me to suggest that wizard-style interactions, with "Next" and "Previous" buttons are not well suited to Ajax applications. Next and Previous are uncomfortably close to Forward and Back, and I think that users of such an application will (and should) reasonably expect that the browser's Back button will perform the same action as the wizard's Previous button. So if you're going for a wizard-style user-interface, skip the Ajax and just do plain old form submissions and page loads so that browser history works okay...

Other than that, I don't think we need to worry about the Back button. But take this advice with a grain of salt. I've performed absolutely no testing with real-world users.

XMLHttpRequest.readyState == 3

| 8 Comments

Microsoft invented the XMLHttpRequest, so they get to document it. Mozilla copies the Microsoft API and their documentation simply links to the Microsoft docs.

Unfortunately the Microsoft docs are lacking... (What is it about MSDN? Does it work better if you view it with IE? Trying to use it with Firefox on a Linux box is a uniformly frustrating experience. Hard to read, and even harder to navigate)

Here's what MSDN has to say about readyState values 2 and 3:

(2) LOADED: The send method has been called, but the status and headers are not yet available.
(3) INTERACTIVE: Some data has been received. Calling the responseBody and responseText properties at this state to obtain partial results will return an error, because status and response headers are not fully available.

The description of state 2 implies that the next state will be the one in which the status code and headers are avaialble. But then the documentation for state 3 just falls apart, saying that the body of the response is not available because the status and headers are not available.

This reads to me like a documentation mistake. In state 3 I would expect status and headers to be available, but I would not expect to be able to query the responseText property.

Has anyone figured out if it is okay to query the response headers in state 3? That is, is this a documentation error? Or does the documentation correctly describe an implementation error?

Update: In comments, Ian Hickson points out that the WhatWG draft spec for XMLHttpRequest addresses this precise question: in readyState 3, responseText should give us all text that has been downloaded so far, and getResponseHeader() and getResponseHeaders() should return any headers that have been downloaded so far. If we can assume that all headers will be in the first IP packet of the response, then those methods should work for readyState 3.

Appending array contents to another array

| 11 Comments

I would have sworn that there was a built in Array function for appending the contents of one array to another array.... But when I went to look it up, I found I was wrong.

Array.concat() concatenates the contents of two arays, but it creates and returns a new array rather than appending to the array on which it is invoked.

Array.push() and Array.splice() modify the array on which they are called, but append the array itself, rather than appending the contents of the array.

There isn't even an append() function in the Array Extras package coming in Firefox 1.5.

Here, therefore, is my solution to this problem:

// Append the elements of the array a to this array
Array.prototype.append = function(a) {
    Array.prototype.push.apply(this, a);
}

Example: using JavaScript in Java

| 2 Comments | 1 TrackBack

Java 6.0 ("Mustang") includes a JavaScript interpreter and a javax.script package for interacting with it. The code below is an example of how it works...

Synthetic tags and unobtrusive JavaScript

| 2 Comments

It occurs to me that it would be a useful convention for any script that creates and adds elements to the document to tag those elements by adding "synthetic" to the class attribute of the element

This way, other scripts that run later can identify elements that were not part of the original document. Some scripts will want to process syntehtic elements along with the originals, but some will want to skip those synthetic elements.

I don't have a compelling example use case to argue for this, but it just seems like as we start writing more and more useful unobtrusive scripts, we'll find that they interact with each other in unexpected ways. I haven't written any greasemonkey scripts myself, but I suspect that a convention like this would be helpful there, too...

Fake Blogs and JavaScript Decoding Challenge

| 5 Comments

If you, like me, use Technorati to find interesting blog entries tagged "javascript", then you've probably noticed in recent days that a site javascript-guide.info (I'm not going to give them a real link; you can type this URL in yourself) has had a lot of posts, but that they titles are kind of gibberish. Looking at the site, it appears to be a fake blog, with content that is some how automatically gleaned from elsewhere on the web. There are lots of ads on each page, so I suspect that this site exists to get Google AdSense clicks...

When I visited, I noticed a persistant "waiting for fueledstudios.com..." message in my browser's status line. So I used view source to find out what it was loading from that site. It turns out that the last think each page of this fake blog does is load a script from fueledstudios.com

This is where the JavaScript Decoding Challenge comes in. Take a look at the script. It is not heavily obfuscated, but whitespace has been stripped out. The name of the script indicates that it is tracking something. A glance at the script shows that it is doing something with the google adsense ads on the page. it also registers event handlers, uses setTimeout() to repeatedly do something, and communicates with its server by dynamically loading images that pass a lot of data in their URL.

This might all be perfectly benign. But I have the feeling that this site is doing something sleazy. It sure would be nice if we could tell Google that this site is violating their AdSense terms-of-service. That might cause the site to shut down and stop spamming Technorati with junk. So, this is the challenge: anyone want to sort out what this script actually does? I'm very curious, but can't spare the time...

Let me know if you figure anything out!

Another practical use for JavaScript closures

| 2 Comments

Vincenzo Alcamo wrote to me with another practical use for closures in JavaScript. Vincenzo is working on a JavaScript library he calls XMLLib, based on the Sarissa library. To prevent his library from cluttering the global namespace, Vinceno defines his symbols in his own XMLLib namespace, of course.

But he goes one step further. In Vincenzo's code, only publically exported methods and properties ever get stored in the XMLLib object. Internal, helper methods that are not intended for public use exist in a closure, where all the public methods can use them but where they are hidden from everyone else.

Schematically, the code looks like this:

// Create an empty namespace
XMLLIB = {}

(function() {  // anonymous function creates a closure for us
    // Thi s is a private method that stays hidden within the closure
    function private_utilty_method() { /* utility code here */ }

    // This method is exported into the XMLLib namespace, so it is a public method
    // But since it is defined here, it can call private methods like the one above.
    XMLLib.publicMethod = function() { /* ... */}
})();  // Close function definition and invoke it all at once

Contrast this approach to private symbols with that taken by JSAN. In that framework, a namespace may contain a mix of public and private symbols. The namespace also declares an array of symbols that should be exported by default, and an array of symbol that are allowed to be exported from the namespace. Any symbols excluded from these arrays are private, and the JSAN exporter functions will not copy them into the global namespace. That is, the JSAN framework does not have true privacy via closures, but defines a convention which, when followed, provides a measure of privacy.

Thanks for the tip, Vincenzo!

Borrowing methods instead of inheriting methods

| 8 Comments

The typical way to create new classes in JavaScript is by subclassing another class to inherit its methods. It occurs to me that this is not the only way. Since functions are data values in JavaScript, it is also possible to extend a class simply by copying methods from another class into it. I call this "borrowing" (although I suspect that someone else has already named it something else--let me know):

The code at the end of this postdemonstrates. It creates a simple Rectangle class. Then another simple class called GenericToString. This second class isn't good for much on its own, but serves as a "mixin" that can be borrowed by other classes. The next bit of code in the example is a function that does the borrowing. This is followed by a new class Rectangle2, which does nothing of its own, just borrows methods from the first two classes.

Update: I should add here that this method borrowing technique can be compared to multiple inheritance. The Rectangle2 class inherits methods from Object and borrows methods from two other classes. If there was a way of writing abstract methods in JavaScript (perhaps just throw "this method is abstract!") then borrowing methods from a class that defined abstract methods would be a little like implementing an interface in Java.

I'm interested in reader's thoughts on this technique. Is anything like this used in other languages? Has anyone given this an official-sounding name?

The code is in the extended entry...

JavaScript Module Conventions?

| 2 Comments

Unobtrusive JavaScript calls for JavaScript code to be removed from our HTML and placed in external .js files. At the same time, JavaScript frameworks and libraries are multiplying like crazy. More and more, we are going to be seeing web pages that load 2, 3, or more external .js files.

This means that we need to become disciplined about how we create those .js files, and adopt namespace conventions for these external modules of code so that two modules do not overwrite each others properties.

As far as I can tell, each JavaScript framework out there does this slightly differently. The most explicitly documented set of conventions I've seen are Casey West's rules for writing modules that work with his JSAN.use() function Casey's use() function is a perl-influenced function that loads (dynamically!) a .js module and then imports a set of symbols from the module into the global namespace. it is good stuff, but his module-structuring and namespace-creating rules are tied directly to his JSAN.use() code and I don't think they are general enough for people who want to write modules to be statically loaded with a <script> tag.. For example. a JSAN module defines the set of symbols that it can export, but the only way to import those symbols is via the use() function. There is not a separate import() function for importing symbols. without using use().

If you know of a well-articulated set of conventions for defining reusable modules of JS code, putting them in namespaces, and importing symbols, please add a comment to this post!

Here is my first cut at a list of requirements for a JavaScript module system:

  1. A .js module must not define more than one symbol in the global namespace. If it does define a symbol, that symbol should probably be the same as, or derived from, its filename.
  2. Any additional symbols defined by a module should be defined within a separate object, or "namespace".
  3. We need a way to selectively import symbols from a namespace into the global namespace. This is for convenience only; the methods deifned by a module should be written to work from their own namespace or from the global namespace.
    1. We could standardize an import() function for doing this importing. Or just create the necessary conventions, so that different frameworks can create their own import() methods.
    2. Modules should probably be allowed (but not required) to declare their own list of exported symbols (as JSAN modules do). And if such a list is defined, the import facility should not allow non-exported symbolsto be imported.
  4. For client-side programming, modules need a safe way to register code to be run in response to the onload event, without worrying that they will overwrite or be overwritten by the initialization code for some other module.
  5. There should be a standard way for a module to declare its name and version number.
  6. There should be a standard way for a module to register itself as loaded, and a standard way for a module to query the list of loaded modules (to verify that any modles it depends on are already present).

Please feel free to add your own ideas in the comments!

What should we call JavaScript pseudo-classes?

| 6 Comments

Like many others, I use the term "class" to informally describe the things we create in JavaScript using constructors and prototype objects. But JavaScript 2.0 is on the horizon, and since that version of the language has real classes, I want to start using a different term to describe JavaScript 1.x pseudo-classes.

Is anyone aware of a pre-existing convention that I can adopt? I've tried using "category" but I think it is too vague. My current feeling is that I should use the hypenated word "proto-type", although if I do this, I need to be careful not to confuse it with "the prototype object" that we use to create a proto-type.

If you have a thought or better suggestion, I'd love to hear about it. Just retaining our current usage of "class" is an option, too, of course.

Find the JavaScript bug

| 3 Comments

Can you spot the bug in the following code?

// Compute the sum of the elements in array a
function sum(a) {
    // Bonus feature: if we're passed more than one argument,
    // then sum the arguments of the array instead.
    if (arguments.length > 1) a = arguments;
    var total = 0;
    for(var i = 0; i < a.length; i++) total += a[i];
    return total;
}

Hint: the function works correctly if you pass an array, but not if invoked with more than one argument.

Answer follows...

Another Useful JavaScript Closure

| 9 Comments

I found another useful example involving closures. Bob Ippolito's python-style iteration framework includes this nifty code:

arrayLikeIterator = function (arrayLike) {
    var i = 0;
    return {
        'next': function () {
            if (i >= arrayLike.length) {
                throw StopIteration;
            }
            return arrayLike[i++];
        }
    };
};

There is lots more to Bob's iteration framework at his blog. The iteration stuff is part of Bob's larger framework, MochiKit, which looks quite interesting.

For the record, I disagree with Bob about throwing an exception at the end of iteration. I tihnk he'd be better of returning a unique sentinel value (but probably not null). His StopIteration error object could work just fine as a sentinel, if he'd return it instead of throwing it.

Update: after exchanging a number of emails with Bob, I now understand that his iterators are python-style iterators, intended to be used as part of a larger framework, and that they are to be treated as opaque values and passed to other functions that do the work of iterating them. That is, the end user of the iterators never has to catch the exception that the iterator throws. Bob has convinced me when an iterator is processed by a chain of composed functions, the use of an exception to end the iterator is the most efficient way to go. So, I drop my objection to throwing an exception to end iteration, as long as you use Bob's iterators in the python-based style he intends.

JavaScript Closures Example

I came up with the code below to demonstrate that two JavaScript closures can have the same scope chain. This gives them shared access to properties that are not accessible from anywhere else.

Here's the code:

//
// This function adds property accessor methods for a property with 
// the specified name to the object o.  The methods are named get<name>
// and set<name>.  If a predicate function is supplied, then the setter
// method uses it to test its argument for validity before storing it.
// If the predicate returns false, then the setter method throws an exception.
// 
// The unusual thing about this function is that the property value 
// that is manipulated by the getter and setter methods is not stored in
// the object o.  Instead, the value is stored only in a local variable
// in this function.  The getter and setter methods are also defined
// locally to this function, and therefore have access to this local variable.
// Note that the value is private to the two accessor methods, and it cannot
// be set or modified except through the setter.
// 
function makeProperty(o, name, predicate) {
    var value;  // This is the property value

    // The setter method simply returns the value
    o["get" + name] = function() { return value; }

    // The getter method stores the value or throws an exception if
    // the predicate rejects the value
    o["set" + name] = function(v) { 
        if (predicate && !predicate(v))
	    throw "set" + name + ": invalid value " + v;	
	else
            value = v;
    }
}

// The following code demonstrates the makeProperty() method 
var o = {};  // here is an empty object

// Add property accessor methods getName and setName()
// Ensure that only string values are allowed
makeProperty(o, "Name", function(x) { return typeof x == "string"; });

o.setName("Frank");  // Set the property value
print(o.getName());  // Get the property value
o.setName(0);        // Try to set a value of the wrong type

This example is simlar to Douglas Crockford's Private Members in JavaScript.

I don't think it is actually that useful in practice--I don't recommend that anyone start calling my makeProperty() function on their own objects! As far as I know, the most realistically useful application of JavaScript closures is Steve Yen's breakpoint() function.

WaSP tackles JavaScript

I've been turning my attention from Java to JavaScript in recent days.

I discovered this morning that the Web Standards Project (or WaSP) has turned its attention to JavaScript, as well. They have recently announced the launch of the DOM Scripting Task Force to promote "unobtrusive" JavaScript programming using the W3C DOM. See the Manifesto and their Definitions. There is not much else at the task force's site yet. Here's an interesting example of unobtrusive JavaScript in action, however.

If WaSP can do for JavaScript programming what they have done for CSS, this is a great thing for the web!

Books

Comprehensive coverage of Ruby 1.8 and 1.9

"The New Most Important Ruby Book"
Peter Cooper,
rubyinside.com

Completely updated for Ajax and Web 2.0

"A must-have reference"
Brendan Eich,
creator of JavaScript

The classic Java quick-reference