Passing function to .on() in plain object - javascript

I want to call a custom function on mouse enter.
My current code looks like this:
var myFunction = function(element)
{
//do something with element
}
$( selector ).on({
mouseenter: myFunction($(this)),
mouseleave: myFunction($(this))
}, ' selector ');
My problem is that it seems like myFunction() isn't even called. Does this even work or did I mess up something else?

You aren't passing a function. You are calling the function immediately and passing its return value.
Since you want to call the function, with an argument, and the value of that argument isn't determined until the event fires, you need to create a new function.
function use_myFunction_as_event_handler(event) {
myFunction($(this));
}
$('selector').on({
mouseenter: use_myFunction_as_event_handler,
mouseleave: use_myFunction_as_event_handler
}, 'selector');

You are misunderstanding how functions work in javascript. Here's a simple way to make mouseenter call a function.
$(selector).on({
mouseenter: function(event) {
console.log(event);
}
});
This makes sense. When the mouseenter event gets called, the function executes. Great.
Your problem is that this code:
var functionToCall = function(event) {
console.log(event);
}
$(selector).on({
mouseenter: functionToCall(event);
});
does not actually do the same thing as the previous example.
When you put brackets after a function name, you are calling the function. What mouseenter wants is a function reference - javascript will call the function reference you give it for you every time the event occurs.
What we assigned mouseenter to in the first example was an anonymous function reference - we didn't actually call the function we created. Javascript was doing that for us. In the second example, we called the function, so mouseenter was actually set to the return value of the function, not to the function itself.
To fix this, you just need to pass a function reference to the event instead of calling the function. Note, you can't directly pass parameters this way (it's not impossible, but you shouldn't need to), but $(this) will still be the same.
var myFunction = function() {
var element = $(this);
// code...
}
$(selector).on({
mouseenter: myFunction,
mouseleave: myFunction
});

You should call the function as
var myFunction = function(element)
{
//do something with element
}
$('selector').on({
mouseenter: function(){
myFunction($(this));
},
mouseleave: function(){
myFunction($(this));
}
}, 'selector');
Since you want to pass the argument in myFunction, you have do define it like above

Related

click event occurs with onload event [duplicate]

I playing around with a function that I want to bind to all the links. At the present the function fires when the page loads, instead of when I click on the link.
Here's my code. (I can post the function showDiv(), if you need to see it.) Can you tell if I'm doing something wrong or stupid here?
$(document).ready(function(){
$('a.test').bind("click", showDiv());
});
Thanks!
You want to pass a reference to a function as a callback, and not the result of function execution:
showDiv() returns some value; if no return statement was used, undefined is returned.
showDiv is a reference to the function that should be executed.
This should work:
$(document).ready(function() {
$('a.test').on("click", showDiv); // jQuery 1.7 and higher
$('a.test').bind("click", showDiv); // jQuery 1.6 and lower
});
Alternatively, you could use an anonymous function to perform a more advanced function:
// jQuery 1.7 and higher
el.on('click', function() {
foo.showDiv(a, b, c);
// more code...
});
// jQuery 1.6 and lower
el.bind('click', function() {
foo.showDiv(a, b, c);
// more code...
});
In some circumstances you may want to use the value returned by a function as a callback:
function function foo(which) {
function bar() {
console.log('so very true');
}
function baz() {
console.log('no way!');
}
return which ? bar : baz;
}
el.click(foo(fizz));
In this example, foo is evaluated using fizz and returns a function that will be assigned as the callback for the click event.
Looks like you're calling the function showDiv directly there (and binding the return result of showDiv() to the click handler instead of binding it directly.
You want something like
$(document).ready(function() { $('a.test').bind("click", showDiv); });
Use the below line. showDiv() will call the function rigth away when that line is executed.
$('a.test').bind("click", showDiv);
Change it to: $('a.test').bind("click", showDiv); (do not put parens around showDiv since you want to pass the function reference).

