22

I am tasked to fire custom events on the document without using any libraries like jQuery or prototype.

So I'm ok on Firefox doing this:

function fireCustomEvent(eventData)
{
    if (document.createEvent)   // Firefox
    {
        var event = document.createEvent('HTMLEvents');    // create event
        event.initEvent('myCustomEvent', true, true );     // name event
        event.data = eventData;                            // put my stuff on it
        document.dispatchEvent(event);                     // fire event
    }
    else if (document.createEventObject)    // IE
    {
        xxxxxxxxxxx
    }
}

and now I can fire it like this:

fireCustomEvent({
    category: 'test',
    value: 123
});

and catch it like this (here I can use jQuery):

$(document).bind('myCustomEvent', function (event) {
    doStuff(event);
});

My question is, what can I do to make this work on IE (in other words, where I put the xxxxxxxxxxx )?

I think that the IE-equivalent should look something like this:

 var event = document.createEventObject();
 event.data = eventData;
 document.fireEvent('myCustomEvent', event);

But that doesn't work. IE lets me use only predefined event-names (onclick, etc) and even some of those don't work (onmessage for example)

Any help or ideas are appreciated!

HumanCatfood
  • 960
  • 1
  • 7
  • 20

3 Answers3

25

Add/Remove/Fire Events/Custom Events in Javascript without any frameworks:

var htmlEvents = {// list of real events
    //<body> and <frameset> Events
    onload:1,
    onunload:1,
    //Form Events
    onblur:1,
    onchange:1,
    onfocus:1,
    onreset:1,
    onselect:1,
    onsubmit:1,
    //Image Events
    onabort:1,
    //Keyboard Events
    onkeydown:1,
    onkeypress:1,
    onkeyup:1,
    //Mouse Events
    onclick:1,
    ondblclick:1,
    onmousedown:1,
    onmousemove:1,
    onmouseout:1,
    onmouseover:1,
    onmouseup:1
}
function triggerEvent(el,eventName){
    var event;
    if (typeof window.CustomEvent === 'function') {
        event = new CustomEvent(eventName);
    } else if (document.createEvent) {
        event = document.createEvent('HTMLEvents');
        event.initEvent(eventName,true,true);
    }else if(document.createEventObject){// IE < 9
        event = document.createEventObject();
        event.eventType = eventName;
    }
    event.eventName = eventName;
    if(el.dispatchEvent){
        el.dispatchEvent(event);
    }else if(el.fireEvent && htmlEvents['on'+eventName]){// IE < 9
        el.fireEvent('on'+event.eventType,event);// can trigger only a real event (e.g. 'click')
    }else if(el[eventName]){
        el[eventName]();
    }else if(el['on'+eventName]){
        el['on'+eventName]();
    }
}
function addEvent(el,type,handler){
    if(el.addEventListener){
        el.addEventListener(type,handler,false);
    }else if(el.attachEvent && htmlEvents['on'+type]){// IE < 9
        el.attachEvent('on'+type,handler);
    }else{
        el['on'+type]=handler;
    }
}
function removeEvent(el,type,handler){
    if(el.removeEventListener){
        el.removeEventListener(type,handler,false);
    }else if(el.detachEvent && htmlEvents['on'+type]){// IE < 9
        el.detachEvent('on'+type,handler);
    }else{
        el['on'+type]=null;
    }
}

var _body = document.body;
var customEventFunction = function(){
    console.log('triggered custom event');
}
// Subscribe
addEvent(_body,'customEvent',customEventFunction);
// Trigger
triggerEvent(_body,'customEvent');

Live demo

Serg Hospodarets
  • 4,658
  • 4
  • 25
  • 31
  • Any pros/cons on this answer by the experts? – Odys Jan 09 '14 at 13:49
  • May I ask why you check against html events? – Jimmy Kane Jul 18 '14 at 13:49
  • Underrated answer. createEvent is now deprecated, I'd suggest to use `if (typeof window.CustomEvent === 'function') { event = new CustomEvent(eventName, {detail: detail}); }` As a first test, for modern browsers – spoutnik Apr 01 '16 at 11:21
  • @SergeyGospodarets you should test the type of `window.CustomEvent` as in android webkits < 4.3 `window.CustomEvent` exists but is not a constructor @see http://caniuse.com/#feat=customevent. Regards, spoutnik – spoutnik Apr 08 '16 at 14:08
  • it's old but i like this answer very much. Can we attach additional object info with event (I know CustomEvent supports it but not sure about the ie version?) – mr1031011 Feb 14 '17 at 18:05
11

OK Based on that article by dean edwards I wrote this which seems to work but it seems a but hacky. The example below is based on element #two nested inside #one so we can simulate event bubbling as I couldn't see or find a way to bubble custom events in IE.

function bindCustomEvent (el, eventName, eventHandler) {
    if (el.attachEvent) {
        if (!el[eventName]) {
            el[eventName] = 0;
        }
        el.attachEvent("onpropertychange", function (event) {
            if (event.propertyName == eventName) {
                eventHandler(eventHandler);
            }
        });
    }
}

bindCustomEvent(document.documentElement, "fakeEvents", function (evt) {
    alert('document');
});
bindCustomEvent(document.getElementById('one'), "fakeEvents", function (evt) {
    alert('one');
});
bindCustomEvent(document.getElementById('two'), "fakeEvents", function (evt) {
    alert('two');
});

dispatchFakeEvent = function (el, eventName, bubble) {
    bubble = !bubble ? false : true;
    if (el.nodeType === 1 && el[eventName] >= 0) {
        el[eventName]++;
    }
    if (bubble && el !== document) {
        dispatchFakeEvent(el.parentNode, eventName, bubble);
    }
};

document.getElementById('click').attachEvent('onclick', function () {
    dispatchFakeEvent(document.getElementById('two'), 'fakeEvents', true);//false = bubble
});
Derek Henderson
  • 9,388
  • 4
  • 42
  • 71
screenm0nkey
  • 18,405
  • 17
  • 57
  • 75
  • 1
    My pleasure even though i've only tested it in IE7 and 8 – screenm0nkey Apr 06 '11 at 14:53
  • 6
    meh, if people insist on using that thing, they don't deserve any better :-) Thanks for your help! – HumanCatfood Apr 06 '11 at 15:21
  • This is great in many circumstances, but the big hole with it is that it requires a special way of binding to the event. This is fine if you're in control of the code doing the binding, but is problematic if you're creating a control to be used by others, and want that control to have the ability to trigger custom events. Unfortunately, I haven't found a way to truly trigger a custom event in IE <9, so maybe this is the best we can do, and just have to document the non-standard binding syntax for the control. :/ – Elezar Sep 10 '14 at 21:32
  • Is there a reason why the `onpropertychange` event would not be fired if the binding is done on the `document` instead of the `documentElement`? – Deepak Sep 26 '14 at 21:05
3

Prototype uses the ondataavailable event to fire custom events in IE

Knu
  • 14,806
  • 5
  • 56
  • 89
JaredMcAteer
  • 21,688
  • 5
  • 49
  • 65