$(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.
Related
I have a function in my controller that targets a button, then attaches an event listener, which should call a function on the click event but it is calling it automatically when the page loads.
How do I change this to only call the function when I click on goBtn?
onAfterRendering: function() {
var goBtn = document.getElementById('__xmlview1--smartFilterId-btnGo');
console.log("goBtn = ", goBtn);
goBtn.addEventListener("click", this._onGoClick(event), false);
},
_onGoClick: function(event) {
console.log("Event attaaaaached!!! = ", event);
// do something else
},
The problem is that you are already evaluating your event handler. This calls the _onGoClick method immediately (as soon as this line is reached).
goBtn.addEventListener("click", this._onGoClick(event), false);
What you want to do is pass a function to addEventListener that gets called later.
goBtn.addEventListener("click", this._onGoClick, false);
On a different note your code is meant to break in the near future. The id __xmlview1--smartFilterId-btnGo is dynamically created and can change as soon as you launch the app in a different context.
I know that this works:
$("#btn_1").click(function() {
alert("Btn 1 Clicked");
});
While this just pops up the alert dialog prematurely:
$("#btn_1").click(alert("Btn 1 Clicked"););
My Q is: in the second case, why doesn't the alert wait for the click before executing?
Because when you call a function, the arguments are executed immediately to provide the parameters to pass to the function.
func(arg);
is equivalent to:
var temp = arg;
func(temp);
So when you write:
$("#btn_1").click(alert("Btn 1 Clicked"));
it's equivalent to:
var temp = alert("Btn 1 Clicked");
$("#btn_1").click(temp);
It should be obvious that in this form, the alert happens before calling .click() to add a listener for the event.
In order to delay action, you have to provide a function as the argument. A function definition by itself doesn't cause any of the code to be executed, it only gets executed when it gets called later (this is called a "callback").
It doesn't have to be an anonymous function, you can name it as well.
function myAlert() {
alert("Btn 1 Clicked");
}
$("#btn_1").click(myAlert);
But notice that you just provide the name of the function as the argument to .click(), you don't write myAlert(), because that will call it immediately, not delay until the click event occurs.
As #Titus said, click() expects its argument to be a function, because it wants to execute it as a callback. But you can call another function to return a function:
function alerter(message) {
return function() {
alert(message);
}
}
$("#btn_1").click(alerter("Btn 1 Clicked"));
Notice that alerter() doesn't call alert() directly, it returns another function that will call alert() when it is called. As above, that won't happen until the click event performs its callback.
Here's the best explanation I can think of:
var alertResult = alert('Btn 1 clicked');
button.addEventListener('click', alertResult); // say waaat?
var alertFunction = function() {
alert('Btn 1 clicked');
};
button.addEventListener('click', alertFunction); // Yess!
The click(...) function expects a function as an argument, you're not passing it a function, you're passing it the result of a function.
Consider this: func(1+2) the argument to the func method will be 3 (the result) not 1 + 2 (the operation itself).
My Q is: in the second case, why doesn't the alert wait for the click
before executing?
You are calling the function.
You can reference the function to call when event occurs using either .bind()
$("#btn_1").click(alert.bind(window, "Btn 1 clicked"));
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
I can't understand the order of execution takes place here:
<script>
$(function(){
function f(id){
document.body.innerHTML += "<p>executing handler for div " + id + "</p>";
}
document.getElementById("div1").onclick = function(){
f("1");
}
document.getElementById("div2").onclick = function(){
f("2");
}
document.getElementById("div3").onclick = function(){
f("3");
}
});
</script>
What I want to know is how the 'function' and 'f' are called? Is it like when someone click on 'div' then function gets invoked? If it is so, why the function is on the right side of "=" operator?
When someone clicks on div1 the onclick method triggers function f with a passed value of 1. Ditto when div2/3 are clicked on, f is called with those values.
All f does is change the content of the page to show a message.
I'm not sure why this is using document.body.innerHTML though, I would normally expect to see a div that shows a message, such as document.getElementById('message').innerHTML.
I have a feeling (without checking) that document.body.innerHTML will change the whole content of the page to the value that f outputs. I doubt that is the desired result.
Explained in comments, line by line:
<script>
// this is a jQuery shorthand for $(document).ready. That means, that this function is executed automatically, when the DOM is ready
$(function(){
// declaration of a function that will be executed when it's called from somewhere. 'id' is an argument that can be passed
function f(id){
document.body.innerHTML += "<p>executing handler for div " + id + "</p>";
}
// 'onclick' is an event handler. When you click the div container with the id 'div1', then the function, set after '=', gets executed
document.getElementById("div1").onclick = function(){
// call the function that you declared above with the argument "1"
f("1");
}
document.getElementById("div2").onclick = function(){
f("2");
}
document.getElementById("div3").onclick = function(){
f("3");
}
});
</script>
If I'm understanding you correctly based on your question of "why the function is on the right side of = operator?", your question really related to = function(){ in the following code.
document.getElementById("div1").onclick = function(){
f("1");
}
What this code is doing is assigning an anonymous function to the onclick property of the div1 element.
When a user clicks on the div1 element, this anonymous function is executed. Within the anonymous function, a call is made to the function f passing the string "1".
The reason the anonymous function is needed is because if you were to exclude this and simply have this:
document.getElementById("div1").onclick = f("1");
Rather than calling the f function when the element is clicked, you would immediately call the f function and set the returned value (undefined) to the onclick property. By wrapping it in an anonymous function, you get the desired effect of calling f with the given parameter when the element is clicked.
According to what you have asked
$(function(){
});
gets executed on load of a page
if you want to call function f() you need to call as
$(function(){
f();
});
$(function(){...} is the jQuery function for document.ready. This function is executed as soon as all of the DOM is ready. It is a feature of jQuery. You don't call it explicitly - jQuery handles that for you.
The f() function is attached to the click handlers (onclick) that are defined for the three div elements. When they are clicked, they trigger the f() function.
The function is on the right side of an assignment because what the code is actually saying is replace the default onclick function with the one defined.
HTML
<button id='hello'>Click Me!</button>
JavaScript (wrong)
$('#hello').click(alert('Hello, World!'));
JavaScript (correct)
$('#hello').click(function() {
alert('Hello, World!');
}
I'm wondering why the first JS code triggers on the event load instead of click. Can anyone tell me why function() { [code] } is needed for the script to work properly?
In this example, I used jQuery events, but this is not specific to it, for example, I need to use it with setTimeout, too.
The click function expects another function as a parameter.
In the first case you would be passing the result of calling alert('hello world');, which is null.
The second is just a shorthand for:
$('#hello').click(callback);
function callback(){
alert('hello world');
}
Because .click() is a handler. The first argument is a function to assign. But if you actually pass the function with arguments then it will call the function (in this case alert) and then pass it's return value.
Writing $('#hello).click( function() { } )` is basically a short hand for writing:
var myfunction = function() {
// code
};
$('#hello').click( myfunction );
As you can see in the long hand way, it's passed as a reference to the function instead of the function's return value.
Your first example says "evaluate
alert('Hello, World!')
right now, and pass the result as an argument to click. "
The second says "Define a function which will do the alert when I call it, and pass that whole function as an argument to click.
The function() { ... } syntax is how you declare an anonymous function in Javascript. jQuery uses lots of these to specify that some action will be performed later, like when an event occurs. You can think of it as delaying the execution of your function until necessary. Without this syntax, whatever code you place there is evaluated immediately, which is not what you want for an event handler.
You might think, "why isn't JavaScript smart enough to know the difference?" Consider this:
function returnCallback(linkId, data) {
return function(e) {
alert('Clicked on ' + linkId + '. Here is some data: ' + data);
// Maybe do some stuff with e, the event parameter
}
}
$('#some-link').click(returnCallback('some-link', 'some-data'));
$('#other-link').click(returnCallback('other-link', 'different-data'));
This is a contrived example, but it illustrates the power of anonymous functions and closures. This works since returnCallback returns a function.
In the first instance, "JavaScript wrong", you're actually calling alert('Hello, World!') at the point that the script is loaded. Now, the reason you pass the .click function a function is because it can call it at any point. Essentially, you're packing code together to be run (or not run at all) at any point when you put it in a function.
$('#hello').click(alert('Hello, World!')); is attempting to run alert('...') and pass its return value to the .click() function which will not work as expected.
This is because JavaScript evaluates everything and during this process your alert is invoked. You can use anonymous function or you can also use your own custom function as implemented below:
<script language="javascript" type="text/javascript">
$("#mybutton").click(clickFired);
function clickFired() {
alert('click fired');
}
</script>
The parameter required for the .click() function is a Function. Therefore $("#hello").click(function { [code] }); is required. Because there's nothing to return by alert().
The click function here assigns a value to the event handler.
With the first ("wrong") code you're assigning a value of alert('Hello, World!') which is itself a function call, so it's going to be immediately evaluated and hence appear at load.
With the second ("correct") code you're now assigning a new anonymous function which is not executed itself, just instantiated at load. Hence this will work as expected later.
somefunction(alert('hello! world'));
this would mean you want to pass to somefunction the return value of alert("hello! world").
jquery click expects a callback that it should fire upon click on the element. so you put it in a function which does not execute unless someone (here jquery) calls it explicitly.