Luke Smith: My name is Luke Smith. I'm one of the members of the YUI team, and I'm going to be talking about the event system in YUI 3 today, and how it's evolved over time to the greatness that it is today, that we all know and love.
We'll start with a little bit of history. As you're well familiar with, back in the day the original was the DOM, and this was how we interacted with it. Then we learned that that was actually kind of dumb, so we introduced the separation of concerns, we started separating markup from the JavaScript, and we're hooking into events inside of the JavaScript leaving the markup just for the content. This was actually inadequate as well, especially in an environment where you have some collaboration. You only have that one event listener going on in this object, so that's not going to cut it either.
So the W3C comes along, and they say: hey guys, I've got the greatest solution for you to take care of that collaboration problem — you just use this convenient sixteen character method name, and all of your multiple subscription things will be taken care of. Of course, that doesn't work either, because we have legacy browsers, and IE has a different API, and it just doesn't work.
So we end up with something like this. We can check to see if it has the right API — maybe it has the IE API, or maybe it doesn't have either and we end up doing that, which of course is also dumb. So that's not going to cut it.
So we move on to trying to wrap up the best practices for event subscription into just a method name, maybe called addEvent — there were a few different versions of this going around on the web a few years ago — and handle all of that normalization under the hood, and just rely on viral spreading of the word to say this is how you should do it, everyone just cut and paste this code into your site, and your event subscriptions will be taken care of just right.
This is also incomplete, unfortunately, because it's only part of the problem. It does take care of event subscriptions for the most part, but it's still missing something. You've got the event object on the inside of that event handler, and it also has normalization issues. This is kind of the beginning of where the libraries come from — JavaScript libraries originate from this point — where we realized that there are a lot of things that need to be normalized. The event system, in particular, is really mucked up across the browsers, but there are other things out there as well, like DOM utility, and other nifty things that we can do on top of the normalized platform to make it easier for developers.
In YUI 2, one of those libraries, we have the event utility which has the on method for subscribing and the preventDefault method for handling the interaction with the event objects themselves. So we have a normalized subscription model, and we have normalized event handling, and we have DOM-like method names. The DOM-like method names are really important. From a philosophical standpoint, we feel very strongly that the API that we present to you should be reminiscent of the actual system that you're working with under the hood. This is the DOM, people, so we want to name things as it would be in a DOM system if it worked.
In YUI 3, we realized that the problem is really the starting point. The starting point of your subscription is that you have this DOM element in hand that is just a bundle of volatility. You don't know what DOM it's coming from, because it could be rendered in this browser, or that browser, and all of that. So you're passing this little bundle of volatility into some utility function that is supposed to take care of everything under the hood. Now, it's fine, it takes care of it alright, but having that unstable thing as your core starting point is just an invitation to disaster.
In YUI 3, one of the big evolutions we did was in the Node interface, and providing that Node façade over the actual DOM to give you a new starting point where all you have to do is treat the Node instances as if you were working with the DOM, and it works. So in this case we end up giving you the normalized subscription and the normalized event handling like before, and the DOM-like method names, because everything is hung directly on the Node instance. Now we have the DOM-like context too. So if you were working in raw DOM you would be executing these methods on the thing that you wanted to subscribe to, right? Now in YUI 3, you get to. It's now even more reminiscent of the underlying subsystem — and, of course, it's an awful lot shorter. It's a really long utility method, so let's work on that. So yeah, we give you the DOM now, but it works. That's what we wanted to do.
That's really just the beginning of the story, because the big revolution happened with YUI 2 introducing custom events into the system. Custom events are awesome; hopefully everybody here already agrees with that. But what they did for us was they allowed us to create an event-driven architecture on top of an event-driven architecture. We're working in a system that's event-driven; this is the DOM, the DOM works with events. If we give you the capacity to build a system that works with events, then it goes with the grain of the system that you're actually working with. Everything is DOM driven, or everything is event-driven at the end of the day.
With YUI 2, we like the DOM, we like the notion of having an event-driven system, so we create these custom events. This is how it looks in its early days — we instantiate a custom event, and drop that on your object as just a property of the object, and the API for subscribing to those custom events lives on that object. Eventually that evolved into the EventProvider API, which you'll see in the more recent widgets in YUI 2, and that brings the API on to the instance itself, so you have this hosting mechanism on the instance that says: 'I have X, Y, and Z events', and you can just subscribe to it with a string, just like you would do in DOM methods, saying addEventListener, eventName, as a string. So that follows that same pattern, and then internally you can fire the event to trigger all the listeners, and broadcast that notification to your subscribers.
In YUI 3 we like that pattern, we stuck with that pattern, but we're bringing everything in, we're shortening method names, and we're trying to do a lot more normalization here. There's also the publish step. I didn't mention on the previous slide that another thing that was nice about the EventProvider API in YUI 2 is that you don't have to create those custom events anymore — you can just fire them and if somebody's subscribing to it, then they'll receive notification. So we also took care of that, we also brought that into YUI 3 as well, so you don't have to publish the events — and publish is the API that you'll use in YUI 3.
There's an awful lot of cool stuff happening in each of these steps here, and we'll get to that in time, but let's start by getting this API onto your classes. What you want to do is to extend your class with EventTarget. EventTarget is the barebones event API; this is where it all lives. Node instances, they're all EventTarget. All of the rest of the things that we hand you that have events, they're all EventTarget. However, most of them are actually Base-based, so if you extend Base it also gives you the event API because it itself extends EventTarget, but it also gives you managed attributes, and the ability to add plugins on to your class. Satyen's going to talk about that later this afternoon — I highly recommend going to his presentation, it's going to be awesome. Finally, Widget, which also gives it the UI lifecycle. All of these things have that same underlying event API, so everything operates the same way.
I'm going to go ahead and recommend that, in general, use Base. Extend Base. It's really done a great job of being proven to be stable, and boils in the best practices, and it just has a lot of great stuff in it that you can take advantage of, and you should take advantage of when building your modules and applications.
Let's talk about the normalized subscription again. Now we have the DOM events and the custom events, they're both using the same method name — we're taking this concept of 'event' and saying it doesn't matter if it's a DOM event, it doesn't matter if it's a custom event, the API for dealing with them both is the same. So it's now a unified subscription API, allowing you to deal consistently with just the event API in the same way across your application, and it doesn't matter where it's coming from.
Jumping back into YUI 2. When we were offering up the custom events, when we first created custom events, we liked the notion of the Observer pattern: you have something that hosts a series of events, and when it comes to that interesting moment it broadcasts those events. People can subscribe to it and they get notified — so, your basic Observer pattern. But the DOM actually has more going on there. We like the DOM, and we decided that we want to be more DOM like, but we also wanted to take the opportunity to go a bit above and beyond what the DOM offers, and give some really nice cool things, or some things that you've always wanted — maybe you didn't realize you've always wanted, but you probably did. Since we have the ability to do that for you, we've put some of that into YUI 3 as well. So making the custom events more DOM-like, these are the two core things that are necessary to bring the custom event infrastructure from YUI 2 up to a more DOM-like API. You have default behaviors and event bubbling. Eric talked a little bit about this in his intro presentation, and I'll go into a little bit more detail about that now.
Default behaviors. You push on a key, and the default function is to add that letter into your text input, right? You can cancel that behavior and the event still fires, and it becomes your hook to say: I get to choose whether or not this bit of functionality executes. We've taken care of the API for subscribing to things — the default behaviours and the bubbling are going to be some configuration that we do in the publish step. I talked a little bit about that earlier. We're going to start with the default behaviors, and in particular in the publish step here, the configuration that you pass in to publish when you're publishing your event name.
This is a really simple example: if you're extending Base, then you have an initializer function and this is the proper place to do things like setting up events that have some default functionality, or have some special thing going on inside them. In here, the configuration object is passed into publish, and you specify a default function — in this case, it's just pointing to an internal method called 'this._defStartFn'. This is just a naming convention that we've taken up internally; it isn't necessarily terribly readable at first glance, but over time it does make it easier for maintainability, because if you see this function name in your code you know that this function is related to an event, it's a default function for a particular event, and you can look for a publish. It informs you that this function has something to do with the event infrastructure that I'm building in to my code.
So let's take a look at that. The default function is where it's appropriate to do state changes and a variety of other things, and we'll go into a little bit more dissection about what is appropriate to put where. But notice that the default function also receives this event object. The event object is the same type of event object that you'll get in DOM events; the thing that has the preventDefault, stopPropagation, all of that normalized API. Now, of course, in your default function it doesn't really matter if you have preventDefault, because you're already there. It's really useful for the payload that it brings — here we'll notice that we have 'e.time' and 'e.urgency'. These are specific things that are hung on that event object because the event was fired internally passing that payload. So the payload that you pass in at fire gets munged onto that event object, so that when you're dealing with DOM events you're dealing with 'e.some-property-of-the-event'. When you're dealing with custom events you're dealing with 'e.some-property-of-the-event' — again, normalize approach, unifying the API.
Let's talk a little bit about what goes on, step by step, so we have some implementation code that has an instance of something that has a start event. I'm going to subscribe to that using the on method, say doSomething when the start event happens, and then internally inside of that instance it reaches that interesting moment and fires the event. What happens is it executes the subscribers, it checks to see if it was prevented, and if it was prevented then it just stops and doesn't execute your default function — otherwise, executes are default functions. That should be kind of a no-brainer — that's how the DOM works, and now that's how the YUI 3 custom event works as well.
The behavior is also preventable, as I've been mentioning, and it's preventable with the same API. We have the 'e' there, which is the event object; it has the payload hanging on it, and you can choose to preventDefault, which means that your _defStartFn — is what I'd called it — it doesn't execute at all.
You don't have to let your events be preventable. It makes sense to put code into default functions, but sometimes it doesn't make sense to have that default behavior be preventable. In the case of maybe setting up some initial state, or doing a fair amount of work up front, building up your foundation or something. It's an interesting moment, and you want to broadcast that I am doing something that is potentially really interesting; I'm setting up this foundation work. So you want to broadcast that event, but you don't want to let people stop it.
One thing that I didn't actually mention on previous slides was that because that 'e' object in your default function is the same 'e' object that is passed into your subscribers, your subscribers can take 'e.urgency', for example, and change its value, and not preventDefault, and just let it go up to the default function. At that point, inside of the default function, you have a new value hanging on that 'e', so it allows you a nice hook point to modify the behavior before it gets to what you think is a reasonable course of action, but you just wanted to tweak the behavior a little bit on the way.
Back to the preventable thing. You can tell it not to be preventable, or another approach is to pass into the configuration the preventedFn property. This is a function that will execute if someone calls 'e.preventDefault().' So in the case that you have some set up going on — maybe there's a series of state changes, and they're highly event driven, but someone calls preventDefault somewhere along the line, this function allows you to take stock of where you are right now, and maybe correct your state to someplace that isn't in the middle of a process. So we like hooks.
The default function is actually used all over the place in YUI 3; we really love it. I use it a lot, I guess I should say, and so do the rest of us. Here it is in cache. It's in Console. DataSource uses it in a really interesting and creative way — we might end up moving more towards this pattern, as well. Drag and Drop definitely uses it. We can also see that it's setting the bubbles true configuration — we'll get into that a little bit more. Slider. And here's an interesting sugar API for publishing multiple events that have some special configuration, rather than just calling publish, publish, publish, publish, publish, you can just pass an object literal to publish and take care of all of those in one go. So yes, we love default behaviors, and you should too.
So we've taken care of unifying the subscription API, and the default behaviors, so let's talk about bubbling. As you saw on one of the previous slides, that's really just as simple as in your publish step, setting bubbles to true. When I first heard that YUI 3 custom events were going to start bubbling, my initial impression was: that's awesome, that is so totally awesome. Then a first minutes later I thought: what does that even mean?
[laughter]
Luke: I mean, really. You have a custom event and it's bubbling? Where's it bubbling to? What are you going to use it for anyway? I mean, how do you set up the infrastructure and the intelligence in the system to know where to go?
That's a really hard problem to solve and it's really implementation specific, so what we do is leave it up to you to say addTarget. So I, as a class, when I am instantiated here I am as an instance, I'm going to say all of my events are also going to be broadcast on here. I identify my bubble chain. You can do multiple addTargets if you want, to create a higher chain, and actually you'll notice that that's a public method. If you have some object in hand, you can add yourself as a target. Just to be clear, adding yourself as a target is not equivalent to subscribing to all the events that come through it. What it means is that you will also broadcast the events from the things that are bubbling up to you. There's still a subscription step involved in actually being notified of those events being fired, but now you can actually subscribe to it on yourself, or from one of the other parts on the bubble chain.
Another configuration for a bubbling environment is broadcast, and broadcast is a little bit different. It's basically a convenience method for saying 'bubble to the Y instance'. But I believe it's true that for broadcast events, you can't preventDefault in the bubble — when you're up at the Y instance, you don't have the same sort of control over the event, it's just letting people know at an upper level that, at the Y instance in particular, all of the instances of this particular thing are going to notify the Y instance that this event happened. Broadcast also takes a number two, which is a way to indicate that it should bubble through my Y instance and then also through a shared EventTarget called 'Y.Global', and we'll see that in just a second. This 'Y.Global' is a shared EventTarget across all YUI instances in the system. Here's the equivalent to the default function, and the prevented function. If someone calls stopPropagation, then your stoppedFn is going to execute.
Let's get into the "Why". This should be fairly self-explanatory, but the same concept of event delegation in the DOM applies to event delegation in the custom event world, now that we're here. So if we want to subscribe to all of the LIs, then you can set up six subscribers, or you can subscribe to just the UL, and the events will bubble up to the UL. In this case, you'll actually have to do some intelligence inside of the sayHi method to verify that the element you're receiving the event from is actually of interest to you. That's where the delegatemethod — a little sugar method — comes in. This is kind of an aside, because delegate is really awesome. It gives you the control to say: anything matching this selector, which is passed as the last parameter there, that's the criteria for saying that this is the node that I'm interested in.
But event delegation is good, so we run into a similar circumstance where, if we have a class that's going to be instantiated an awful lot in our system, then we end up with an awful lot of subscriptions if we want to know when this particular event is happening on any of them. So having the event delegation, the bubbling system, allows you to subscribe at a higher level — the manager level — to be notified of any event coming from any of those instances. Same basic rule, same basic principle as event delegation in the DOM system.
Here I have highlighted what we call the event prefix. The event prefix exists because this is an event system that we're letting you build. We're building it ourselves, but also this is out in the world, you're creating your own events, and if those events are bubbling then we have to worry about name collision. In order to identify the origin of this particular start event, we give it a prefix. The prefix is part of the normal configuration of a Base-based element — so if you extend Base you can specify the name and that just gets boiled in as your prefix automatically. Otherwise, you can actually pass the prefix in your publish step. But just use Base, it's great. In this case, here you might have an initializer that says addTarget, and pulls the attribute host and says whoever is hosting me, I'm going to bubble my events to.
This is our poster boy. Drag and drop is really popular, and we can create a simple drag instance, and we can subscribe to its start event. Or there's the DD Manager, the DDM class, which affords you the higher level point to subscribe to any drag start event happening from any of the drag instances that you have created inside of that YUI instance.
I mentioned YUI Global earlier. yui:log is an example that currently uses it. You can set up your own events to broadcast up to the 'Y.Global' if you want — it kind of depends on the needs of your particular set up. Generally speaking, you shouldn't need to have more than one YUI instance, so having that 'Y.Global' as a bridge between instances might not be terribly necessary. But the yui:log, for example, is broadcast up to the global, so from any number of YUI instances you can subscribe at the global level to receive all of the log messages that are coming in from every instance on the page.
I think we've taken care of making them more DOM-like, so now let's make them better. Say you want to subscribe to an event and you want to override its execution context. In the DOM world, you have a button that you want to click on and you want to execute this function, but you don't want it to execute from the context of the button itself, which is the default context for DOM events, the host of that event, the node itself. This is all present in YUI 2, and of course it's present in YUI 3. Passing a subscription payload, as well. Maybe you have some transactional data, or some short lived data that just doesn't need to exist for very long; it's really only relevant to this particular subscription, and you want to pass it in to the subscriber so that when that event is fired, your handler will receive that extra information.
Detaching events has kind of been a nuisance in the past, so we want to make that easier and there are a couple of different ways to do that. 'After' moment subscriptions are huge. They don't seem huge, because it's just there, but they're really awesome, and we'll get into that in just a second. Then, while we're talking about awesome stuff, we can create new DOM events. I have an example of that at the end that should be a little bit of fun, but this gives us an opportunity to fill in the gaps in the DOM implementation for things that really just ought to be there, and events that are relevant for working with nodes.
Let's start with making 'on' a little bit better. We have our instance, we want to subscribe to its start event, and we have a function that lives on this instance — something called myObj — and it has a method called startHandler. If I just did this, then because of the way JavaScript works, startHandler is going to be resolved into a function reference and then assigned into that subscription. But when it gets executed, it doesn't know that it came from myObj. It's just a function reference, and by default, 'this' is going to refer to the window object, the global object. That's not something that you generally want, and you can get around that by using the 'Y.bind' method, which is a great method for locking in a context on a particular function. What 'Y.bind' does is it returns a function that you can call which just wraps up the execution of your function from the specified context. But 'on' actually has that functionality boiled into it now, so you can just specify a context as the third parameter, and that will override the context; you don't have to do any 'Y.bind' stuff, it'll just execute from the context. Of course, since we have the normalized API, Nodes are EventTarget, Base is EventTarget, all of the stuff that you're going to build with this API are EventTarget, and this also works on the DOM.
Let's add some transactional information, some payload information with the subscription. In this case, we just can't really do it unless we create an anonymous function right here in line, that has that payload information inside of that anonymous function that is executing 'myObj.startHandler', specifically with that payload information. In this case, we give you 'Y.rbind'. Now, 'Y.bind' also does this, but for a DOM event subscription where you want to pass in arguments, 'rbind' is a better fit. Again, for DOM events, 'rbind' is a better fit. The distinction between 'Y.bind' and 'Y.rbind' is that 'Y.bind' will take all of the arguments that you pass it, and it'll prepend the list of arguments into your function with all of that extra stuff.
This is actually coming into ECMAScript 5, which now has bind on the Function prototype, and that's the way they modelled it. We may not agree with it, but that's the way they modelled it. So that's what 'bind' does. We actually think that having the extra parameters added to the end actually makes a little more sense, especially in the case of DOM events where you kind of want that first argument to be your event object consistently. You want your API to say: the first thing I get is that event object. I may or may not get a bunch of other junk, but I can count on that event object being the first parameter. That's what 'rbind' does, it just says: add my stuff to the end versus the beginning. 'rbind', in this case, is also boiled into the API so that you can pass in the event name, the function handler, override context, and any number of arguments you want to also go into the signature of your event handler. Incidentally, if you don't need to override the context because we're now to the fourth and fifth and sixth parameters, you can just pass null for that.
So we've taken care of those first two. Let's talk about detaching events. This is the basic pattern for detaching events. This is present in YUI 2; it's a slightly different API, because your 'YAHOO.util.Event.detachListener'. Shortening that to 'detach', and passing in the signature of the subscription… but that's not terribly convenient because you end up having to duplicate the exact signature of that subscription in the detach phase, and really, what a nuisance. I mean, you have a subscription. Now, the on method actually returns what's called a detach handle, and all you have to do is call detach on that thing and it's done, it's gone. That is a really short way of doing things, that way.
Another way that we made possible to do is to give your subscriptions a name, so you can say 'I'm subscribing to my button's click event to do something'. You'll notice this is a pipe. We were already using colon for event bubbling, so we settled on pipe. You can just detach the name that you've given that subscription; you don't have to worry about the rest of the signature because it understands it by name. The extension of this is that that's not just a name, it's actually a category, so you can add many, many, many subscriptions into that same category, and you can detach them all in one glob. This is really handy for creating widgets or something that have a lot of internal events going on. You might have a lot of internal subscribers to manage state — you just create all of your event subscriptions, do all of your event subscriptions under one category, and if there's a destructor or a destroy process in the life cycle for this thing, you just call detach with that name passing in the star, and everything is gone. So we like that one.
OK, on to the greatness. Satyen's actually going to talk a lot more about the after moments and the attributes stuff, but let me just give you a quick run through here. We have an instance that fires this event, and we have our on listeners, and then if it's not prevented it goes onto the default function. Maybe what you care about is what happens after the fact — how many times you've wished you that you could subscribe to something on the DOM where you don't need to stop it, you just need to know what it's like afterwards. We can't do that for you for the DOM, but we can do that for you for custom events.
We now have a parallel method called after, which allows you to subscribe to that moment that happens just after the default function happens, but before any further app logic that may occur after that event was fired. Inside of the implementation code you have some code, and then this event gets fired, and then some more code. The after subscribers will execute before the rest of that code happens, but after any state changes that may have happened inside of that default function. This is really relevant to the managed attributes portion of Base, and again, Satyen, in case I haven't mentioned enough by now, will be talking about that. But after moments are really relevant for managed attributes, because you might be holding on to a value attribute or something, and you internally don't need to care about "it's going to be set", you care that it changed. If someone prevents that, the after subscribers aren't going to fire. Only if you've gotten through the default function are the after subscribers going to fire. Does that make sense?
I'll say that again. We have the on subscribers, the default function, and the after subscribers. The on subscribers give you the capacity to say don't execute the default behavior. If the default behavior executes, then there has been a change and the after subscribers are notified that there has been a change. If the default behavior is prevented, there hasn't been a change, so the after subscribers aren't notified, because there wasn't a change to notify them of. So the after moments represent a good point to hook in to apply side effects as a result of state changes. Again, the on subscribers are where you want to subscribe if you want to see things before they're changed. The changes to the state happen in the default function, and the after subscribers get a view of the world after that state has been changed. Like I said, we like hooks.
Now let's get into the new DOM events. I'm personally pretty excited about this, because of the way it ends up at the end of the day, which we'll see in just a couple of slides. This is the basic pattern right now for how to add a new special event into the event subsystem. I have a chained equals here for the sake of space, but you'll notice that there's an environment that contains an event subsystem, and you can plug in your event in there. But you also want to identify that this is a DOM event, or it can be treated like a DOM event. That means that if you have a Node in hand then you can subscribe to this event on that Node. You just set up your on handler, and this is what gets called in lieu of the default event subsystem for its on behavior, and that's where the magic happens.
Eric actually showed this on a slide — I'm not sure how many of you saw it, but I wrote this special event called Konami. Maybe some of you are familiar with what the Konami code is — hopefully. For those of you who aren't aware, this is a cheat code that Konami introduced into a lot of its video games, where you could just do up, up, down, down, left, right, left, right, B, A, and it'll send you into God mode or something. That got adopted elsewhere, and it kind of became this cute little meme or cult following or whatever.
This was actually fairly easy to do. Let's just set up a Konami event by saying: here are the key codes that are relevant, and then inside of my on subscriber, I'm going to set up the necessary DOM events under the hood for the Node that was passed in to me, and then do all of the checking that's necessary, and then check the progress, then once the progress has gotten there, fire my special internal event. That means that this is how you use events that you add in to the YUI subsystem.
Those are the above and beyond points that I wanted to talk about. Of course, you can use the added DOM events for more practical things, perhaps; it's always fun to have fun, but… I think Isaac is actually going to talk a little bit about creating another DOM event for his use in AutoComplete. I've written another event for subscribing to a text input where you get a notification after there's been a pause in typing, which was based on some work done by the man back there, Ryan Grove.
The big take away for my talk is that the custom event system in YUI 3 is bigger and better and bad ass-er than just your basic DOM. It has all these great features in it, and I want you to take this and rethink about how you're going to use events, and how you're going to build your apps, and really leverage the power of an event-driven architecture, and event-driven infrastructure, so that the code that you write goes with the grain of the system that you're actually building, taking that DOM event system, building up your app subsystem on top of that, and all of it works the same and has consistent code throughout, and consistent behavior.
Here's some image credits for the things that I added. That's what I have for today. Any questions?
Explain the distinction a little better between setting up bubbles and specifying broadcast. When you configure an event to bubble, you need to specify the chain of that bubble path. That chain can consist of any EventTarget — you can say I, as an EventTarget, am going to bubble my events to this other EventTarget, and to this other EventTarget. The fact that that other EventTarget has a responsibility as a manager class is sort of an aside; it isn't a requirement necessarily. It's just saying: I will also broadcast your events, and I will also broadcast your events. But doing the add target manually is closer to the mettle. It allows you to configure specifically where those events are also going to be fired from.
Broadcast, on the other hand, is a simpler mechanism that says: I just want the YUI instance that I'm in to also broadcast my events, and potentially, the 'Y.Global' to also broadcast those events. It doesn't add the configurability of saying: here's the path I want it to take before it gets up to the Y instance, for example. Does that answer your question?
You had a question?
[Audience member makes inaudible comment]
Luke: Right, the way that the 'Y.Global' is built is that it doesn't give YUI instance A and YUI instance B introspection into the code that's executing from one instance to the next. It doesn't actually give any access to that. But as an EventTarget it's useful as a relay of messaging to say: something's going on over here that you might be interested in. You're free to actually pass objects and things in your firing from one instance to the other, if you need to transfer data, per se. But there might be other ways to skin that cat. Does that answer your question?
OK, the question is: is there a way to have the default function, or the default behavior for an event, fire either before or in parallel to its subscribers? The answer to that is no. The event system is based on the DOM, and it patterns the DOM, but we provide you the after moment specifically for that use case. If you publish an event that has a default function, that means that it is possible for implementers to subscribe to that events on moment. If you don't want it to be preventable, you can configure it not to be preventable, but those subscribers will be executable before the default function happens. You can recommend that people subscribe to the after moment if it's really more pertinent to do so, in which case you don't have those on subscribers slowing down the execution of your default function. But no, it's the contract of the on subscribers that they have the capacity to interject into that workflow.
The question is, what happens if you subscribe to the click event, or any DOM event, using after? So, button after click or something like that? The answer is that it's functionally equivalent to on. It still happens. If you have a key down, for example, that character's going to show up after your after event.
OK, well I'm going to be hanging out over here at the side for a few minutes. Thanks everyone for showing up. Hopefully everyone has a better understanding.
[applause]
YUI Theater — Todd Kloots: “Building Accessible Widgets with YUI 3″
Mon, 23 Nov 2009
YUI Theater — Isaac Schlueter: “Solving Problems with YUI 3″
Fri, 20 Nov 2009
YUI Theater — Reid Burke: “Building YAP Applications with YUI”
Thu, 19 Nov 2009
YUI Theater — Todd Kloots: “YUI 3 Sugar”
Thu, 19 Nov 2009
YUI Theater — Allen Rabinovich: “YUI 3 Infographics”
Wed, 18 Nov 2009