Javascript convert anonymous function to named function passing clicked object [duplicate] - javascript

I have the following script which does not work
<script type="text/javascript" >
function ADS(e){ alert(e); }
$(document).ready(function(){
$(document).on("dblclick","#an_tnam tr", ADS('hello'));
$(document).on("dblclick","#kv_tnam tr", ADS('world'));
// ....
});
</script>
how can I pass argument to event handler function ADS ?

You can pass extra data to an event handling function and can be accessed using event.data within the handler.
$(document).on('dblclick', '#an_tnam tr', { extra : 'random string' }, function(event)
{
var data = event.data;
// Prints 'random string' to the console
console.log(data.extra);
}
You can also send extra data to any event you like when triggering the event from an external source using the .trigger() method
$('#an_tnam tr').trigger('click', [{ extra : 'random string' }]);
The difference with passing data to the .trigger() method is that .on() expects the handler to take extra arguments of the length of the array passed in. The above would expect the handler to have (only) one extra argument to contain the object passed in.
$('#an_tnam tr').on('click', function(event, obj)
{
// Prints 'random string' to the console
console.log(obj.extra);
}

The .on() function expects a function reference to be passed; what you're doing is calling the function and passing its return value. If you need to pass a parameter you'll need to wrap the call in an anonymous function.
$(document).on('dblclick', '#an_tnam tr', function(event) {
ADS('hello');
});
jQuery always passes its normalized event object as the first argument to the function to be executed.

Actually, there is a very neat simple way to achieve this, with no extra clutter and no anonymous functions, using JS bind():
$(document).on('dblclick', ADS.bind(null, 'hello'));
First parameter is the value you want "this" to have inside callback function.
MOre info in Mozilla Developer Network: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

As Anthony Grist pointed out, the .on() method is expecting a function reference at that part; you're evaluating a function which returns nothing (null).
However, one fun feature of JavaScript is that everything is an object, including functions. With a small modification, you can change ADS() to return an anonymous function object instead:
function ADS(e){
return function(){ alert(e); };
}
http://jsfiddle.net/cSbWb/

function ADS(e){ alert(e); }
$(document).ready(function(){
$(document).on("dblclick","#an_tnam tr", function (e) { ADS('hello') });
});
will do the trick.

function ADS(e) {
return function() {
alert(e);
};
}
Like that when you're doing
$(document).on("dblclick","#an_tnam tr", ADS('hello'));
, it is the returned function that is assigned as event handler (and your string argument is passed when you're assigning the handler, not when it's called).

Related

How to pass arguments in a function reference

I'm looking for a way to save reference to two this objects in one function called after an event triggers in jQuery - this reference to the object the method is defined in (so I can use this.anotherObjectFunction()) and this reference to the object that triggered the event - so that I can use $(this).someJQueryFunction later on. The way I'd like to do it is by passing a this (function object) reference as an argument to the function. Unfortunately, the function is to be called by jQuery, not me, so it's passed as a reference, i.e.
someFunction: function()
{
...
cell.$el.on('click', 'li.multiselect-option', this.myClickFunction);
...
},
myClickFunction: function(objectReference)
{
//It should be able to call methods of that object.
objectReference.anotherFunction();
//And reference to the clicked item.
$(this).html("Don't click me anymore!!!");
}
I'm aware of the fact that I can do something like
cell.$el.on('click', 'li.multiselect-option', myFunction.bind(this));
...
myClickFunction: function(event)
{
this.anotherFunction();
$(event.currentTarget).html("Don't click me anymore!!!");
}
But this workaround doesn't really answer the question as it doesn't show how to pass additional arguments and in the future there may be a necessity to pass another (no, I don't want to register them as fields in the object).
No anonymous functions are allowed unless they can be easily removed with cell.$el.off() function that will remove them and only them (there are some other function associated with the same objects and events at the same time and they should remain intact).
UPDATE:
By no anonymous functions I mean solutions like:
var self = this;
cell.$el.on('click', 'li.multiselect-option', function() {
self.MyClickFunction(self, this);
});
They will not work because I'll have to use cell.$el.off() with the function reference (3-argument prototype) to remove this single function and only it, leaving other functions bound to both the same element and event.
Jquery .on event has option to pass the argument as parameter in event handler like this
cell.$el.on('click', 'li.multiselect-option', {arg1:'arg1' , arg2:'arg2'} , myFunction);
...
myClickFunction: function(event)
{
alert(event.data.arg1);
alert(event.data.arg2);
this.anotherFunction();
$(event.currentTarget).html("Don't click me anymore!!!");
}
Passing data to the handler
If a data argument is provided to .on() and is not null or undefined,
it is passed to the handler in the event.data property each time an
event is triggered. The data argument can be any type, but if a string
is used the selector must either be provided or explicitly passed as
null so that the data is not mistaken for a selector. Best practice is
to use a plain object so that multiple values can be passed as
properties.
or another way
cell.$el.on('click', 'li.multiselect-option', function() {
myClickFunction("hai" , "bye");
});
myClickFunction: function(arg1, arg2)
{
alert(arg1);
alert(arg2);
}
And I would also suggest a plugin-free solution to the question "how to supply a parameter to function reference"
Example
function x(a){
console.log(a);
}
setInterval('x(1)',1000);

Why must callbacks in jQuery be anonomous?

This works just as expected but I don't like it.
$('#login-form').on('submit', function(event){
event.preventDefault();
init.login();
});
var init = {
login: function() {
// do login stuff
}
};
This is what I want but it does not work.
$('#login-form').on('submit', init.login(event));
var init = {
login: function(event) {
event.preventDefault();
// do login stuff
}
};
Why?
It will work, you're calling the function (the value given as a callback will be the result of the function) rather than passing it as a value
$('#login-form').on('submit', init.login);
init.login(event) calls the function init.login, passing the (non-existent) variable event to it. If you want to pass the function itself as callback, don't call it:
$('#login-form').on('submit', init.login);
You will have to declare that function before you pass it though, at this point init.login is undefined.
You're already calling the function in that line (with undefined, there is no event yet). You need to pass the function itself (not its result):
$('#login-form').on('submit', init.login);
Notice that init.login is still an anonymous function, it has no name :-) Also beware that the method is called with this being the login form element, not the init object. If you needed that, you'd use .on('submit', init.login.bind(init)).

Using defined function instead of anonymous function as callback

Why isn't it possible to use a defined function as event callback?
<div id="me">
<input>
</div>
$(document).ready(function(){
// $("#me").on('keyup', 'input', doit()); # doesn't work
// $("#me").on('keyup', 'input', 'doit'); # neither does this
$("#me").on('keyup', 'input', function() {
doit();
}); // well, this one works of course
});
function doit() {
console.log($("input").val());
}
You need to pass the function in as a parameter.
$("#me").on('keyup', 'input', doit);
You should pass the function, not call it
$("#me").on('keyup', 'input', doit)
To clear why that is wrong, see this example:
$("#me").on('keyup', 'input', (function() {
doit();
})());
Here you are passing an anonymous function and invoking it immediately, which is not what the event handler expects.
The problem is not in the difference between anonymous or not, the problem is that you are invoking the function instead of passing it.
When you pass in doit() (with the "()") as the callback, you're actually running the function at that point and passing in the return value of the function (likely undefined) as the callback. If you pass in just a reference to the named function doit then the function will be executed as the callback.
when you say something=function(){ blah } in js, it stores that as text and parses it on the fly - so yes, you can.
For example:
CallMe = function(){ alert("blah!"); }
bobsCallback.setFunction( CallMe );
CallMe is like any other variable, but it's contents is the js for the function.
You can pass it around as a callback, or invoke like so:
alert("calling CallMe...");
CallMe();

triggering the same function, from 2 different click events, with and without parameters

I have a function myFunc that can be triggered 2 different ways: by clicking div1 or div2.
If the click came from div2, I'd like to pass some parameters to the function at the time of the call.
Also, in both cases, I need a reference to the item that was clicked: $(this).
I've tried this code, but the second version (where I'm passing the parameters) gets triggered automatically even without me clicking anything. What am I doing wrong, and do I need to pass this as a parameter in both cases?
$('#div1').live('click', myFunc);
$('#div2').live('click', myFunc('param1 value', 'param2 value'));
function myFunc(param1, param2){
console.log('inside myFunc');
}
Replace your second live call with:
$('#div2').live('click', function() {
myFunc.call(this, 'param1 value', 'param2 value');
});
Or using the new on method in jQuery 1.7+ which is proposed as new standard for binding handlers:
$(document).on('click', '#div2', function() {
myFunc.call(this, 'param1 value', 'param2 value');
});
Your second line is immediately executing myFunc. Instead, wrap it in an anonymous function:
$('#div2').live('click', function() {
myFunc.apply(this, ['param1 value', 'param2 value']);
});
You'll need to use apply or call to preserve the original context (otherwise this in myFunc will be the global window object instead of the clicked element).
I believe it is better for you to pass an anonymous function as the handler of the second, and inside it you call "myFunc" as you want.
Example:
$('#div1').live('click', myFunc);
$('#div2').live('click', function() {
myFunc.call(this, 'param1 value', 'param2 value');
});
Dont use live, its deprecated now. Use on instead.
jQuery provides an easy way to pass data when an event occurs.
This should be the standard way,
$(document).ready(function() {
$("body").on("click","#div1", {param1: "param1",param2: "param2"},myFunc);
$("body").on("click","#div2",myFunc);
function myFunc(event){
console.log(this.id);
if(this.id == 'div1'){
console.log(event.data.param1);
console.log(event.data.param2);
}
}
});
Edit:
I dont know what is your context or requirement, but I would have coded like this,
$("body").on("click","#div1,#div2",function(){
if(this.id == 'div1'){
// the code for div1, use your params here.
}
else{
// the code for div2
}
});
You can not do this on this way.
You must define a function inline, and call myFunc from it.
$('#div1').live('click', myFunc);
$('#div2').live('click', function(){ return myFunc('param1 value', 'param2 value'); } );

jQuery's .click - pass parameters to user function

I am trying to call a function with parameters using jQuery's .click, but I can't get it to work.
This is how I want it to work:
$('.leadtoscore').click(add_event('shot'));
which calls
function add_event(event) {
blah blah blah }
It works if I don't use parameters, like this:
$('.leadtoscore').click(add_event);
function add_event() {
blah blah blah }
But I need to be able to pass a parameter through to my add_event function.
How can I do this specific thing?
I know I can use .click(function() { blah }, but I call the add_event function from multiple places and want to do it this way.
For thoroughness, I came across another solution which was part of the functionality introduced in version 1.4.3 of the jQuery click event handler.
It allows you to pass a data map to the event object that automatically gets fed back to the event handler function by jQuery as the first parameter. The data map would be handed to the .click() function as the first parameter, followed by the event handler function.
Here's some code to illustrate what I mean:
// say your selector and click handler looks something like this...
$("some selector").click({param1: "Hello", param2: "World"}, cool_function);
// in your function, just grab the event object and go crazy...
function cool_function(event){
alert(event.data.param1);
alert(event.data.param2);
}
You need to use an anonymous function like this:
$('.leadtoscore').click(function() {
add_event('shot')
});
You can call it like you have in the example, just a function name without parameters, like this:
$('.leadtoscore').click(add_event);
But the add_event method won't get 'shot' as it's parameter, but rather whatever click passes to it's callback, which is the event object itself...so it's not applicable in this case, but works for many others. If you need to pass parameters, use an anonymous function...or, there's one other option, use .bind() and pass data, like this:
$('.leadtoscore').bind('click', { param: 'shot' }, add_event);
And access it in add_event, like this:
function add_event(event) {
//event.data.param == "shot", use as needed
}
If you call it the way you had it...
$('.leadtoscore').click(add_event('shot'));
...you would need to have add_event() return a function, like...
function add_event(param) {
return function() {
// your code that does something with param
alert( param );
};
}
The function is returned and used as the argument for .click().
I had success using .on() like so:
$('.leadtoscore').on('click', {event_type: 'shot'}, add_event);
Then inside the add_event function you get access to 'shot' like this:
event.data.event_type
See the .on() documentation for more info, where they provide the following example:
function myHandler( event ) {
alert( event.data.foo );
}
$( "p" ).on( "click", { foo: "bar" }, myHandler );
Yes, this is an old post. Regardless, someone may find it useful. Here is another way to send parameters to event handlers.
//click handler
function add_event(event, paramA, paramB)
{
//do something with your parameters
alert(paramA ? 'paramA:' + paramA : '' + paramB ? ' paramB:' + paramB : '');
}
//bind handler to click event
$('.leadtoscore').click(add_event);
...
//once you've processed some data and know your parameters, trigger a click event.
//In this case, we will send 'myfirst' and 'mysecond' as parameters
$('.leadtoscore').trigger('click', {'myfirst', 'mysecond'});
//or use variables
var a = 'first',
b = 'second';
$('.leadtoscore').trigger('click', {a, b});
$('.leadtoscore').trigger('click', {a});
$imgReload.data('self', $self);
$imgReload.click(function (e) {
var $p = $(this).data('self');
$p._reloadTable();
});
Set javaScript object to onclick element:
$imgReload.data('self', $self);
get Object from "this" element:
var $p = $(this).data('self');
I get the simple solution:
<button id="btn1" onclick="sendData(20)">ClickMe</button>
<script>
var id; // global variable
function sendData(valueId){
id = valueId;
}
$("#btn1").click(function(){
alert(id);
});
</script>
My mean is that pass the value onclick event to the javascript function sendData(), initialize to the variable and take it by the jquery event handler method.
This is possible since at first sendData(valueid) gets called and initialize the value. Then after jquery event get's executed and use that value.
This is the straight forward solution and For Detail solution go Here.
Since nobody pointed it out (surprisingly). Your problem is, that $('.leadtoscore').click(add_event); is not the same as $('.leadtoscore').click(add_event('shot'));. The first one passes a function, the second a function invocation so the result of that function is passed to .click() instead. That's not what you want. Here's what you want in vanilla JavaScript terms:
$('.leadtoscore').click(add_event.bind(this, 'shot'));
Function.prototype.bind() passes the function to .click() just like in the first example but with bound this and arguments that will be accessible on invocation.

Categories

Resources