As the title explain, i'm trying to send data to a function by event handler.
i've tried the following:
canvas.on("mouse:wheel",{name:"spin"}, constructSpin);
function constructSpin(e){
console.log(e.data.name);
}
sadly this is not working :(
is there any way to send data to a function using event handler ?
NOTE: i've found this in fabric document:
on(eventName, handler) → {Self}
so it look like there is no data in on construction !
You should construct and call the constructSpin function in the following way, if you wish to pass some custom data on mouse:wheel event :
canvas.on("mouse:wheel", function(e) {
constructSpin(e, { name: "spin" });
});
function constructSpin(event, data) {
console.log(data.name);
}
The fabric events are sort of syntetic.
You are spinning the wheel on the canvas element and you get back 2 events, one at canvas level and one at object level.
if spin is a particular object on your canvas, or is a name property of your objects you can have:
canvas.on("mouse:wheel", function(opt) {
// opt.e => real event
// opt.target => object where you spinned over
// opt.target.name maybe is what are you looking for
});
If my assumption is wrong, you can just do what is already suggested in another answer:
canvas.on("mouse:wheel", function(opt) {
// opt.e => real event
// opt.target => object where you spinned over
opt.name = 'spin'
yourFunction(opt);
});
Related
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
I'm currently attempting to test some code that uses drag-and-drop. I found some other questions that were kinda related to this, but they were way too specific to help me, or not related enough.
This being a test, I'm struggling on trying to automatically execute code inside a .on('drop',function(e){....} event. The main issue is not that I can't run the code inside, but it's that I can't transfer the dataTransfer property, and I can't seem to fake it because it's read-only. Is there anyway to fake the dataTransfer property or otherwise get around it?
I came up with this JSFiddle that serves as a template of what I'm trying to do: https://jsfiddle.net/gnq50hsp/53/
Essentially if you are able to explain to me (if this is at all possible) how I can possibly fake the dataTransfer property, I should be all set.
Side notes:
I'm totally open to other ways of somehow getting inside that code, like for example, maybe its possible to trigger the event and pass in a fake event object with a fake dataTransfer object.
To see the drag-drop behavior, change the JavaScript load type from no-wrap head to on-Load, then you should see what I'm trying to simulate.
Important to note that I cannot modify any of the code inside the event handlers, only inside the outside function
Using Karma/Jasmine so use of those tools are also possible like spies
Also, I'm using Chrome.
Thanks in advance, and let me know for any questions/clarifications!
You should be able to override pretty much everything you want using Object.defineProperty. Depending on what you want to test it can be very simple or very complex. Faking the dataTransfer can be a bit tricky, since there's a lot of restrictions and behaviors linked to it, but if you simply want to test the drop function, it's fairly easy.
Here's a way, this should give you some ideas as to how to fake some events and data:
//Event stuff
var target = $('#target');
var test = $('#test');
test.on('dragstart', function(e) {
e.originalEvent.dataTransfer.setData("text/plain", "test");
});
target.on('dragover', function(e) {
//e.dataTransfer.setData('test');
e.preventDefault();
e.stopPropagation();
});
target.on('dragenter', function(e) {
e.preventDefault();
e.stopPropagation();
});
//What I want to simulate:
target.on('drop', function(e) {
console.log(e)
//Issue is that I can't properly override the dataTransfer property, since its read-only
document.getElementById('dataTransferDisplay').innerHTML = e.originalEvent.dataTransfer.getData("text");
});
function simulateDrop() {
// You'll need the original event
var fakeOriginalEvent = new DragEvent('drop');
// Using defineProperty you can override dataTransfer property.
// The original property works with a getter and a setter,
// so assigning it won't work. You need Object.defineProperty.
Object.defineProperty(fakeOriginalEvent.constructor.prototype, 'dataTransfer', {
value: {}
});
// Once dataTransfer is overridden, you can define getData.
fakeOriginalEvent.dataTransfer.getData = function() {
return 'test'
};
// TO have the same behavior, you need a jquery Event with an original event
var fakeJqueryEvent = $.Event('drop', {
originalEvent: fakeOriginalEvent
});
target.trigger(fakeJqueryEvent)
}
https://jsfiddle.net/0tbp4wmk/1/
As per jsfiddel link you want to achieve drag and drop feature. jQuery Draggable UI already provides this feature why you can not use that?
For create custom event on your way you have to follow two alternative ways
$('your selector').on( "myCustomEvent", {
foo: "bar"
}, function( event, arg1, arg2 ) {
console.log( event.data.foo ); // "bar"
console.log( arg1 ); // "bim"
console.log( arg2 ); // "baz"
});
$( document ).trigger( "myCustomEvent", [ "bim", "baz" ] );
On above example
In the world of custom events, there are two important jQuery methods: .on() and .trigger(). In the Events chapter, we saw how to use these methods for working with user events; for this chapter, it's important to remember two things:
.on() method takes an event type and an event handling function as arguments. Optionally, it can also receive event-related data as its second argument, pushing the event handling function to the third argument. Any data that is passed will be available to the event handling function in the data property of the event object. The event handling function always receives the event object as its first argument.
.trigger() method takes an event type as its argument. Optionally, it can also take an array of values. These values will be passed to the event handling function as arguments after the event object.
Here is an example of the usage of .on() and .trigger() that uses custom data in both cases:
OR
jQuery.event.special.multiclick = {
delegateType: "click",
bindType: "click",
handle: function( event ) {
var handleObj = event.handleObj;
var targetData = jQuery.data( event.target );
var ret = null;
// If a multiple of the click count, run the handler
targetData.clicks = ( targetData.clicks || 0 ) + 1;
if ( targetData.clicks % event.data.clicks === 0 ) {
event.type = handleObj.origType;
ret = handleObj.handler.apply( this, arguments );
event.type = handleObj.type;
return ret;
}
}
};
// Sample usage
$( "p" ).on( "multiclick", {
clicks: 3
}, function( event ) {
alert( "clicked 3 times" );
});
On above example
This multiclick special event maps itself into a standard click event, but uses a handle hook so that it can monitor the event and only deliver it when the user clicks on the element a multiple of the number of times specified during event binding.
The hook stores the current click count in the data object, so multiclick handlers on different elements don't interfere with each other. It changes the event type to the original multiclick type before calling the handler and restores it to the mapped "click" type before returning:
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.
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.
I am making a custom events object so that I can inject custom events into another object, so far I have (simplified),
function Game() {
new Events(["pause", "resume"], this);
};
function Events(events, obj) {
// Event object for object
obj.events = {};
// For each event
events.forEach(function(event) {
// Attach event array to store callbacks
this.events[event] = [];
}, obj);
// Fire event
obj.fire = function(event) {
////////////
};
// Add event
obj.on = function(event, callback) {
////////////
};
};
My question is, is this the right way to do this? Is it considered ok to call Event from Game and add to Game from Events? It for some reason seems wrong to me, and I do not know why?
Is there any way that I should be structuring this code that I am not aware of?
(I do not want to add Events to Game's prototype for the sole reason that Game has events and is not an extension of Events)
Thank you for taking the time to read my question.
My question is, is this the right way to do this? Is it considered ok to call Event from Game and add to Game from Events?
Yes, it's perfectly fine. This is called the decorator pattern. I don't see a reason for your feeling that it was wrong.
Is there any way that I should be structuring this code that I am not aware of?
Don't use new. Events is not a constructor. A better and more descriptive signature might be
function makeEventEmitter(obj, events) {