How to pass parameters to a function that is getting triggered by an event handler?

So the problem is I have an event listener and a function:
$(document).ready(function() {
function insert_hint(element, string){
console.log(string);
}
$('.test').on('click', insert_hint('123', '123'));
});
But If I do it like this, it instantly triggers my function, instead of waiting for the element with class 'test' to be clicked.
How can I prevent it from happening and what is a proper way to pass parameters to a function that is being triggered on an event?
I have a feeling that it's something very obvious and easy, but I'm just missing it.
You can simply do this:
$('.test').on('click', function() {
insert_hint('123', '123');
});
Passing the function inside the click callback function.
More details here: .on() jQuery API Documentation
You need to wrap the function into another function, which will specify its' arguments.
$(document).ready(function() {
function insert_hint(element, string){
console.log(string);
}
$('.test').on('click', function() {
insert_hint('123', '123');
});
});
Outside of wrapping it into an anonymous function like #palash and #ralh demonstrated, you can also use .bind()
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
$(document).ready(function() {
function insert_hint(element, string, evt){
console.log(element, string, evt); // "hello", "world", the click event
}
$('.test').on('click', insert_hint.bind(this, 'hello', 'world'));
});
JSFIDDLE: http://jsfiddle.net/8nahor6L/

How can I add an event for a one time click to a function?

I would like to add a click event listener to a function but would only like it to happen once. How could i do this?
I would like to stay clear of JQuery as well if it is possible please.
EDITED
As the answers that I am getting for this are fully satisfying my need i thought i may make it a bit more clear with context.
I am writing a function to draw a rectangle, first with one click on a button to initiate the rectangle function. Then there are two click event listeners in the drawRectangle function. These are the events i would like to happen only once in the function. Allowing the user to then create another rectangle if they click on the rectangle initiation button again.
Use modern JavaScript!
EventTarget.addEventListener("click", function() {
// Do something cool
}, {once : true});
A Boolean indicating that the listener should be invoked at most once after being added. If true, the listener would be automatically removed when invoked.
- MDN web docs
All modern browsers support this feature
Other reference
You have to use removeEventListener once the event is fired once. However, removeEventListener takes a function as argument, which means you need to declare a named function, add it with addEventListener, and have it removing itself. Example:
function foo() {
// do things, then
removeEventListener('click', foo);
}
addEventListener('click', foo);
function one(el, type, fn) {
function handler(event) {
el.removeEventListener(type, handler);
fn(event);
}
el.addEventListener(type, handler);
}
// use it like
one(window, 'resize', function () {
alert("This triggers just once");
});
Example: http://jsfiddle.net/6njpem7x/
The other answers are correct in that this can be achieved with a named function, but you don't need to declare the function separately. You can use a named function expression:
element.addEventListener("click", function handler(event) {
this.removeEventListener("click", handler);
// ...
});
An alternative, though less optimal, approach is to keep around a variable that keeps track whether the handler was executed:
var wasExecuted = false;
element.addEventListener("click", function(event) {
if (wasExecuted) {
return;
}
wasExecuted = true;
// ...
});
The variable needs to be declared outside the handler but within scope, so that its value persists across event triggers.
Combination of addEventListener and removeEventListener:
element.addEventListener("click", clickFunction);
function clickFunction(e) {
console.log("clicked");
element.removeEventListener("click", clickFunction);
}
jsFiddle
something like this
var el = document.getElementById('something');
el.addEventListener('click', doSomething);
function doSomething() {
el.removeEventListener('click', doSomething);
//code
}
Inside event handler you can use universal: e.target.removeEventListener(e.type, arguments.callee)
Or you can make special function for creating "one time" event listeners:
function oneTimeListener(node, type, callback) {
// create event
node.addEventListener(type, function(e) {
// remove event listener
e.target.removeEventListener(e.type, arguments.callee);
// call handler with original context
// as it happens with native addEventListener
return callback.call(this, e);
});
}
oneTimeListener(document.getElementById("myElement"), "click", myHandler);
You can set a cookie after first click:
document.cookie="click=1; expires=.......";
and add condition to listener - if cookie is set, you omit that.
Another simple solution which I'm using is to add a dummy class to the element to which we are listening so that it will not fire again.
const myButton = document.querySelector('#my-button:not(.init)');
myButton.addEventListener('click', (e) => {
e.preventDefault();
myButton.classList.add('init');
});

