开发者

Firing and capturing custom events

Imagine this scenario (it's开发者_如何学Python really just a scenario):

  • I have a global counter that gets incremented on every mouse click.
  • when I reach 50 clicks, I want to fire a custom event named 'reachedCount'
  • I want to register my window object to capture that event with something like

    window.addEventListener('reachedCount', function(args){alert(args.count);}, false)

So, my problems are that I don't know, and can't find anywhere how I can pass arguments to my eventHandler. Also, I had tried the method Rikudo posted, but it doesn't work in IE lt 9.

Is this possible? How?


Using Rikudo Sennin's answer, you can pass parameters to your event handler by putting them inside the event itself, just like the DOM handlers do!

function fireEvent(name, target, param1, param2) {
    //Ready: create a generic event
    var evt = document.createEvent("Events")
    //Aim: initialize it to be the event we want
    evt.initEvent(name, true, true); //true for can bubble, true for cancelable
    evt.param1 = param1;
    evt.param2 = param2;
    //FIRE!
    target.dispatchEvent(evt);
}

function foobar(ev) {
    alert("foobar" + ' ' + ev.param1 + ' ' + event.param2);
}

function testEvents(param1) {
    window.addEventListener("foobar", foobar, false); //false to get it in bubble not capture.
    fireEvent("foobar", document, 'test', param1);
}


All your arguments -just like all the other information about the event- should be carried inside the Event Object itself. The completely self-contained Event Object carries all the needed information about that event. Your argument values are generally set when the new custom event object is created (not when the event is fired).

(All the fragments of example code below exactly match all the other fragments. In fact, some of the examples may not make much sense by themselves; whenever this happens refer to previous example fragments.)

For your own arguments, in some cases you could reuse existing fields (or perhaps even add new fields of your own):

var newEvent = ...
newEvent['scrollX'] = your-own-custom-value;

Exactly how these would get set differs depending on whether you're able to use the new standardized HTML5 way, or must fall back to older browser support. (The various "shims" that add custom event support even to old browsers that don't provide anything at all aren't covered here -- many of them will provide their own rather unique way to set arguments.)

The HTML5 way involves the "dictionary" (second) parameter to the object constructor, something like this:

var newEvent = new CustomEvent('customname', { propertyname : propertyvalue,
                                            anotherpropname : anotherpropvalue,
                                              thirdpropname : thirdpropvalue,
                                                etcpropname : etcpropvalue }   );

The corresponding older method would look something like this:

var newEvent = document.createEvent();
newEvent.initEvent('customname', true, true);
newEvent['propertyname'] = propertyvalue;
newEvent['anotherpropname'] = anotherpropvalue;
newEvent['thirdpropname'] = thirdpropvalue;
newEvent['etcpropname'] = etcprovalue;

(The above example may also make it clearer just what the HTML5 CustomEvent constructor is actually doing.)

Using existing property names like this (or creating your own properties:-), isn't generally recommended though, because cross-browser issues and debugging hassles can be pretty severe. Once in a while this will be necessary and it will work, but don't rely on it as a general technique. Even though some types of event objects include a particular named property, similar types of event objects may not. Some event properties may be "read-only". Event objects are internally highly variable from one browser to another and even between browser versions. And creating your own new properties may confuse the browser's implementation of Javascript.

Instead, use the one particular property that's "set aside" for your use in custom events and nothing else: detail.

Often you will have several arguments, yet there's only one property set aside for your use. So the conventional approach is to always make all your arguments into just one "object", something like this:

var myargs = { my : 1,
              own : getElementById('foo');
             args : { X : 32, Y : 53 }    };

The HTML5 way of setting this variable will look something like:

var newEvent = new CustomEvent('customname', { bubbles : true,
                                            cancelable : true,
                                                detail : myargs } );

The older interface for doing the same thing will look something like:

var newEvent = document.createEvent();
newEvent.initEvent('customname', true, true);
newEvent['detail'] = myargs;

(Of course if you make heavy use of the Javasript "literal object" curly brace syntax to minimize your typing, your code may look a little different than the above examples which prioritize clarity.)

(Two existing event properties, 'bubbles' and 'cancelable', must always be set for every event, regardless of setting possible custom arguments. If the new HTML5 way is being used, they will always appear as two additional lines in the object that's the second parameter to the CustomEvent constructor. If the older way is being used, they will be the second and third parameters to the initEvent(...) call.)

Two different methods of triggering the custom event are also provided. The newer HTML5 way uses object.dispatchEvent(newEvent). The older way uses object.fireEvent('customname', newEvent, false). Here "object" means DOMObject/Element; exactly what (if anything) happens if "object" is something besides a DOM Element is even more browser-specific than the rest of this topic. (Mixing the HTML5 way and the older way generally works, but can be confusing. Another frequent source of confusion is having a system function named fireEvent(...) and also defining your own function with that same name.)

(There are some arcane differences between the two ways of triggering a custom event. The older fireEvent(...) method requires you to re-specify the name of the event even though you already specified it in the initEvent(...) call. And the older fireEvent(...) method does not trigger the "default action" [whatever that means].)

On the other side, custom arguments are accessed the same way regardless of whether the HTML5 or the older method of setting up the event was used. It will look something like this:

function customhandler(evt) {
        alert(evt.detail.own);

Where some of your custom values are in fact objects themselves, the dot notation can get so long it may look like a typo ...but it's not. For example:

function customhandler(evt) {
        alert(evt.detail.args.X);

It appears some of this may work slightly differently in IE 9 and below, though. Hopefully the problems are simply the usual ones with attempting to re-use -or even create- properties of an event object. If problems are more pervasive, you could put a "sorry:-(" message on your website, or you could wait for IE6/7/8/9 to die, or you could try to cross-browser hack it yourself, or you could use some sort of shim/fallback. It's not clear to me whether it's better to find a shim that "looks exactly like" the conventional interface, or to use the alternate interface provided by the shim for everything (even when the conventional interface is available).

(Disclaimer: Of course I could be wrong about some of the above...:-)


The answers above seem to be deprecated.

Create a new CustomEvent.

var data = { x:20, y:30, rotationY: 60 },
    end = new CustomEvent('MOTION_FINISHED', { detail: data });
    this.dispatchEvent(end);

It seems to only allow the property 'detail' to pass parameters though. I've also read 'bubbles' and 'cancelable' properties are available, but you didn't mention those in your question.

To retrieve your parameters:

function _handler(e){
    var x = (e.detail && e.detail.x) || 0;
}


function fireEvent(name, target) {
    //Ready: create a generic event
    var evt = document.createEvent("Events")
    //Aim: initialize it to be the event we want
    evt.initEvent(name, true, true); //true for can bubble, true for cancelable
    //FIRE!
    target.dispatchEvent(evt);
}

function foobar() {
    alert("foobar");
}

function testEvents() {
    window.addEventListener("foobar", foobar, false); //false to get it in bubble not capture.
    fireEvent("foobar", document);
}

Found this code with 1 minute of Google Search. http://the.unwashedmeme.com/blog/2004/10/04/custom-javascript-events/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