I need to fire a custom event each time when clicked on div with different data attached.
Here is a simplified variant of my code (JSFiddle):
<div onclick="selectItem(Math.random())">click me</div>
<script>
function selectItem(id) {
var event_data = {
myid: id
};
if (!arguments.callee.event)
arguments.callee.event = new CustomEvent("selectItem", {detail: event_data});
arguments.callee.event.detail = event_data; // no success here
document.dispatchEvent(arguments.callee.event);
}
document.addEventListener("selectItem", function(event) {
console.log(event.detail); // same thing all the time :(
});
</script>
But in the event listener function I receive the same data each time the event is fired. I tried to change the event before dispatchEvent but seems it is read only object.
Is there any other options to send different data each time i click on div?
The reason is that detail property of the event can be any object but they are read only, i.e they can be set only when the event is created.Iit is specifically used to provide details regarding the event, and not for attaching data for each dispatch of the event.
interface CustomEvent {
readonly attribute any detail;
};
Probably you can just set a custom property data to the event during each dispatch and access that property.
Try:
function selectItem(id) {
var event_data = {
myid: id
};
if (!arguments.callee.event) arguments.callee.event = new CustomEvent("selectItem");;
arguments.callee.event.data = event_data;
document.dispatchEvent(arguments.callee.event);
}
document.addEventListener("selectItem", function(event) {
console.log(event.data);
});
Fiddle
Or you would need to init the custom Event each time to set the details property like this:
arguments.callee.event.initCustomEvent("selectItem", true, true, event_data);
and details property will have new updated value each time the event is dispacthed.
Demo
Related
I've been working on this for a while. But I think it is going to be difficult for me to simply it for this question.
I have this object. It is a child to an other object.
The child object has an 'action' attribute which executes a fn();
On a mouse click I fire off the action I can see I am executing fn() with no problems.
I want fn() to trigger an event of the parent object.
$('#par).on('trgr.obj', fn(e, dta) { alert('success'); });
$('#par').obj({
chi: { action: fn(dta) {
console.log("doing okay so far");
// Here is where I'm trying to trigger trgr.obj event
// this is what I have so far.
var inst = $.obj.reference(dta.reference);
var objT = inst.get_node(dta.reference);
inst.trgr(
objT, { type: "default" }, "last"
, function (newDta) {
setTimeout(function () { inst.edit(newDta); }, 0);
}
);
}}
});
How does action trigger event 'trgr.obj'?
Any help appreciated.
Are you looking for jQuery to trigger a custom event?
Try $('#par').trigger('trgr.obj')
http://api.jquery.com/on/
I'm having problems to retrieve the argument passed to my eventHandler.
I'm using geous to put a map inside and activeadmin interface. The solution is working on the show page but I didn't get things working on the index page. The idea is to attach the handler to the dragend event on a marker with my model geographic coordinates.
What I do:
map.locations.add($fields.geousable('getLocation'), { draggable: true, on: { dragend: setFieldsLocation }});
and setFieldsLocation is defined below:
function setFieldsLocation (event) {
alert(setFieldsLocation.caller);
console.log(event);
$('.geousable').find("input")[0].value = event.data.lat;
$('.geousable').find("input")[1].value = event.data.lng;
};
So the first line bind the handler (for dragend) and a method inside the geous lib code attachs it and calls it when the event is fired, here is the snippet:
var _onAdd = function (locationMarker, opts) {
// not relevant code
if (options.on) {
for (event in options.on) {
eventHandler = function() {
var handler = options.on[event],
location = locationMarker.location;
return function() {
handler.call(location);
}
}();
google.maps.event.addListener(locationMarker.marker, event, eventHandler);
}
}
};
Debugger shows the location correct location variable when the handler is called, but I can't get the location variable inside my "setFieldsLocation" function. I tried a lot of things. I changed the header of the javascript function, I used event, e, arguments and this kind of things:
console.log("arguments.callee.caller.name = " +
arguments.callee.caller.name);
console.log("arguments.callee.caller.toString() = " +
arguments.callee.caller.toString());
But no luck.
Ideas with an explanation of what is occurring here will be very appreciated.
I am creating a link that changes text when it is clicked. I want the link text to change back to the original text after all the processing is complete. It was working fine, but the code was spread all over my js file, so I am trying to abstract it into a function. This is the function, textToggle. In the textToggle function we are publishing an event. This event is the one that I cannot get to fire off at the right time.
var textToggle = function(data) {
var original_text = $(data.element).text();
var id = data.id;
var $element = $(data.element);
$element.text(data.replacement_text);
$('body').on(data.event, function(e) {
e.preventDefault();
$this.text(original_text);
});
};
Here is the function that sets up the textToggle. At the end of the function, we are triggering another event `clinical.status'.
$('#clinicalPatients').on('click', '[data-role="auth-process"]', function(e) {
e.preventDefault();
var $this = $(this);
var _id = $target.attr('id');
textToggle({
id: _id,
element: $this,
replacement_text: "Processing...",
event: "clinical.status.finished"
});
$('#clinicalPatients').trigger('clinical.status', [{
id: _id,
target: $target,
action: _type
}]);
});
At the end of clinical.status is when I want to fire the event in toggleText, clinical.status.finished. This is the code for that event.
$('body').trigger('clinical.status.finished', [{
id: originalId
}]);
clinical.status.finished is not getting triggered at the right time. There is no other place in the code that is using this, so it has to be the way that I am setting it up. If I leaved that event out of the toggleText function, and drop it in the function where I set up the toggleText function, then everything works like it is supposed to. By putting on event into a separate function, will this cause issues. Please, any help will be appreciated. Thanks.
When I fire a function I want it to apply listeners just to elements I pass, particular this jQuery element.
addEventListeners(this);
function addEventListeners(el) {
$(el).mouseenter(function() {
$(this).stop(true,true).switchClass("", "HIGHLIGHT", 400, "easeInOutQuad");
});
$(el).mouseleave(function() {
$(this).stop(true,true).switchClass("HIGHLIGHT", "", 400, "easeInOutQuad");
});
}
It fires from AJAX result:
$.post(url,{el:wartosc_inputa},function(returned) {
var data = $(returned).hide();
$("#listaElementow").prepend(data);
data.slideDown();
loading();
addEventListeners(this);
});
How to code it good? This code is not passing variables from addEventListeners(this); to function.
in the ajax callback function "this" will be the ajax object i think and no longer an element so you need to save "this" in a variable before the ajax starts.
that = this;
$.post(url,{el:wartosc_inputa},function(returned) {
var data = $(returned).hide();
$("#listaElementow").prepend(data);
data.slideDown();
loading();
addEventListeners(that);
});
Judging from the context of the rest of your success handler, I assume returned is the DOM element you're attempting to bind your handlers to. Assuming this is the case:
$.post(url,{el:wartosc_inputa},function(returned) {
var data = $(returned).hide();
$("#listaElementow").prepend(data);
data.slideDown();
loading();
addEventListeners(data[0]);
// change this ^^^^
// pass the DOM element here, or
// change the addEventListeners function to take a jquery element
});
this in that context is not what you expect it to be. Try this:
var self = this;
$.post(url,{el:wartosc_inputa},function(returned) {
var data = $(returned).hide();
$("#listaElementow").prepend(data);
data.slideDown();
loading();
addEventListeners(self);
});
At row level I catch the event and try to add an extra parameter
onRowClick: function(e){
console.log("Event in row");
e.model = "test";
console.log(e.model) // prints 'test'
}
In main view I catch the same event again
onRowClick: function(e){
console.log("Event in main view");
console.log(e.model) //prints undefined
}
Console:
>Event in row
>test
>Event in main view
>undefined
How can I append an attribute to the event?
The answer is that you don't catch the same event, but rather two (initially) identical events. Changing the first does not change the latter.
If you want to pass data between those events, you would need to store that data elsewhere (e.g. a closure, or if you don't care about the scope save it in the window object).
There are 2 ways that I know of to pass data to a jQuery event. One with with e.data, you can add any properties to e.data like this.
http://www.barneyb.com/barneyblog/2009/04/10/jquery-bind-data/
the other way is to use closures such as:
function myFunc() {
var model = 'test';
var x = {
onRowClick: function(e){
console.log("Event in row");
console.log(model) // prints 'test'
}
}
}
instead of catching the rowClick event in the main view, i suggest you catch it in the row view, and pass it through the backbone event system...
your parentview can bind to it's rows to catch a click.
there are two ways to do this,
trigger a custom event on your row's model, and let the parent bind to every model in the collection, though that seems like a hack and a performance hit.
i suggest doing it with an event aggregator:
var App = {
events: _.extend({}, Backbone.Events);
};
var myGeneralView = Backbone.Views.extend({
initialize: function() {
_.bindAll(this, "catchMyCustomEvent";
/*
and here you bind to that event on the event aggregator and
tell it to execute your custom made function when it is triggered.
You can name it any way you want, you can namespace
custom events with a prefix and a ':'.
*/
App.events.bind('rowView:rowClicked');
},
catchMyCustomEvent: function (model, e) {
alert("this is the model that was clicked: " + model.get("myproperty"));
}
// other methods you will probably have here...
});
var myRowView = Backbone.Views.extend({
tagName: "li",
className: "document-row",
events: {
"click" : "myRowClicked"
},
initialize: function() {
_.bindAll(this, "myRowClicked");
},
myRowClicked: function (e) {
/*
You pass your model and your event to the event aggregator
*/
App.events.trigger('rowView:rowClicked', this.model, e);
}
});