Can I get event.target when there are nested jQuery calls - javascript

I am trying to find the event DOM target when there are nested jQuery calls. If there was only one level of call, then event.target would get the DOM target and I could go from there. But how to get through nested calls?
I am testing with a Javascript function
jQuery(document).bind('gform_post_render', function(event, formID){
jQuery("#id").val(event.target.nodeName);
});
I can look at event.target.nodeName and see that it is "#document". I assume that is because the trigger which called this function was something like
jQuery(document).trigger('gform_post_render', ...);
And I think there is another level or two of calls above that.
What I'd like to be able to do is something like
event.trigger.event.trigger.closest(.classname).attr("attname");
although I realize that 'event.target.event.target' is not allowed.
Is there any way to do this?
BTW, what I am trying to do is extract a piece of data from the HTML that is going though a couple of WordPress plugins (popup and gravity forms) that do the jQuery calls. So I have no ability to change things, just trying to deal with what they did.

You can pass a data argument to trigger, and then access it within the handler. So you pass it like this:
$(document).trigger('gform_post_render', {target: event.target});
and then in the handler:
$(document).on('gform_post_render', function(event, data) {
var target = data.target;
...
});

Related

Appending function to Custom Event in Prototype JS

I'm working with a 3rd party product where I am extending the UI with my own custom functionality. Within part of that I need to call an event after the UI has been updated with an AJAX call. Luckily the app fires a call to a Custom Event using the Prototype JS library after the call is complete, like this:
$(document.body).fire("ns:customevent");
If I add my own custom event with the same name then this works as expected
$(document).observe("ns:customevent", function(event) {
//do custom stuff here
});
[I could not get $(document.body).observe() to work here but I don't think that really matters.]
My concern here is that there may be other parts of the app that have registered functions against that event, and I am (blindly) overwriting them with my own, which will lead to issues further down the line.
Does Prototype append custom functions even though they have the same name or does it in fact overwrite them? If it does overwrite them then how can I append my function to anything that is already existing? Is there anyway of viewing what
I would imagine something like this, but I hardly know Protoype and my JS is very rusty these days.
var ExistingCustomEvent = $(document.body).Events["ns:customevent"];
$(document).observe("ns:customevent", function(event) {
ExistingCustomEvent();
//do custom stuff here
});
I can't add my event handler or add in code to call my own function, I want to try avoiding the 3rd party library (if that would even be possible).
Thanks.
As an FYI for anyone else that stumbles upon this question, following the comment from Pointy it turns out that Prototype does append the functions to the custom event.
I verified this by trying the following and both alerts fired.
$(document).observe("ns:customevent", function(event) {
alert("ALERT 1");
});
$(document).observe("ns:customevent", function(event) {
alert("ALERT 2");
});
Great :)

Using jquery Callbacks.fire method as a event handler

So I've got a jquery project where I'm using an external class that has callback style events.
Meaning, it has an "onSave" property that takes one function. However, I need to more than one other components to hook into it.
What I've settled on for now, goes like this:
var saveCallbacks = $.Callbacks();
saveCallbacks.fire.callbacks = saveCallbacks;
globalDoodad.onSave = saveCallbacks.fire;
which allows me to do this in my other components:
globalDoodad.onSave.callbacks.add( myMethod );
Is there a better way to handle this? It seems to be working ok, just has a bit of a smell to it.

How does Ractive's proxy-load work?

