Posts tagged ‘javascript’

Adding a Centralized Event Dispatcher on Backbone.js

This article contains my solution to adding a simple global event dispatcher to Backbone. It should also help noobies (myself included) understand how Backbone events work (which has one big gotcha).

Sharing Events = Global Dispatcher

Today, I came across a fairly mundane – and probably common – problem: I have two views that need to talk to each other. An example for this would be when you have a status bar in one corner that gets updated when a user completes an action in another area. It turns out that Backbone (as far as I can tell) does not support this use case very well out of the box. Well, it does: it expects you to build that yourself.

Backbone supports a model where you publish and subscribe to things happening in your views/models (commonly known as an “event dispatcher“). For example, you can make your application do stuff when a user clicks on something or if a model attribute changes. The native solution localizes these events (probably a good thing) to the model/view that you’re working with. This works for simple stuff, but when you need it in other parts of your application, things break down. The short answer is that you need to build a global event dispatcher A.K.A. global event “hub.” Everything publishes (“trigger”) and listens (“bind”) to events from this object.

This is a common pattern. In fact, I found two solid articles on this topic. The first explains in detail why you need an event dispatcher. The second shows you how to make the dispatcher natively accessible by all of your Backbone classes.

Event Dispatcher Gotcha: Native Events

However, I felt both solutions weren’t quite there. The first forces you to pass around an Event object everywhere you need it. This is nice from a decoupling standpoint, but highly error prone. The second solution is nice, but makes the caller oblivious to the global event namespace they are triggering/binding to. This is dangerous because Backbone has native generic events that are fired when certain things happen. For example, when you edit a Model, it automatically fires a “change” event into its event dispatcher (which bubbles up to its Collection too). This means if that dispatcher was global, every object would see a “change” firing every time every Model changed. Not good.

Goals

I came up with my own solution that accomplishes three main goals:

  1. Retain native Backbone event triggering/binding
  2. Allow the developer to trigger/bind to global events
  3. Not require the developer to pass things around

Solution Code

(If you can’t read CoffeeScript, just use this converter to convert it back to JavaScript)

The following (very simple) code modifies your Backbone definition to attach the global dispatcher to all objects. The dispatcher is easily accessible from any Model, Route, View, or  Collection through the global_dispatcher parameter. I thought about having it trigger events to the local dispatcher as well, but I decided that keeping them fully separate was in everybody’s best interest (to prevent events from accidentally colliding):

# centralized global_dispatcher object added to all Backbone Collection, Model, View, and Router classes
(->
  return if this.isExtended
  # attaching the Events object to the dispatcher variable
  dispatcher = _.extend({}, Backbone.Events, cid: "dispatcher")
  _.each [ Backbone.Collection::, Backbone.Model::, Backbone.View::, Backbone.Router:: ], (proto) ->
    # attaching a global dispatcher instance
    _.extend proto, global_dispatcher: dispatcher
)()

Example Code

The next section is a simple class I wrote that will demonstrate how these events work. I am defining a simple Collection and a Model. Note that I named the global and local events the SAME. This was to help demonstrate that the namespaces are in fact completely separate (as in, just because they are named the same doesn’t mean a local event will ever trigger a global event with the same name).

# See http://www.michikono.com/2012/01/11/adding-a-centralized-event-dispatcher-on-backbone-js/ for an explanation

class Test extends sBackbone.Model

  initialize: () ->
    this.global_dispatcher.bind('model_custom_action', () ->
        console.log('GLOBAL TRIGGERED: test model custom action')
    )
    this.bind('model_custom_action', () ->
        console.log('TRIGGERED: test model custom action')
    )

  trigger_stuff: () ->
    console.log('triggering model')
    this.trigger('model_custom_action')
    this.global_dispatcher.trigger('model_custom_action')


class TestCollection extends sBackbone.Collection
  model: Test

  initialize: () ->
    this.global_dispatcher.bind('collection_custom_action', () ->
        console.log('GLOBAL TRIGGERED: test collection custom action')
    )
    this.bind('collection_custom_action', () ->
        console.log('TRIGGERED: test collection custom action')
    )

    this.global_dispatcher.bind('model_custom_action', () ->
        console.log('GLOBAL TRIGGERED inside Collection: test model custom action')
    )

    this.bind('model_custom_action', () ->
        console.log('TRIGGERED inside Collection: test model custom action')
    )

  trigger_stuff: () ->
    console.log('triggering collection')
    this.trigger('collection_custom_action')
    this.global_dispatcher.trigger('collection_custom_action')

