Skip to content

Blogs

Using Base64 Canvas Data In jQuery To Create ColdFusion Images

Ben Nadel Ajax and JQuery Feed - 9 hours 17 min ago
Last week, I explored the HTML Canvas element for the first time. In that exploration, I created a "finger painting" demo for the iPhone that would post drawing commands to the server where the image would be re-created as a PNG in ColdFusion. That was a nice approach because it gave me some flexibility in how the ColdFusion image was created (using anti-aliasing and a t ... Read More »
Categories: Blogs

Translating Global jQuery Event Coordinates To A Local Context

Ben Nadel Ajax and JQuery Feed - Tue, 03/09/2010 - 16:31
When you use jQuery to capture mouse events (mousedown, mouseup, click, etc.), the jQuery Event object contains the X and Y coordinates of the mouse position at the time the event was triggered. These coordinates, while somewhat different in each browser, have been standardized by jQuery to be available in the pageX and pageY properties . No matter what the target of the event is, these ... Read More »
Categories: Blogs

Custom events in JavaScript

NCZOnline - Nicholas C. Zakas - Tue, 03/09/2010 - 15:00

Without a doubt, the most often-used paradigm in JavaScript is events. Events are a manifestation of the observer pattern, a well-defined computer science design pattern for loose coupling. Loose coupling is incredibly important for creating maintainable, stable codebases. I talk a lot about loose coupling and its importance in my talk, Scalable JavaScript Application Architecture (video), so I won’t talk too much about it here. However, the concept is very important to grasp if you wish to progress as a software engineer.

Events

Unless you’ve never written any JavaScript before, you’ve used events at some point in time (admittedly, if you’ve never written JavaScript before, the chances of your reading my blog are probably pretty slim). Put quite simply: the way that you tie behavior to web pages is through events. Events are a way of letting interested parties know that an important moment has occurred in the lifecycle of the application. For instance:

window.onload = function(){
    Application.init();
};

In this example, the load event is the interesting moment. I want to know when the window is fully loaded so that I can initialized the JavaScript application. The onload event handler is the location to where an event handler is assigned. The brilliant part is that window doesn’t care what web page is loaded or who is writing the code; it just knows that there’s a function to call when load occurs. This is the essence of loose coupling: when parts of an application have very limited knowledge of one another.

The Browser Object Model (BOM) and Document Object Model (DOM) publish events to allow developers access to the interesting moments of the browser and web page, respectively.

Custom events

It’s no surprise that most JavaScript libraries rely heavily on custom events since this is a pattern that web developers are familiar with. Every major JavaScript library provides its own events, components to enable easy custom event definition, or both. This makes sense, of course, since libraries want to be loosely-coupled to the execution environment, and therefore, to your code.

There’s nothing magic about custom events, though, and there’s no need to load an entire library if you’d like to experiment with custom events. An object that supports custom events needs to be able to do a small set of things:

  1. Assign an event handler for a particular event.
  2. Remove an event handler for a particular event.
  3. Fire an event and call all assigned event handlers.

The following implements all of this basic functionality:

//Copyright (c) 2010 Nicholas C. Zakas. All rights reserved.
//MIT License

function EventTarget(){
    this._listeners = {};
}

EventTarget.prototype = {

    constructor: EventTarget,

    addListener: function(type, listener){
        if (typeof this._listeners[type] == "undefined"){
            this._listeners[type] = [];
        }

        this._listeners[type].push(listener);
    },

    fire: function(event){
        if (typeof event == "string"){
            event = { type: event };
        }
        if (!event.target){
            event.target = this;
        }

        if (!event.type){  //falsy
            throw new Error("Event object missing 'type' property.");
        }

        if (this._listeners[event.type] instanceof Array){
            var listeners = this._listeners[event.type];
            for (var i=0, len=listeners.length; i < len; i++){
                listeners[i].call(this, event);
            }
        }
    },

    removeListener: function(type, listener){
        if (this._listeners[type] instanceof Array){
            var listeners = this._listeners[type];
            for (var i=0, len=listeners.length; i < len; i++){
                if (listeners[i] === listener){
                    listeners.splice(i, 1);
                    break;
                }
            }
        }
    }
};

The EventTarget type has three methods: addListener(), fire(), and removeListener.

The addListener() uses the private _listeners object to store event handlers for various events. When an event handler is added, the method first checks to see if there’s a named property for that event type on the _listeners object, and if not, creates one containing an array. The event handler function is then saved to the array for later.

The fire() method fires an event with a given name. In effect, this method’s only job is to execute each event handler for the given event type. The method accepts either an object, in which case it’s expected to have a type property, or a string, in which case a new object is created and the string is assigned as the value of type. Next, if the event object doesn’t have a target property assigned, it is set to the current instance. This effectively creates an event object similar to the one most are familiar with via the BOM and DOM. Once the event object is created, the _listeners object is checked for event handlers, and if found, they are executed. Note that in order to mimic the BOM/DOM approach, event handlers are executed in the scope of this via the call() method.

The last method, removeListener(), simply reverses the process of addListener(). It searches through the _listeners property for the given event type to locate the specified event handler. If found, the event handler is removed by using the array’s splice() method, and otherwise it exits without doing anything.

Basic usage:

var target = new EventTarget();
function handleEvent(event){
    alert(event.type);
};

target.addListener("foo", handleEvent);
target.fire({ type: "foo" });    //can also do target.fire("foo")
target.removeListener("foo", handleEvent);

Practically speaking, you’ll likely not want to use an instance of EventTarget directly, but rather inherit from it:

function MyObject(){
    EventTarget.call(this);
}

MyObject.prototype = new EventTarget();
MyObject.prototype.constructor = MyObject;
MyObject.prototype.foo = function(){
    this.fire("foo");
};

var o = new MyObject();

o.addListener("foo", function(){
    alert("Foo just happened.");
});

o.foo();

Typically, events are fired in reaction to some other method call, as in this example (events are usually not fired external to the object that is publishing the events).

What about…?

This is a pretty barebones implementation of a custom event providing object, so inevitably someone will come along and ask why I didn’t include one feature or another. There are, of course, a lot of enhancements you can make to custom events if you so desire. Some enhancements others have implemented:

  • Bubbling of events
  • Continue to execute event handlers even if one throws an error
  • Allow event handlers to cancel further processing or default actions

Each of these can be built pretty easily on top of the base presented in this post.

Conclusion

Custom events are a very powerful and useful pattern in JavaScript programming, and your usage of them doesn’t have to rely on a large JavaScript library. Implementing your own custom events is easy. The implementation presented in this post is a minimum feature set that typically fulfills most requirements, but you can consider it as a starting point for more advanced functionality if your requirements are more complex.
Related posts

P.S. My new book, High Performance JavaScript is coming out in early 2010. Need help now? Check out Professional JavaScript, 2nd Edition.

Categories: Blogs

J4D update: My Book, Other Books, Workshops and talks

jQuery for Designers - Remy Sharp - Tue, 03/09/2010 - 15:00
It’s been a while since I’ve been in touch, so I wanted to let you know what’s going on in the jQuery for Designers world, what to look out for and what’s coming next. A personal update I realise I’ve neglected you again (there was a similar dip back in Feb 2009: I see a pattern emerging), [...]
Categories: Blogs

grammar.coffee

Simon Willison’s Weblog - Mon, 03/08/2010 - 21:27

grammar.coffee (via). The annotated grammar for CoffeeScript, a new language that compiles to JavaScript developed by DocumentCloud’s Jeremy Ashkenas. The linked page is generated using Jeremy’s Docco tool for literate programming, also written in CoffeeScript. CoffeeScript itself is implemented in CoffeeScript, using a bootstrap compiler originally written in Ruby.

Categories: Blogs

jQuery Mouse Events: PageX/Y vs. ClientX/Y

Ben Nadel Ajax and JQuery Feed - Mon, 03/08/2010 - 16:19
When I first starting playing with jQuery events, a lot of what I learned about the jQuery Event object was through trial and error. While I could be remembering incorrectly, I used to find that the jQuery documentation was good at describing the event handlers, but not so good at describing the event object; as such, while I knew that the jQuery event object was a standardized event object, I was never 100% sure which parts of it I was supposed to be using. ... Read More »
Categories: Blogs

Memory Barriers article published by InfoQ

Not Dennis Byrne - Sat, 03/06/2010 - 00:14
InfoQ has published an article I wrote about memory barriers and the JVM. Here's an excerpt:

"A trip to main memory costs hundreds of clock cycles on commodity hardware. Processors use caching to decrease the costs of memory latency by orders of magnitude. These caches re-order pending memory operations for the sake of performance. In other words, the reads and writes of a program are not necessarily performed in the order in which they are given to the processor. When data is immutable and/or confined to the scope of one thread these optimizations are harmless. Combining these optimizations with symmetric multi-processing and shared mutable state on the other hand can be a nightmare. A program can behave non-deterministically when memory operations on shared mutable state are re-ordered. It is possible for a thread to write values that become visible to another thread in ways that are inconsistent with the order in which they were written. A properly placed memory barrier prevents this problem by forcing the processor to serialize pending memory operations."

You can read the rest over at InfoQ ...
Categories: Blogs

Drawing On The iPhone Canvas With jQuery And ColdFusion

Ben Nadel Ajax and JQuery Feed - Fri, 03/05/2010 - 15:44
The HTML Canvas element is something that I've known about for a long time but never actually looked at until yesterday. The Canvas element is just what it sounds like - a surface on which we can programmatically render graphics and shapes. After seeing some really cool canvas-based demos floating around on Twitter, I decided that it was finally time to see what this web-2.0 element could do. ... Read More »
Categories: Blogs

Spring 2010 jQuery Talks

John Resig - Blog - Thu, 03/04/2010 - 16:27

I gave a number of talks this spring on jQuery and especially on some of the recent additions made in jQuery 1.4. Below are all the slides and demos that I've given.

The conferences / meetups that I spoke at (or will speak at, in the case of MIX), and the talks that I gave, are as follows:

  • Webstock (Wellington, NZ) (Introduction to jQuery Workshop, Things You Might Not Know About jQuery)
  • Future of Web Apps (Miami, FL) (Introduction to jQuery Workshop, Improve Your Web App with jQuery)
  • jQuery Boston Meetup (Boston, MA) (Things You Might Not Know About jQuery)
  • MIX (Las Vegas, NV) (Improve Your Web App with jQuery)
Introduction to jQuery Workshop

This workshop starts with an introduction to the fundamentals of jQuery (1 hour) and continues on with two pieces of hands-on coding (Todo list, 30 min, Social Networking Site, 1.5 hours).

Introduction to jQuery
Source Code

In the workshop I also had two pieces of hands-on coding. The first was an ajax-y todo list the second was converting a functional social networking site into a one page application (making significant use of jQuery UI).

jQuery Todo List
Source Code Reset Demo Edit Demo

jQuery Social Network
Source Code Reset Demo Edit Demo

Things You Might Not Know About jQuery

A variety of things that people don't know about in jQuery - including new things added in jQuery 1.4 (and newer), data bindings, custom events, and special events.

Things You Might Not Know About jQuery
Source Code

For the first jQuery Boston Meetup I built a game using the avatars of everyone in attendance. Sort of a space shooter style game you need to kick and kill the advancing hordes of users. I used this game as a way of demonstrating constructing an application that makes use of custom events, data binding, and building applications in an event-centric manner.

jQuery Meetup Game
Source Code

Improve Your Web App with jQuery

A different restructuring of the previous talk that emphasizes a more holistic approach to improving your web applications with jQuery

Improve Your Web App with jQuery
Source Code

I've been messing around with a new piece of presentation software that I wrote for these talks. It's still terribly crude and buggy (pretty much just got it working enough in order to run my talks in Firefox 3.6 and Chrome) - you've been warned. I hope to refine it at some point and release it for general consumption.

Categories: Blogs

FLEX On jQuery: Turning HTML Links Into Standard UI Elements

Ben Nadel Ajax and JQuery Feed - Thu, 03/04/2010 - 03:39
In my first "FLEX on jQuery" blog post yesterday , I talked with Javier Julio about some of the similarities and differences between FLEX applications and rich jQuery applications. As we talked, one of the patterns that I began to see was the significant difference in the inherent power of "link" elements in the two differ ... Read More »
Categories: Blogs

FLEX On jQuery: The Relative Power Of Link Elements

Ben Nadel Ajax and JQuery Feed - Wed, 03/03/2010 - 17:17
Mentally, I am still very much in the web application world of the traditional client-server request-response life cycle. I think in terms of page requests and view rendering; and, as my ability to code complex jQuery applications increases, I fear that my understanding of client-side architecture "best practices" is not keeping up. After a lot of experimentation and exploration that lead to concepts like c ... Read More »
Categories: Blogs

jQuery Twitter plugin update – jTwitter 1.1

JQuery HowTo - Wed, 03/03/2010 - 09:12
Some time ago I created jQuery Twitter plugin – jTwitter. Plugin lets you get data about any Twitter user, such as user’s bio, profile image, homepage URL, background image URL, following count, followers count, messages count, etc. without any Twitter API key. It is very useful to attach additional Twitter data to your site’s user profiles, etc. However, it was not very handy for creating your
Categories: Blogs

Get URL parameters & values with jQuery

JQuery HowTo - Tue, 03/02/2010 - 23:28
In this post, I would like to share a little jQuery code snippet that makes getting URL parameters and their values more convenient. Recently, while working on one of my projects, I needed to read and get parameter values from URL string of the current page that was constructed and sent by PHP script. I came across this short and sweet JavaScript code snippet by Roshambo that does just that. //
Categories: Blogs

Experimenting With jQuery's Queue() And Dequeue() Methods

Ben Nadel Ajax and JQuery Feed - Tue, 03/02/2010 - 16:10
jQuery comes with a number of built-in animation methods like slideUp() and slideDown(). While these appear to be packaged in their own methods, many of them are powered internally by the animate() method. And while the animate() method handles many of the effects, a string of sequential animations is controlled internally by jQuery's queuing mechanism. This queuing mechanism, while used primarily for the FX ("effects") queue, is also made available as part of the jQuery API. This API allows ... Read More »
Categories: Blogs

Maintainable JavaScript: Don’t modify objects you don’t own

NCZOnline - Nicholas C. Zakas - Tue, 03/02/2010 - 15:00

The first talk I gave after arriving at Yahoo! was entitled Maintainable JavaScript (video). As with most topics I write or speak about, I didn’t think it would be terribly controversial. The basis of the talk is that hacking around on your own and writing code in an enterprise environment are two different things. Web developers are truly unique in that none of us learned what we know in school; we all began as hobbyists one way or another and taught ourselves most (if not all) of what we know.

Professionalization

The professionalization of web development has been a difficult journey because of our disparate beginnings. Even those who end up at large companies such as Yahoo! inevitably began on their own, hacking around. Perhaps you were even “the web guy” at a small company and could do pretty much whatever you wanted. When the large companies started tapping this previously undiscovered resource, it brought a lot of hackers into a corporate environment where they were met with constraints. No longer a lone soldier in a small battle, all of these self-taught, self-directed individuals had to figure out how to work together as a team.

At the time that I gave the talk (2007), web development was evolving into front-end engineering and people were having trouble with the transition. Smart folks like Nate Koechley talked about the professionalization of front-end engineering (video) and how our discipline was evolving. My talk was aimed at the same goal: helping front-end engineers adapt to JavaScript development in a team environment by making sure that their code was as maintainable as possible.

Why can’t I modify objects I don’t own?

I still gets email and comments about Maintainable JavaScript, and the most popular question is, “why can’t I modify objects I don’t own?” JavaScript is, of course, a dynamic language that allows you to add and remove objects and their members at any point in time. For many, this is precisely why they enjoy the language: there are very few constraints imposed by the language. And I was telling them not to do this. Why?

Dependability

The simple explanation is that an enterprise software product needs a consistent and dependable execution environment to be maintainable. In other languages, you consider already-existing objects as libraries for you to use in order to complete your task. In JavaScript, people saw already-existing objects as a playground in which you could do anything you wanted. My point was that you should treat the already-existing JavaScript objects as you would a library of utilities. Don’t override methods, don’t add new methods, don’t remove existing methods.

When you’re the only one working on a project, it’s easy to get away with these types of modifications because you know them and expect them. When working with a team on a large project, making changes like this cause mass confusion and a lot of lost time. I still remember a bug that occurred while working on My Yahoo! because someone had overridden YAHOO.util.Event.stopEvent() to do something else. It took days to track this problem down because we all assumed that this method was doing exactly what it always did. Once we discovered this, we also found other bugs because the same method was being used in other places with its original intended usage…but of course, it wasn’t behaving in that way. Unraveling this was an incredible mess and I’d be very happy if no engineers ever had to go through a similar exercise.

Incompatible implementations

But developer confusion isn’t the only problem. Another peril of modifying objects that you don’t own is the possibility of naming collisions and incompatible implementations. Take a lesson from the history of the Prototype JavaScript library. John Resig wrote about this a while ago, so I’ll just quickly summarize. Prior to version 1.6, Prototype implemented its own document.getElementsByClassName() method long before it was part of HTML5 and long before any browser thought about implementing it natively. In addition, Prototype also added the each() method to Array objects. Thus, users of the Prototype library began writing code such as:

document.getElementsByClassName("myclass").each(doSomething);

This wasn’t a problem until the native document.getElementsByClassName() method was implemented. While Prototype’s version returned an instance of Array, the native implementation returns a NodeList object. Since NodeList doesn’t have an each() method, either natively or added by Prototype, the above coding pattern caused a JavaScript error when executed in browsers that had a native implementation of document.getElementsByClassName(). The end result is that users of Prototype had to upgrade both the library code and their own code; what a maintenance nightmare.

What if everyone did it?

Looking at a few isolated examples doesn’t really represent the enormity of the maintenance problem when you modify objects that you shouldn’t. To understand this point of view, it’s helpful to take a step back and look at moral philosophy (aka ethics). Moral philosophy is all about determining if an action is moral. There are many schools of thought on the topic, but I point towards a favorite modern philosopher, Immanuel Kant.

While I don’t want to get too deeply into moral philosophy and open this up for philosophical debate, Kant was famous for trying to determine “universal law” as the basis for moral action. In short, you can determine if an act is moral by asking, what would happen if everyone did it? For example, what if everyone cheated on a test? In that case, the test becomes useless, so this must not be a moral action.

Applying this same line of reasoning to the topic at hand, what if everyone on your team started modifying objects that they didn’t own? What if I went in and made modifications to document and so did everyone else on my team? What if everyone on the team created their own global variables? I hope that it’s obvious just how detrimental these actions could be to a team development environment.

Simply put: if everyone on your team modified objects that they didn’t own, you’d quickly run into naming collisions, incompatible implementations, and maintenance nightmares.

As a side note, I find Kant’s question incredibly relevant to any system that must scale. “What if everyone did it?” can really save you some trouble when considered as part of a technical design.

Conclusion

Maintainable code is code that you don’t need to modify when the browser changes. You don’t know how browser developers will evolve existing browsers and the rate at which those evolutions will take place. The code you write needs to continue working in future browsers and with future versions of JavaScript libraries without modification, and you cannot ensure that when you’re modifying objects that you didn’t create in the first place. The only code you can be certain will remain the same is the code you write yourself.

I can’t state this strongly enough: your code is not maintainable when it requires modifications to objects you didn’t create. Stepping down that path only leads to maintenance nightmares going forward.

P.S. If you’re interested in learning more, check out my presentation on Scalable JavaScript Application Architecture (video).
Related posts

P.S. My new book, High Performance JavaScript is coming out in early 2010. Need help now? Check out Professional JavaScript, 2nd Edition.

Categories: Blogs

Internet Explorer: Global Variables, and Stack Overflows

Simon Willison’s Weblog - Tue, 03/02/2010 - 11:21

Internet Explorer: Global Variables, and Stack Overflows. An extremely subtle IE bug—if your recursive JavaScript function is attached directly to the window (global) object, IE won’t let you call it recursively more than 12 times.

Categories: Blogs

Node.js, redis, and resque

Simon Willison’s Weblog - Mon, 03/01/2010 - 01:02

Node.js, redis, and resque (via). Paul Gross has been experimenting with Node.js proxies for allowing web applications to be upgraded without missing any requests. Here he places all incoming HTTP requests in a redis queue, then has his backend Rails servers consume requests from the queue and push the responses back on to a queue for Node to deliver. When the backend application is upgraded, requests remain in the queue and users see a few seconds of delay before their request is handled. It’s not production ready yet (POST requests aren’t handled, for example) but it’s a very interesting approach.

Categories: Blogs

jQuery Twitter plugin update

JQuery HowTo - Sun, 02/28/2010 - 22:05
A lot of users requested a demo for my jQuery Twitter plugin. It has been a while since I updated the plugin, so I downloaded the latest version and while looking thought the code found couple of bugs. So, here comes updated and fixed jQuery Tweeter plugin - jTwitter 1.1.1. In this release, I fixed a little bug that would not allow you request Tweets without number of posts like this: //
Categories: Blogs

kriszyp's node-promise

Simon Willison’s Weblog - Sun, 02/28/2010 - 17:50

kriszyp’s node-promise. Another elegant approach to managing asynchronous flows in Node, including running things both in parallel and serial.

Categories: Blogs

Review: Heavy Rain

Painfully Obvious - Andrew Dupont - Sun, 02/28/2010 - 12:35

A couple years ago, I stumbled upon a game called Masq. It’s a simple game with the art style of a comic book — a bunch of still frames with no sound — but each choice you make affects the final outcome in significant ways. I played at least four times and never had the same ending twice.

I’d forgotten about Masq until I played Heavy Rain. They’re both interactive dramas (a sparsely-populated genre, to say the least), but the new PS3 offering aims to meld the forking plotlines of Masq with the atmosphere and immersion of high-tech games.

Developer Quantic Dream is aiming to break new ground in both story and storytelling. To distinguish between them, I need only recall Indigo Prophecy, the studio’s previous game: it used fascinating storytelling mechanisms to convey a story that was utter shit.

Well, they’ve fixed that part. I spent the entire game somewhat fearful that the plot would veer into WTF territory, but it didn’t. Instead, I got a simple-yet-compelling noir plot, plenty of meaningful choices, and a unique ending. No, I mean a unique ending; there are seven in total, the most I’ve seen in a game since Chrono Trigger.

The main story is about eight hours long, but I’ve already finished two playthroughs, and I know I’ll revisit Heavy Rain at least once a year to remind myself how a game should tell a story.

Categories: Blogs