Difference between this.show and this.show() function calling?

$(document).ready(function(){
$('html').addClass('js');
var contactForm = {
init: function(){
$('<button></button>',{
text: 'contact me'
}).appendTo('article')
**.on('click', this.show);**
},
show: function(){
console.log('show is clicked');
}
}
contactForm.init();
});
In the onClick call, why does the .on('click', this.show()); gets executed immediately when the dom is loaded and later get only happens on the click of the button.
The brackets at the end mean that the preceding function should be invoked immediately. Without the brackets, it becomes a reference to the function.
Therefore on('click', this.show()); will mean that the show function is invoked on load when the click handler is set, and it's return value is set to the event handler.
Where as on('click', this.show); gives the click handler the reference to the show function, which will be called when the click event happens.
Best practice is to only pass the reference of a function to an event handler - ie. the latter example.
'on()' is a function that (in this case) takes two arguments.
this.show passes a reference to the function named show.
this.show() invokes the function and passes the return value.

How To Access jQuery Event Without Using Anonymous Callback Parameter

Typically, when needing to access an event, you do so via the parameter specified in the callback function:
$button.live("click", function(ev) {
// do something with ev here, like check 'ev.target'
}
But instead (for reasons too complicated to get into here), I do not want to use an anonymous callback function, but instead specify a function to call, like this:
$button.live("click", functionToCall(ev, $(this));
So you'll notice that I included 'ev' as a parameter to functionToCall(), but this obviously won't work because I'm not using the anonymous callback function. But I do still need to access that click event (to check ev.target) within functionToCall(). My question is, how do I access this event? It would be nice if I could do something like this:
$button.live("click", functionToCall($(this));
and
function functionToCall($item) {
var target = $item.event("click").target;
// do something with target
}
Any ideas would be very much appreciated. Thanks.
Original answer
function test(eve) {
alert(eve.type);
alert(this);
//$(this) if you need it as jQuery object
}
$([yourselector]).live("click", test);
You will automatically get the event in the eve parameter.
Answer to extended question in comment
Passing in a parameter makes it a little more difficult. If you need an explanation why I did it like this: Ask.
function helper(customparam) {
return function(eve, selector) { actualFunction(eve, selector, customparam, this) };
}
function actualFunction(eve, selector, customparam, self) {
alert(eve.type);
alert(selector);
alert(customparam);
alert(self); //self is now the element we clicked on
//$(self) if you need it as jQuery object
//using this won't work anymore as this is now window
}
$([yourselector]).live("click", helper([yourparameter]));
You could call a function within the anonymous callback function:
$button.live("click", function(ev) {
functionToCall(ev, $(this));
}
EDIT: I think this may be what you're looking to do (untested):
function handleClick(ev) {
$(this).die("click");
// ...whatever processing to do...
$(this).live("click", handleClick);
}
$button.live("click", handleClick);
I believe the $(this) will refer to the button object in which the function was called.
Remember that jQuery re-assigns this when it calls event handlers, by using the Function methods call or apply. So when functionToCall is invoked, this is the DOM element of $button.
var functionToCall(ev) {
var $this = $(this);
$this.die("click", functionToCall);
// stuff
$this.live("click", functionToCall);
}
$button.live("click", functionToCall);
var mythis = $(this);
var callback = function(ev) {
var target = mythis.event("click").target;
}
$button.live("click", callback);

Categories