The following snippet illustrates triggering the events attached to the Collection. Note that we add a Model into this collection (which has no impact on the output). The trigger_stuff method triggers both a local and global event (in that order). The output shows that the events were picked up in the order fired (local, then global). Note that the Collection also listens to the “model_custom_action” event, which coincides with an event the Model triggers. This is very important.

# Trigger both the local and global event bindings for the collection

# Outputs:
# triggering collection
# TRIGGERED: test collection custom action
# GLOBAL TRIGGERED: test collection custom action

collection = new TestCollection()
# adding an empty, but fully valid Model instance
collection.add()
collection.trigger_stuff()

The order of operations looks like this:

  1. Fire a local event
  2. The Collection picks it up
  3. END OF FIRST EVENT
  4. Fire global event
  5. The Collection’s globally attached event handler picks it up
  6. END OF SECOND EVENT

The next snippet shows what happens when you fire an event on a Model inside a Collection. It is also why I decided to keep things separate. This is a little hairy, so pay special attention.

# Trigger both the local and global event bindings for the model

# Outputs:
# triggering model
# TRIGGERED: test model custom action
# TRIGGERED inside Collection: test model custom action
# GLOBAL TRIGGERED inside Collection: test model custom action
# GLOBAL TRIGGERED: test model custom action

collection = new TestCollection()
# adding an empty, but fully valid Model instance
collection.add()
# getting the just-added instance
instance = collection.at(0)
# trigger an event on the Model
instance.trigger_stuff()

The order of operations looks like this:

  1. Fire a local event
  2. The Model picks it up
  3. The Collection picks it up since all events in children bubble up
  4. END OF FIRST EVENT
  5. Fire global event
  6. The Collection’s globally attached event handler picks it up
  7. The Model’s globally attached event handler picks it up
  8. END OF SECOND EVENT

Notice that in step #6, the Collection’s binding fires BEFORE the Model’s. This is key.

Step #3 fires because there is a LOCAL binding to the “model_custom_action” event in the Collection. The local binding is reacting to an event triggered in the child Model’s local event dispatcher. In other words, any event triggered from the local event dispatcher in a Model will bubble up to the Collection’s local event dispatcher and be otherwise indistinguishable from events triggered directly from that Collection.

Step #6, however, is different. That event did NOT originate from the child model’s local event dispatcher. Instead, it is reacting to the global bindings, which happen to share the same name as the event we saw earlier in step #3. Because it didn’t bubble up, the events are being processed in the order they were bound (via the bind() function). The Collection was defined before the Model, thus, the Collection’s global binding fires first.

In this last snippet, we demonstrate how Models behave when not inside a Collection.

# Trigger event bindings for a model not in a collection

# Outputs:
# triggering model
# TRIGGERED: test model custom action
# GLOBAL TRIGGERED: test model custom action

instance = new Test
instance.trigger_stuff()

  1. Fire a local event
  2. The Model picks it up
  3. END OF FIRST EVENT
  4. Fire global event
  5. The Model’s globally attached event handler picks it up
  6. END OF SECOND EVENT

This is very straight forward if you managed to follow the last example. To get additional clarity, you may want to try renaming the events in the above class and re-run the examples.

By having the global dispatcher separate, you can consciously decide when an event should be “public,” as well as not clobber any existing Backbone functionality. Backbone is still really young (pre 1.0!), so I wanted to avoid using any solution that might break if they changed the internals. Also, completely preserving the behavior of event bubbling for Model-Collections is important to future proof my hack.

I hope this is useful for all of your Google-visitors!

Q: Hiding JS Files? A: Impossible

In my popular post about hiding your Word Press folder, a reader asked:

Hi Michi, can you help me with this, in the head section i wrote this:

<script src="/style/js/somescripts3.js” type=”text/javascript” charset=”utf-8″>

and when we go to the webpage then right click, it will show:

