Author's note: this probably doesn't match the Mediator pattern exactly, but
it's the closest pattern I could find to what I had in mind. Also, check out
the "latest version post" link at the top of this post to see the latest
update.

So, while this works ok, as you can see, it gets a little... big over time.
That's a lot of if statements to go through. That's a lot of dom interaction
being called from the same chunk of code that's dealing with the messages.
That's tight coupling. So, what happens when, say, we want Chrome to usedesktop notifications?
Well, we're nesting more if
statements based on data type. Maybe even copypasting this notification code
several times. As we add more conditional logic, it gets heavier, and heavier,
and heavier...

And that's when it struck me - there is a better way! What if I used an object
that held functions in an array based on response type, and called those
functions when I received a call with that response type? It would be fast, as
an array lookup, and it would let me add any arbitrary amount of functions
based on logic without having to tie it into a massive if/then statement. And,
as an added bonus, we get a really easy method of testing our application
without being connected to a server, by directly passing our Mediator object
some mocked data.

I sat down and got together a little utility class that allows you to add
methods based on data type (which we assume to be there. More on this in a
bit.) I added a remove method that allows you to remove all associations for a
given type, or to remove associations based on a type for a specific function
that you've wired up. (Like the jQuery bind / unbind.) I finally added a Call
method, which accepts an object. Easy and elegant.

And then I got thinking about ways to take it a step further. In our example
chat application - what if I want different logic if it's a chat message with
my username in it? If we allow our Add method to take a predicate as an
alternative to a "type", we can now say things like:

Wow, neat-o! So, as long as our "data" object contains a "type", we can call
anybody who's registered to that type. We can also remove objects, either by
typed, or if it's a named function, by passing in the function. (Note:
anonymous functions won't work here.)