Reputation: 1683
This is possibly duplicated, however, things are changing fast in JavaScript world with new browsers. I'm using some resources that used in AS3 a long time ago and now it's finally popular in JavaScript. However, I still can't make events work in my classes. I did this simple example using Mozilla MDN as guide:
var endEvent = new Event("end");
function MyClass(text){
this.text = text;
this.show = function(){
console.log("MyText: "+this.text);
this.dispatchEvent(endEvent);
}
}
function End(evt){
console.log("Event dispatched: "+evt);
}
function run(){
var MyInstance = new MyClass("I have something to say...");
MyInstance.addEventListener("end", End, false);
MyInstance.show();
}
At the first line, Safari returns: "TypeError: '[object EventConstructor]' is not a constructor (evaluating 'new Event("end")')".
It means won't work? Is there a way to create and dispatch custom events in PURE JavaScript (won't use jQuery or anything like)?
Upvotes: 2
Views: 1661
Reputation: 135187
I had this same question a bit ago
Here's the solution I came up with
requires ecmascript >= 5
function Emitter() {
var eventTarget = document.createDocumentFragment();
function delegate (method) {
this[method] = eventTarget[method].bind(eventTarget);
}
[
"addEventListener",
"dispatchEvent",
"removeEventListener"
].forEach(delegate, this);
}
Now a "class" that uses it
function Example() {
Emitter.call(this);
}
Let's try it out now!
var e = new Example();
e.addEventListener("something", function(event) {
alert("something happened! check the console too!");
console.log(event);
});
e.dispatchEvent(new Event("something"));
Cool!
Let's see it working with your code now. Here's a demo.
// include function Emitter from above
function MyClass(text){
Emitter.call(this);
function show() {
console.log("MyText:", text);
this.dispatchEvent(new Event("end"));
}
this.show = show;
}
function onEnd(event){
console.log("Event dispatched:", event);
}
function run(){
var myInstance = new MyClass("I have something to say...");
myInstance.addEventListener("end", onEnd, false);
myInstance.show();
}
run();
Output
MyText: I have something to say...
Event dispatched: Event {
bubbles: false
cancelBubble: false
cancelable: false
clipboardData: undefined
currentTarget: null
defaultPrevented: false
eventPhase: 0
path: NodeList[0]
returnValue: true
srcElement: null
target: null
timeStamp: 1406332794168
type: "end"
__proto__: Event
}
Lastly, here's a version of Emitter
that's compatible with ecmascript < 5
// IE < 9 compatible
function Emitter() {
var eventTarget = document.createDocumentFragment();
function addEventListener(type, listener, useCapture, wantsUntrusted) {
return eventTarget.addEventListener(type, listener, useCapture, wantsUntrusted);
}
function dispatchEvent(event) {
return eventTarget.dispatchEvent(event);
}
function removeEventListener(type, listener, useCapture) {
return eventTarget.removeEventListener(type, listener, useCapture);
}
this.addEventListener = addEventListener;
this.dispatchEvent = dispatchEvent;
this.removeEventListener = removeEventListener;
}
See document.createEvent for firing events in legacy browsers
You could make a polyfill like this (untested)
if (typeof Event !== "function") {
function Event(type) {
var e = document.createEvent("Event");
e.initEvent(type, true, true);
return e;
}
}
Upvotes: 3
Reputation: 42306
Preaching for my own church here, but I happen to have worked on this very recently and wrote a tiny javascript that handles events and inheritance.
It's all on github if you want to check out some examples:
(contains clickable links)
Upvotes: 1