<script src="content/themes/exampletheme/exampletheme/style/js/somescripts3.js”
  type=”text/javascript” charset=”utf-8″>

can you teach me or show me how to do that, any help highly appreciated, And im so sorry if my english not good.

This question was complicated enough where I thought a new post might make sense.

For clarification, I believe he is asking if it’s possible to put one thing in the source and another that the browser sees. This is impossible. Anything that the browser can see, the user can see. There is no way to “show” something different in the source of an HTML file versus what the browser sees (except through obfuscation); however, you can forward things along behind the scenes. You want to create an htaccess rule that will redirect your requests.

RewriteRule /path/to/thejsfileyouwanttoshow\.js /path/to/real/js/file.js [L]

Let me reiterate that you *cannot* hide the content of the JS file. However, you *can* hide the true folder structure of the web server. If you desire to hide your JS contents, the better solution is a JS minifier.

Alternatively, if your goal is to somehow make it harder for somebody to steal your code and you don’t want ot use a JS minifier, you could write the JavaScript tag dynamically using another piece of JavaScript. However, ultimately, that level of weak obfuscation won’t protect you from anything since Firebug will quickly expose what’s really going on.

I hope that answers your question.

Rainbow Google and Annoying Google

I launched two more Google parodies: Rainbow Google and Annoying Google!

Rainbow Google is just a pretty demonstration of dynamic stylesheet modification. It was actually extremely hard to code — it took me about 8 hours of JavaScript hell. On another day, I’ll go over how I did it. This site adds a colorful spray of colors to the text on the page (see screenshot).

rainbowgoogle.com

RainbowGoogle.com

Annoying Google was about 10 minutes of work since it was just a super simple version of Rainbow Google’s code. :) Search queries and results are jumbled so that their letters are in random capitalized states… LiKe ThiS.

annoyinggoogle.com

AnnoyingGoogle.com

If you have suggestions or ideas, please let me know!

Getting Around Overwriting form.submit()

Since my dear reader Sameer requested it, I’m here making an update. I’ve got a cool JavaScript fix for everybody! I mentioned in a post a long time ago, but JavaScript has this semi-unexpected “feature” where you can accidentally overwrite the submit() function from a form. As in:

<form id=”myform”>
<input name=”submit” value=”submit me” type=”submit” />
</form>
<script>
document.getElementById(‘myform’).submit(); // THIS FAILS – Object not a method
</script>

Apparently, by creating a form element called “submit” you overwrite the native function that exists in every form element in JavaScript. Because it’s native, it also means you can’t just willy-nilly redefine it. And to make things worse, you cannot (at least not in a cross browser manner), successfully re-assign the submit() method because some browsers will disregard any attempt to reassign its value. As in:

<script>
document.getElementById(‘myform’).submit = ‘This gets ignored’;
</script>

Fortunately, there is a fix. This fix requires modifying the actual DOM. Because this tends to be inconsistent across browsers, I’m doing this fix in MooTools (which is my JS library of choice). However, the fix is fairly straight forward and can easily be done with (or without) any JS framework, as you will see. The steps are:

  1. REMOVE the form element in question. This is an absolute requirement to make the solution cross browser compatible. This can be skipped, but it will cause quirks. However, the good news is that we can assume that 99.99% of all form elements named “submit” are due to designers being ignorant — thus, such cases are exclusive to submit buttons. Luckily, these are almost NEVER needed in the server side code and really just act as wall flowers.
  2. Check if step #1 completed successfully
  3. If it did not, create a new Form element and copy its submit function over
  4. Submit

The code looks like this:

<script>
var formObject = document.getElementById(‘myform’);
// Removes the node
formObject.submit.remove();
// Functions don’t have tagName defined

if(‘undefined’ == (typeof formObject.submit.tagName)) {
    // create a form and assign its submit function
    formObject.submit = new Element(‘form’).submit;
}
formObject.submit()
</script>

Let me know if you encounter any problems.

Improving Your JavaScript Load Time

On our production website at work, I noticed that there was considerable lag time when loading the page due to a high number of JavaScript files. For those of you who don’t know, when a JavaScript file is loaded into a page, the rest of the page will hang until that file is completely downloaded. So unlike an image on a page, a slow JavaScript file can completely bog down your page. This is similar to an issue I noticed many months ago with FeedBurner. Each JavaScript file that is pulled requires the full overhead of firing up Apache and serving an HTTP request. This can be slower for you and painful for the web server if you have a high traffic website.