I want to know when a DOM element generated by Ractive is ready. In my case, I want to use jquery to attach an autocomplete function onto the element. Ideally it would go something like this:
Template:
{{#list}}
<input type="text" proxy-load="attach-typeahead">
{{/list}}
Javascript:
ractive.on("attach-typeahead", function(event){
$(event.node).typeahead(...);
})
But the event never fires even though I remeber seeing proxy-load mentioned somewhere in the documentation. What's the proper way to do what I'm trying to do? Thanks.
Codler's answer is spot on - transitions can be used to attach behaviour to nodes (and detach it, with outro).
As of the latest (0.3.8) version, there's another method, which behaves similarly but is slightly more streamlined for this purpose: decorators.
The documentation hasn't been written yet (my bad), but you can see a typeahead decorator here. A decorator is simply a function that gets called as soon as a node is added to the DOM, and which returns an object with a teardown() method that gets called as soon as the node is removed from the DOM.
You can make a decorator globally available like so:
Ractive.decorators.foo = function ( node ) {
// do some setup work with the node here...
return {
teardown: function () {
// do any necessary cleanup here
}
};
};
Or you can specify per-instance decorators, as in the fiddle.
Another decorator example here, this time a sortable list.
The proxy-events are mentioned here in the documentation of ractive. Your example doesn't work because the input element does not have a native load event.
All the ractive functions have a complete function callback that fires when the rendering has completed. Maybe you can use that.
You can use the intro attribute. It is a transition in ractive. When the DOM are created, intro will be called.
You can find more info here https://github.com/RactiveJS/Ractive/wiki/Transitions

jQuery Plugin - Public method - Data only targeting one element

I'm trying to write a plugin that will select multiple elements and then apply some private methods to them (see code below). Then I also want to give the user the ability to trigger the activation of the plugin's methods manually with a .activate() function.
Here is my code :
MARKUP : https://github.com/simonwalsh/jquery.imagepox/blob/master/demo/index.html
JS : https://github.com/simonwalsh/jquery.imagepox/blob/master/dist/jquery.imagepox.js
Basically, when I select multiple items and then try to use the manual activation like so :
$(".pox-wrapper").imagepox({ // NOTE: selects two elements
manualActivation: true
});
var manual = $(".pox-wrapper").data('imagepox');
setTimeout(function(){
manual.activate();
}, 5000);
It will only apply the activate() method to the first element in the query...
This is my first jQuery plugin and I've been able to handle everything so far but I'm not sure about this one or even if it is the right way to effectively call a public method. I also tried using a custom event with an event listener in the plugin but it still only applies the methods on the first element in the page.
Thanks in advance :)
its not your plugin's fault. data does not work like that, it doesnt know how to return data from a collection of elements. Because think about it, each element in the collection contains its own data object!
So when you call data on a collection, it returns the data from the first one. The quick solution would be to change the innards of the setTimeout into a loop over all the elements in the set and call activate on them.
setTimeout(function(){
$(".pox-wrapper").each(function(){
$(this).data('imagepox').activate();
})
}, 5000);
It seems to me that you want to add functions to collections of jquery objects. This is the usecase of a jquery plugin. You can create a lightweight one like this:
$.fn.imagepox.activate = function(){ //do this after you create your plugin!
return this.each(function(){
var $this = $(this);
var data = $this.data('imagepox');
if(data){
data.activate();
}
});
};
now you can call it like this:
$(".pox-wrapper").imagepox.activate()

Listening and firing events with Javascript and maybe jQuery

In my JavaScript and Flex applications, users often perform actions that I want other JavaScript code on the page to listen for. For example, if someone adds a friend. I want my JavaScript app to then call something like triggerEvent("addedFriend", name);. Then any other code that was listening for the "addedFriend" event will get called along with the name.
Is there a built-in JavaScript mechanism for handling events? I'm ok with using jQuery for this too and I know jQuery makes extensive use of events. But with jQuery, it seems that its event mechanism is all based around elements. As I understand, you have to tie a custom event to an element. I guess I can do that to a dummy element, but my need has nothing to do with DOM elements on a webpage.
Should I just implement this event mechanism myself?
You have a few options:
jQuery does allow you to do this with objects not associated with the document. An example is provided below.
If you're not already using jQuery on your page, then adding it is probably overkill. There are other libraries designed for this. The pattern you are referring to is called PubSub or Publish/Subscribe.
Implement it yourself, as you've suggested, since this is not difficult if you're looking only for basic functionality.
jQuery example:
var a = {};
jQuery(a).bind("change", function () {
alert("I changed!");
});
jQuery(a).trigger("change");
I would implement such using MVVM pattern with knockjs library.
Just create an element, and use jquery events on it.
It can be just a global variable, doesn't even have to be connected to the DOM.
That way you accomplish your task easily and without any extra libs.
Isn't it possible to bind onchange events in addition to click events? For instance, if addFriend is called and modifies a list on the page, you could bind the change event to then invoke additional functionality.
$('#addFriendButton').click( function() {
// modify the #friendList list
});
$('#friendList').change( function() {
myOtherAction();
});
This is total Host independent, no need for jQuery or dom in this case!
function CustomEvents(){
//object holding eventhandlers
this.handlers_ = {};
}
//check if the event type does not exist, create it.
//then push new callback in array.
CustomEvents.prototype.addEventListner = function (type, callBack){
if (!this.handlers_[type]) this.handlers_[type] = [];
this.handlers_[type].push(callBack);
}
CustomEvents.prototype.triggerEvent = function (type){
//trigger all handlers attached to events
if (!this.handlers_[type]) return;
for (var i=0, handler; handler = this.handlers_[type][i]; i++)
{
//call handler function and supply all the original arguments of this function
//minus the first argument which is the type of the event itself
if (typeof handler === "function") handler.apply(this,arguments.slice(1));
}
}
//delete all handlers to an event
CustomEvents.prototype.purgeEventType = function(type){
return delete this.handlers_[type];
}
test:
var customEvents = new CustomEvents();
customEvents.addEventListner("event A", function(arg){alert('Event A with arguments' + arg);));
customEvents.triggerEvent("event A", "the args");
EDIT added arguments passing

Categories

Resources