Dispatch custom Event to a JS object - javascript

I have a object Constructor that I want to dispatch a customEvent from. Then I want to listen to it from the instance of the object.
The code below is an example of what I'm trying to accomplish. Anyone know how or if this is possible.
var example = new Example();
example.addEventListner('customEvent', tempMethod);
function tempMethod(event){
console.log("event working = ", event.message);
}
function Example(){
// dispatch and event from here.
this.dispatchEvent('customEvent', 'message hello');
}

You can use jQuery to create an emitter from a plain object (or from your Example instance).
var emitter = $({});
$(button).click(function() {
emitter.trigger('customEvent');
});
You could also use an emitter library like energy or eventemitter2.
var emitter = energy();
button.addEventListener('click', function() {
emitter.emit('customEvent');
}, false);
Without the button (as in your edited question) you can create your own .on, .off, and .emit methods on your Example.prototype or you can assign them from an emitter instance like this.

Related

Java script how to pass around an object with event being attached

I have a custom object that being passed around. I want to show a toast when a workflow is done.
I am looking for some thing like
object.addEvent("workflowIsDone", ()=> {
toast.open();
});
and when the workflow ends:
object.fireEvent("workFlowIsDone")
I was wondering if some one can tell me how to do it in Javascript
You might add a method to your object:
object.workflowIsDone = () => toast.open();
and call it when the workflow ends:
object.workFlowIsDone()
You can produce new events by using const myEvent = new Event('eventName')
And then add a listener to it:
element.addEventListener('eventName', function () { // ... })
Also you need to dispatch it:
element.dispatchEvent(myEvent)
For passing custom data there's a CustomEvent class that you can use. You can read more about it here

JavaScript Literal Object In seperate Files

Say I have this structure:
File1.js:
var myObject = {
bindEvents: function() {
console.log('Root events binding');
}
}
keyboard-object.js:
myObject.bindEvents: function() {
console.log('Keyboard events binding');
}
mouse-object.js:
myObject.bindEvents: function() {
// extends original bindEvents and adds more functionality
// right now this behavior overrides the original bindEvents method
console.log('Mouse events binding');
}
How can I trigger myObject.bindEvents() and make sure it is fired in each file?
My purpose is to split one big object into separate files and make one method that fires all the corresponding method(s) in each file, as in bindEvents should trigger bindEvents (or keyboardEvents in my case) in the object
You are essentially after a custom events handler for objects here. I would take a look at the one that Backbone.js supplies.
Be ware that you are not assigning an anonymous function to (earlier declared) myObject properties with the described syntax (as in):
myObject.bindEvents: function() {
console.log('Keyboard events binding');
}
What you are doing here is actually labeling the anonymous function with the word "myObject.bindEvents" which doesn't do you any good.
I think that - aside from this error - you are trying to do something like this:
myObject.bindEvents = function() {
console.log('Keyboard events binding');
}
And only Now your myObject has a property method of bindEvents which than you can invoke by simply declaring:
myObject.bindEvents(); later on your script.
Ok eventually I decided to use two (or more) seperate objects and trigger methods by firing events which are set on the document.
So my current solution is this:
myObject.js
var myObject = {
bindEvents: function() {
// some code here
$(document).trigger('myObject:bindEvents');
}
}
secondObject.js
var secondObject = {
bindEvents: function() {
// separate code and logic here
}
}
$(document).on('myObject:bindEvents',function(){
secondObject.bindEvents();
});
This gives me the flexibility to add more separate objects and bind their methods to events which are fired by the myObject object.

Adding an object to a fabric.Canvas without dispatching the `object:added` event

Is there a way of adding an object to a fabric.Canvas instance without dispatching the object:added event?
Currently I'm forced to use the following ugly approach:
var dispatchObjectAdded = true;
canvas.on('object:added', function () {
if (!dispatchObjectAdded) {
return;
}
// handle event..
});
// add normally with dispatch
canvas.add(object);
// add without dispatch
dispatchObjectAdded = false;
canvas.add(object);
dispatchObjectAdded = true;
This works because the object:added event is dispatched synchronously, but I'm sure there's a better way – I just can't find what it is.
You can define a custom property on your object, and check in the event handler if the object that triggered the event has that property.
Here is a small fiddle example.

Delegating a function call in Javascript

Is there a way in Javascript to have a delegate like the ones in c# ?
Example in c#
Object.onFunctionCall = delegate (vars v) {
Console.WriteLine("I can do something in this private delegate function");
};
I would like with my Javascript to have my main object do something over a long time, and shot a delegate once in a while to give a little update. All that without having to change the code itself of my class to adjust for the webpage.
function mainObject() {
this.onUpdate = function() { //Potentially the delegate function here
}
}
var a = new mainObject();
a.onUpdate = Delegate {
$(".myText").text("Just got a delegate update");
}
I dunno if it's clear enough.. havent found ressources on this so I suppose there is just no way to do so ?
NOTE: I am not looking into jquery Click delegates event here, but into delegating a function call like how it works in c#
Let me know
Although the original question was ansered by solving the root problem (observer - pattern) there is a way to implement delegates in JavaScript.
The C# delegate pattern is available in native JavaScript using context binding. Context binding in JavaScript is done with the .call method. The function will be called in the context given by the first argument.
Example:
function calledFunc() {
console.log(this.someProp);
}
var myObject = {
someProp : 42,
doSomething : function() {
calledFunc.call(this);
}
}
myObject.doSomething();
// will write 42 to console;
What you are looking for is an "Observer Pattern", as described eg. here.
But as you are interested in jQuery, you don't need to go the trouble of writing an observer pattern for yourself. jQuery already implements an observer in the guise of its .on() method, which can be invoked on a jQuery collection to cause callback function(s) to fire every time a native or custom event is dispatched.
Here's an example :
$(function() {
//attach a custom event handler to the document
$(document).on('valueChange', function (evt) {
$(this).find("#s0").text(evt.type);
$(this).find("#s1").text(evt.value);
$(this).find("#s2").text(evt.change);
$(this).find("#s3").text(evt.timestamp).toLocaleString();
});
//customEvent(): a utility function that returns a jQuery Event, with custom type and data properties
//This is necessary for the dispatch an event with data
function customEvent(type, data) {
return $.extend($.Event(type||''), data||{});
};
//randomUpdate(): fetches data and broadcasts it in the form of a 'changeValue' custom event
//(for demo purposes, the data is randomly generated)
function randomUpdate() {
var event = customEvent('valueChange', {
value: (10 + Math.random() * 20).toFixed(2),
change: (-3 + Math.random() * 6).toFixed(2),
timestamp: new Date()
});
$(document).trigger(event);//broadcast the event to the document
}
});
Here's a demo, complete with "start" and "stop" buttons for a regular "interval" dispatch of the custom event.
Notes
Under some circumstances, it might be more appropriate to broadcast the event to the four data spans individually.
On the web, you will find mention of a more convenient jQuery.event.trigger({...}) syntax. Unfortunately this was an undocumented feature of jQuery, which disappeared at v1.9 or thereabouts.

Trigger event with parameters

This is pretty annoying. I want to just trigger an event in javascript. I need to pass the event object into the parameters as usual and an additional custom parameter.
In jQuery, this would be super easy:
$('#element').trigger('myevent', 'my_custom_parameter');
But I don't want to use this however. Every other question I have found relating to this has just suggested 'use jQuery!' It's for a plugin I'm developing and to require jQuery for one method is pretty silly. Can anyone point to a way to do the above in vanilla JS that's cross-browser compatible?
You may create custom events http://jsfiddle.net/9eW6M/
HTML
click me
JS
var button = document.getElementById("button");
button.addEventListener("custom-event", function(e) {
console.log("custom-event", e.detail);
});
button.addEventListener("click", function(e) {
var event = new CustomEvent("custom-event", {'detail': {
custom_info: 10,
custom_property: 20
}});
this.dispatchEvent(event);
});
Output after click on the link:
custom-event Object {custom_info: 10, custom_property: 20}
More information could be found here.
Creating an event
To create a simple event, use the Event constructor.
var event = document.createEvent('MyEvent');
However, if you want to pass data along with the event use the CustomEvent constructor instead.
var event = CustomEvent('MyEvent', { 'detail': 'Wow, my very own Event!' });
Dispatching the event
You can then raise the event with targetElement.dispatchEvent.
var elem =document.getElementById('myElement');
elem.dispatchEvent(event);
Catching the event
elem.addEventListener('MyEvent', function (e) { console.log(e.detail); }, false);
For older browsers( Pre-IE9)
You have to use the document.createEvent function.
// Create the event.
var event = document.createEvent('Event');
// Define that the event name is 'build'.
event.initEvent('MyEvent', true, true);
//Any Element can dispatch the event
elem.dispatchEvent(event);
Note that this method is deprecated and should only be used for compatibility purposes.
More help : https://developer.mozilla.org/en-US/docs/Web/Guide/DOM/Events/Creating_and_triggering_events: MDN: Creating_and_triggering_events
the event object and an additional custom parameter
That's impossible with the native DOM methods. Handlers are called with only one argument, which is the event object. So if there is any data you need to pass along, you need to make it a (custom) property of your event object. You might use the DOM4 CustomEvent constructor for that (see the MDN docs for a cross-browser shim).
Then use dispatchEvent as you would normally with (custom or native) script-triggered events. For IE below 9, you seem to need to use fireEvent.
This is pretty annoying. I want to just trigger an event in javascript. I need to pass the event object into the parameters as usual and an additional custom parameter.
so you can use prototype to extend DOM and create your own methods instead of using jQuery (without new customEvent().
An example here:
(or you can modify it and send callback function in dispatchCustomEvent)
// set custom event to dom objects
Element.prototype.addCustomEventListener = function(eventName, callbackFunction) {
var customEvent = {
name: eventName, // just for info
callbackFunction: callbackFunction // function to use on callback
};
if (!this.customEvents) {
this.customEvents = [];
}
this.customEvents[eventName] = customEvent;
return this;
};
// dispatch or trigger
Element.prototype.dispatchCustomEvent = function() { // args: eventName, args for callback
var args = Array.from(arguments);
var eventName = args.shift();
// apply callback function
// you can also add 'this' to the args list and have access to element:
// args.unshift(this)
this.customEvents[eventName].callbackFunction.apply(null, args);
return this; // or return result of callbackFunction
}
// function to call
function foo(something) {
// do some stuff here
console.log('There is ' + something);
}
document.getElementById("mainContainer").addCustomEventListener('sweetEvent', foo);
// somewhere else in the code, or in console you can than execute
document.getElementById("mainContainer").dispatchCustomEvent('sweetEvent', 'my custom attribute');
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>something</title>
</head>
<body id="mainContainer">
some content here
</body>
</html>

Categories