Additionally, once the JavaScript files load, if the code is full of asynchronous snippets (AJAX, event handlers, etc), the pieces can load in the wrong order! This has caused me headaches when unexplainable and random JavaScript errors began popping up (undefined variables and functions that are clearly defined in another file that should have loaded prior). This issue became increasingly common as the number of files being loaded increased. While I admit I don’t understand browser physiology enough to explain why this problem is more common with more files, I concluded there is some correlation that likely is attributed to the rendering order.

So after some thought, I came up with a solution. The goal was simple: decrease the number of web calls and try to make the JavaScript code render in 100% reliable and linear matter. Additionally, the hack would need to be easy to implement and take issues such as caching into account. The solution is a PHP file that looks like this:

/*
 * This file compiles a collection of JS files and then dumps them collectively
 * to the page, thereby reducing overall request overhead
 * Copyright 2007 Michi Kono (www.michikono.com)
 * Feel free to modify this however you want.
 */
header("content-type: application/x-javascript");
foreach(explode(",", $_GET["files"]) as $filename) {
   /*
    * prevent malicious attacks, only allow JS files
    */
   $filename = basename(trim($filename), ".js") . ".js";
   if($filename && file_exists($filename)) {
       $handle = fopen($filename, "r");
       fpassthru($handle);
       /*
        * in case there is no trailing ;
        */
       echo ";";
   }
}

Put this file in your JavaScript folder next to the rest of your JavaScript files. I called mine render.php.

Then, you put this in your HTML:

<script type="text/javascript" src="/javascript/render.php?files=firstfile.js, secondfile.js, thirdfile.js, etc.js"></script>

Ta-da! Faster JavaScript loading for everybody. :) Oh, and the issue of caching? Just put a timestamp on the end of the JavaScript URL string (like, "&<?php echo substr(time(), 0, -2) ?>" — cache changes every 100 seconds)

Other useful ideas: JS code could be compressed during this step, with comments and extra spaces being removed. Because code is being run through PHP, server side macros are now possible, rather than relying on cryptic JavaScript functions (such as for date management or database integration).

IE Redirect Bug with Dynamic Location Hash

I discovered the most obscure bug today in IE. For those of you paying attention, this bug is the reason I haven’t been updating — it ate up all my god-damned time. People who aren’t programmers can stop reading here.

What Happens

The browser is redirected when it shouldn’t be after modifying the URL hash (the stuff after #).

Scope

The bug exists on IE7, possibly 6 (why not, right?).

Steps to Reproduce

Assume you are on page A and want to redirect to page B.

  • Go to page A.
  • From page A, do a header redirect to page B in PHP/ASP/whatever. As in, header(‘location: $pageB’);
  • On page B, using JavaScript, modify the document.location.hash variable.

What Should Happen

The anchor text in the address bar should change. As in, http://www.michiknows.com/#someanchor changes to http://www.michiknows.com/#newanchor. This should happen without the page refreshing.

What Actually Happens

The browser refreshes. @#%!*(&$!

Solution / Fixes

On page A, rather than redirect using headers, use JavaScript:

<script>
// if page A was http://www.michiknows.com
document.location.href = 'http://www.michiknows.com/';
</script>
<a href="http://www.michiknows.com">go to page A</a>

For some dumb reason, this fixes the problem.

Damn you, Microsoft!

The Truth Behind Giving IE7 Standards Compliance Updates

I just realized a funny irony about Microsoft competing with Google. See, Google has some really advanced JavaScript when it comes to its Adsense scripts (look to the left of or below this article). If you’ve never thought about this process, here’s your chance. The JavaScript that makes these ad unit boxes must:

  • Scan the page and send the contents to Google for analysis, get the response, and serve an ad accordingly (AJAX)
  • Build an entire block of HTML from scratch (DOM manipulation – very annoying)
  • Fire after the page loads, to ensure all of the content is in place (event handling)
  • Override any CSS or other page altering scripts to ensure people can’t be tricked into clicking (CSS hacking!)
  • Look and function exactly the same in all browsers

Well, the stuff I listed up there involves some of the most annoying aspects of programming in JavaScript (believe me). AJAX, Event handling, DOM manipulation, and CSS pretty much sum up the four pillars of “the most inconsistent things in JavaScript.” Thanks to IE, these tasks are a pain in the ass, when they really shouldn’t be.

Microsoft has to ensure their ads appear in all browsers, especially Firefox (#2 browser). You can’t sell your services to advertisers if it’s known that your ads break, and possibly misfire, when the wrong browser hits it. That means they’re forced to use a standards compliant implementation to do their ads.

This, of course, means they’re taking their own medicine and finding out what a horrible pain it is to support Firefox 1.5, Firefox 2.0, IE5, IE6, IE7, Opera, Safari, etc. It’s mostly a pain because of IE and its inconsistent and buggy support for the established JavaScript and CSS standards.

Maybe this is why they appear to be supporting some standards in IE7. Or, maybe they’re just building in the ones they use. Either way, this explains a lot. :P

Today, I Converted My JavaScript Allegiance to MooTools

As none of you probably realize (I mean, who even reads my JavaScript posts), I am an avid fan of JavaScript. I think it’s an awesome language that is very underestimated. Even Joel likes it. Anyway, one of the big problems with JavaScript is its inconsistencies between browsers. The first popular pioneer into cross browser scripting was Prototype, an open source library full of tons of useful functions and enhancements to the JavaScript language. It was quickly followed up by an extremely popular open source effects library called Scriptaculous. I was never a fan of Scriptaculous because of its bloat, but I have remained a steadfast supporter of Prototype.

That is, until yesterday.

Yesterday, I discovered MooTools, an amazing open source library that has all of Prototype and Scriptaculous’ functionality, and then some. After thoroughly examining its features, size, ease of use, and extensibility, I have concluded it is my new JavaScript library of choice. Some of the highlights include:

  • A relatively similar naming scheme as Prototype, making porting a simple process for most scripts.
  • Functionality that matches all of Prototype’s core methods, including AJAX functionality, DOM manipulation, and browser compatibility fixes.
  • Really easy animation effects that give you an amazing amount of control (see below).
  • Very active developers (they actually respond to questions within a day!)
  • The compressed download is only 40kb (which is the one you’d be using).

I highly encourage web developers to check it out. There was a recent article on Slashdot that discussed some of the big libraries out there, but it completely omitted MooTools. Well, I have been looking for a few months now for a library to use for our application at work. I examined Scriptaculous, Yahoo UI, Dojo, jQuery, Open Rico, Mochikit, and various other small ones I came across. I stumbled for hours just looking for JavaScript libraries. At one time or another, I wrote something relatively advanced with each of these frameworks in an attempt to see how well the advanced functionality was designed.

  • Scriptaculous suffers from insane bloat and heavy reliance on Prototype, a completely separate project — this problem was highlighted when a recent fix in Prototype broke Scriptaculous unless you switched to their unfinished beta release. This is unacceptable.
  • Yahoo UI tends to require more lines of code to do the same things in other libraries. It is trying to do “everything at once.” It is also very bloated because it fragments itself across many files.
  • Dojo is just huge (150kb, compressed). That’s a negative.
  • jQuery is too fragmented, which actually hurts it in my eyes (others see it as really “customizable”) – it has way too many plugins that you can’t depend on since the developers working on them aren’t affiliated to the jQuery project. If you do too much advanced stuff, it can end up like Yahoo UI, except the fragments you are relying on are made by 40 different people, none of whom have any reason to help you.
  • Open Rico is awesome for simplifying AJAX, but fails in the visual effects department due to over simplification of the process and requiring too many changes to the HTML (see their accordion example). It is, however, a great introduction for AJAX developers, in my opinion.
  • Mochikit had a (barely) tolerable size (113kb, compressed), but I despise their coding standards (just look at their code sample variable names!) and I wasn’t happy about the complicity in using their library. It is not very beginner friendly, in my opinion. This is a deal breaker since I can’t ensure future maintainers of my code will be JavaScript experts.

The decision was clear: MooTools owned the rest.

On ease of use, it was the top due to its consistent naming conventions and predictable function behavior. Their methods all support “chaining“, which allows you to compress several complex lines of code into one, easier to read one.

What impressed me most for its ease of use was its animation methods. Take this simple snippet:

new Fx.Style($('some-element'), 'margin-left', {
  duration: 400,
  wait: false)
}).start(0, 100);

What’s that do? It takes the element called “some-element” and slides it 100 pixels to the right by changing the margin-left CSS property from 0 to 100 over a 400ms span. This might seem complicated to complete JavaScript beginners, but believe me when I say JavaScript animation literally doesn’t get simpler than this. I have shown you an extremely simple example, but with only another line or two, you can do stuff like this. Here’s an example of making something transparent:

new Fx.Style('popup-message', 'opacity').start(1,0);

Change the “0″ to a “0.5″ and the popup message only goes half way invisible before stopping. They’ve done an exceptional job keeping it relatively simple while still giving you full control over the effects (you can apply transitional algorithms too).

On AJAX, I was also impressed because they managed to keep it very simple, yet give you control of the process. For example, check out this amazingly simple AJAX code:

<form id="myForm" action="submit.php">
<input value="bob@bob.com" name="email">
<input value="90210" name="zip">
</form>
<script>
$('myForm').send();
</script>

That sends an AJAX request to submit.php. Of course, you could customize this and add in callbacks and cool loading images, but just the fact that you can do the entire AJAX request in one line like that is impressive.

They also have a ton of demos (my favorite one). Again, if you are considering a library for AJAX and visual effects, MooTools is by far the best one I have encountered.

Note: If you are looking for a library for only AJAX and not visual effects, MooTools can be downloaded in pieces, so it can fit your needs there as well. It also means later, if you change your mind, you can always download the visual libraries and not have to worry about compatibility issues.

Google Makes the Best Mashup Service Ever

Google just introduce a new RSS Feed JavaScript API. At first, I didn’t get why it was so useful, but after reading up on it, I realized its power.

First, it simplifies RSS parsing. This is awesome on its own level just because that can be a pain sometimes.

But the true power in this API is that it overcomes a critical problem in JavaScript in a safe and manageable way: you can read data from multiple domains. For those of you unaware, JavaScript has a limitation: you can only access one external domain in your script. When you try to get data from a second domain, JavaScript barfs up security warnings. This is there as a safety net so that developers don’t accidentally leave a security hole that lets some hacker throw in their JavaScript code that talks to the hacker’s server.

Google’s new API lets you side-step the entire issue by taking everything through Google. You can take a feed from Slashdot, Digg, and your favorite blog, all on one page, all at once, without having to use otherwise lame and unnecessary workarounds (using proxies or “middleman” scripts).

As I mentioned, the API makes parsing simple. Check out this example:

  1. var feed = new google.feeds.Feed('http://www.digg.com/rss/index.xml');
  2. feed.load(function(result) {
  3. if (!result.error) {
  4.     for (var i = 0; i < result.feed.entries.length; i++) {
  5.       var entry = result.feed.entries[i];
  6.       alert(entry.title);
  7.       alert(entry.content);
  8.     }
  9.   }
  10. });

At first glance, I know it looks like regular JavaScript. But if you look carefully, it is very intuitive.

  1. The first line grabs the RSS feed from Digg and creates a new feed object in feed
  2. The feed is loaded.
  3. If there is no error…
  4. Go through each item.
  5. Get the entry.
  6. Display the title of the entry.
  7. Display the content of the entry, etc.

While this isn’t going to be a huge step for the advanced developers out there, it will be significant for those of us who are too lazy to or didn’t know how to work around JavaScript’s domain security model. The added ease of parsing feeds will be huge for developers who aren’t familiar with parsing XML (note: it is a huge PitA).

Thanks, Google.

A Lesson on JavaScript Objects and Prototype’s bindAsEventListener Method

This post covers 3 topics about JavaScript:

  • How objects work in JavaScript and what makes them useful.
  • A concise explanation as to why the this variable is confusing at times.
  • A clear explanation of bindAsEventListener since the official one is confusing at best.

An Overview of JavaScript Objects

To dumb things down, in JavaScript, functions can be assigned to variables. Thus, you can do cool stuff like this:

var eat = function() {
    alert(‘munch, munch’);
};
// displays ‘munch, munch’
eat();

Objects are denoted by using curly brackets. Inside an object, you can put variables. The syntax is a little different, so pay attention. Thus:

var Michi = {
    favoriteFruit: ‘banana’,
    favoriteBread: ‘whole grain’
};
// displays ‘banana’
alert(Michi.favoriteFruit);

Note: I don’t like either of those that much.

The colon is sort of an equals sign. It essentially equates to “variable name: value”. Each assignment is separated by a comma and the “value” portion can be anything that you can assign to a regular variable. Since you can assign variables inside objects, that means you can put functions inside objects. Then you can call a function by putting a pair of parentheses () on the end of the variable. Again, pay attention to the syntax:

var Michi = {
    eatFruit: function() {
        return ‘Eating: banana’;
    }
}
// displays ‘Eating: banana’
alert(Michi.eatFruit());

In a truly object oriented example, calling eatFruit() should cause Michi to eat his favoriteFruit variable:

// does the same thing as the previous example
var Michi = {
    favoriteFruit: ‘banana’,
    eatFruit: function() {
        return ‘Eating: ‘ + this.favoriteFruit;
    }
}

This is where stuff gets sticky. Or maybe gooey. Nah, I won’t make a pun here. this refers to Michi. This is important because later we might copy Michi into another variable Tom. When that happens, this now refers to Tom‘s favorite fruit, which might be an orange. this is a dynamic placeholder for whatever object that we are inside of.

How *this* Complicates Things

Let’s continue illustrating the problem by building another example:

function watch(personEating) {
    alert(personEating);
}
// displays “Eating: banana”
watch(Michi.eatFruit());

This will do exactly what you think it will do. It will cause Michi to eatFruit(). However, the next example is where things get very tricky:

function watch(personEating) {
    alert(personEating());
}
// the goal is to display “Eating: banana”
watch(Michi.eatFruit);

This will fail. Why? Notice the very subtle differences between the two examples. Look at section I highlighted. In the first example, the function is called and its result, the text “Eating: banana” is then sent to alert(). In the second example, the function Michi.eatFruit is passed in as a variable. It is then called as a function from inside watch(). Translated, that code renders like this:

function watch(personEating) {
    // this temp stuff isn’t necessary, but it should make
    // things easier to understand

    var tempFunction = function() {
        return ‘Eating: ‘ + this.favoriteFruit;
    }
    var tempText = tempFunction();
    alert(tempText);
}

As you can see, the problem is due to the this.favoriteFruit variable. this now refers to the function watch()‘s parent (e.g., nothing at all), which doesn’t have a favoriteFruit variable. this no longer refers to Michi. This is a very common and very frustrating part about JavaScript. To get around this, the popular prototype library has a fix.

Prototype’s bindAsEventListener

The official documentation (as of this writing) for this method is dead wrong. Their example is wrong. Their explanation is fuzzy. Maybe somebody over there will read this and fix it up. Prototype’s example doesn’t even work! The corrected example is:

var obj = { name: ‘A nice demo’ ,
    handler: function (e) {
        var tag = Event.element(e).tagName.toLowerCase();
        var data = $A(arguments);
        data.shift();
        alert(this.name + ‘\nClick on a ‘ + tag + ‘\nOther args: ‘ + data.join(‘, ‘));
    }
};
Event.observe(window, ‘click’, obj.handler.bindAsEventListener(obj, 1, 2, 3));

So I will try to explain how to use it correctly. The syntax is simple:

parentObject.someFunction.bindAsEventListener(parentObject);

Thus, in my previous example that broke, you would rewrite it as follows:

function watch(personEating) {
    alert(personEating());
}
// was watch(Michi.eatFruit);
watch(Michi.eatFruit.bindAsEventListener(Michi));

When the code is executing, it knows that this refers to Michi, thanks to that argument being passed in. The argument represents what this refers to. So you would still call the method exactly as you normally would, but you tack bindAsEventListener on the end.

I hope this was educational. The fixed demo code will run for certain since I tested it; the rest: I am not as sure (95%).

REMEMBER: Word Press likes to convert my quotation marks into the slanted ones. So if you cut and paste my code, make sure you change those!