How can I pass arguments to anonymous functions in JavaScript? - javascript

I'm trying to figure out how to pass arguments to an anonymous function in JavaScript.
Check out this sample code and I think you will see what I mean:
<input type="button" value="Click me" id="myButton" />
<script type="text/javascript">
var myButton = document.getElementById("myButton");
var myMessage = "it's working";
myButton.onclick = function(myMessage) { alert(myMessage); };
</script>
When clicking the button the message: it's working should appear. However the myMessage variable inside the anonymous function is null.
jQuery uses a lot of anonymous functions, what is the best way to pass that argument?

Your specific case can simply be corrected to be working:
<script type="text/javascript">
var myButton = document.getElementById("myButton");
var myMessage = "it's working";
myButton.onclick = function() { alert(myMessage); };
</script>
This example will work because the anonymous function created and assigned as a handler to element will have access to variables defined in the context where it was created.
For the record, a handler (that you assign through setting onxxx property) expects single argument to take that is event object being passed by the DOM, and you cannot force passing other argument in there

What you've done doesn't work because you're binding an event to a function. As such, it's the event which defines the parameters that will be called when the event is raised (i.e. JavaScript doesn't know about your parameter in the function you've bound to onclick so can't pass anything into it).
You could do this however:
<input type="button" value="Click me" id="myButton"/>
<script type="text/javascript">
var myButton = document.getElementById("myButton");
var myMessage = "it's working";
var myDelegate = function(message) {
alert(message);
}
myButton.onclick = function() {
myDelegate(myMessage);
};
</script>

The following is a method for using closures to address the issue to which you refer. It also takes into account the fact that may which to change the message over time without affecting the binding. And it uses jQuery to be succinct.
var msg = (function(message){
var _message = message;
return {
say:function(){alert(_message)},
change:function(message){_message = message}
};
})("My Message");
$("#myButton").click(msg.say);

By removing the parameter from the anonymous function will be available in the body.
myButton.onclick = function() { alert(myMessage); };
For more info search for 'javascript closures'

Event handlers expect one parameter which is the event that was fired. You happen to be renaming that to 'myMessage' and therefore you are alerting the event object rather than your message.
A closure can allow you to reference the variable you have defined outside the function however if you are using Jquery you may want to look at its event specific API e.g.
http://docs.jquery.com/Events/bind#typedatafn
This has an option for passing in your own data.

<input type="button" value="Click me" id="myButton" />
<script type="text/javascript">
var myButton = document.getElementById("myButton");
myButton.myMessage = "it's working";
myButton.onclick = function() { alert(this.myMessage); };
</script>
This works in my test suite which includes everything from IE6+. The anonymous function is aware of the object which it belongs to therefore you can pass data with the object that's calling it ( in this case myButton ).

The delegates:
function displayMessage(message, f)
{
f(message); // execute function "f" with variable "message"
}
function alerter(message)
{
alert(message);
}
function writer(message)
{
document.write(message);
}
Running the displayMessage function:
function runDelegate()
{
displayMessage("Hello World!", alerter); // alert message
displayMessage("Hello World!", writer); // write message to DOM
}

Example:
<input type="button" value="Click me" id="myButton">
<script>
var myButton = document.getElementById("myButton");
var test = "zipzambam";
myButton.onclick = function(eventObject) {
if (!eventObject) {
eventObject = window.event;
}
if (!eventObject.target) {
eventObject.target = eventObject.srcElement;
}
alert(eventObject.target);
alert(test);
};
(function(myMessage) {
alert(myMessage);
})("Hello");
</script>

What you have done is created a new anonymous function that takes a single parameter which then gets assigned to the local variable myMessage inside the function. Since no arguments are actually passed, and arguments which aren't passed a value become null, your function just does alert(null).

If you write it like
myButton.onclick = function() { alert(myMessage); };
It will work, but I don't know if that answers your questions.

Related

Svelte value not updating on screen when passing a value to a function

A little confused on why the below isn't working. I have tried this where I don't pass an argument to the function and can get the UI to update but if I pass the argument in and do the same exact stuff to it it updates it in the code and I can console.log it out but the UI is not updated.
This Works:
<script>
import { text, toggle_class } from "svelte/internal";
let line1 = {name:"line 1", display:"some text here", originalText:"some init text", visible:true};
function toggleView(){
line1.visible = !line1.visible;
if(!line1.visible) line1.display = "*************"
else line1.display = line1.originalText
};
</script>
<main>
<button on:click="{toggleView}">{line1.display}</button>
</main>
This does NOT work:
<script>
import { text, toggle_class } from "svelte/internal";
let line1 = {name:"line 1", display:"some text here", originalText:"some init text", visible:true};
function toggleView(field){
field.visible = !field.visible;
if(!field.visible) field.display = "*************"
else field.display = field.originalText
};
</script>
<main>
<button on:click="{toggleView(line1)}">{line1.display}</button>
</main>
I think it might be because I'm assigning this to a local variable from Svelte's point of view but I'm not sure how else I would call a function to make this reusable since I would be doing this for a bunch of lines.
Any help would be appreciated.
UPDATE - Solved
Below works based on Thomas' answer below:
<script>
import { text, toggle_class } from "svelte/internal";
var lines = {
line1: {
name: "line 1",
display:"some text here",
originalText:"some init text",
visible:true
}
};
function toggleView(field) {
return function() {
lines[field].visible = !lines[field].visible;
if (!lines[field].visible) {
lines[field].display = "*************";
} else {
lines[field].display = lines[field].originalText;
}
}
}
</script>
<main>
<button on:click="{toggleView('line1')}">{lines.line1.display}</button>
</main>
When you set on:click to toggleView(line1), the function is executed right away, just as if you'd set it to toggleView() instead of toggleView in your other, working example.
You have two ways to fix this. The most common approach is to turn your on:click handler into a lambda/anonymous function:
<button on:click="{() => toggleView(line1)}">{line1.display}</button>
The other, less common approach is to modify your handler function and turn it into a curried function:
function toggleView(field) {
return function() {
field.visible = !field.visible;
if(!field.visible) field.display = "*************"
else field.display = field.originalText
};
};
in which case on:click={toggleView(field)} will return a function that will be bound to the click handler, and that function will actually execute when the button is clicked.
In raw HTML + JS, an inline event handler like onclick is actually a bit of code that will be executed when the event happens. In particular, if you use a function in your handler, you must call it:
Example (not Svelte):
<button onclick="toggleView()" />
In contrast, in Svelte, a event handler is expected to be a function, that will be called when the event happens.
OK because toggleView is a function:
<button on:click={toggleView} />
Not OK because it calls toggleView() every time the markup is rendered (i.e. when reactive vars change), and _the return value of togggleView() is bound to the click event:
<button on:click={toggleView()} />
If you need to pass local arguments to an event handler, then you need to wrap the function to still get what you want (that the whole is called when the event happens, not when the markup is rerenred):
Example, OK + argument:
<button on:click={() => toggleView(line1)} />
Note that here, the handler is () => toggleView(line1), not toggleView(line1).

Define the order of execution of functions after event in javascript

Just, before reading, I have read about this thread: Order of execution of functions bound to an event in Javascript but its not helping. Actually,
I have an anonymous function, define like that:
<input type="button" name="blablabla" value="Send" onclick="javascript:blablabla">
So, this function is on a button, use to validate forms. As you can see, It's an anonymous function, and I don't have any access on this code. This function start when I click on it. Okay, I have understood that
But, this function is not totally full, and I want to add my own, with her own logic of check. So I want my checks first, and then call the anonymous function. Here is my code:
function check() {
console.log("debut de check");
var participant = document.getElementById("new_participant_name");
var participant1 = document.getElementById("new_participant2_name");
var participant2 = document.getElementById("new_participant3_name");
participant = participant.value;
participant1 = participant1.value;
participant2 = participant2.value;
var trois_participants = (participant2) ? true : false;
if (!participant1 || !participant)
{
console.log("pas de participant1 ou participant, sert à rien de gérer la suite");
//if the script come here, I want to stop processing, and don't want to call the anonymous function.
return ;
}
}
window.onload = function()
{
document.getElementById("InsertButton").addEventListener('click', function () {
check();
})};
So, I want to call my function (check) before the anonymous function, but, with the same event. I don't know if I am totally understable... thanks per avance
EDIT: Sorry guys, My code have a bug before, yes the code is inlined, I will try all of your solutions tomorrow, thanks guys
If (and only if) the existing handler is attached using an inline onclick="..." handler, you can obtain its value, and then overwrite it:
window.onload = function() {
var el = document.getElementById('InsertButton');
var old_click = el.onclick;
el.onclick = undefined;
el.addEventListener('click', function() {
check();
old_click(this);
});
}
Why not create your own handler??
Element.prototype.myEventListener=function(name,func){
this.addEventListener(name,function(){
if(!check()){return;}
func();
});
};
Now you can do:
document.body.myEventListener("click",function(){
alert("t");
});
Check will always be called before the registered handler.
Note, to block the call, check must return false:
function check(){
return false;//no custom eventlistener fires
return true;//all will fire
}
Use the useCapture flag so you can intercept the event while it's travelling down to the button.
At that point you can perform your check, and if it fails you can call stopPropagation on the event to prevent it from reaching the handlers that are attached to its bubbling phase.
Also, by nature, events are quite bad at managing the order of execution. In general they depend on the order of registration of the listeners.
// code over which you have no control and can't change
var btn = document.getElementById("greeter");
btn.addEventListener("click", function() {
console.log("hello");
})
// code you can add later
function check() {
return Math.random() > 0.5;
}
window.addEventListener("click", function(e) {
var greeter = document.getElementById("greeter");
if (e.target === greeter && !check()) {
e.stopPropagation();
}
}, true)
<button id="greeter">hello world</button>

JavaScript not allowing input before running

Im having issues with this javascript running prior to the user input, can someone help me fix this.
im just trying to make a little html page with a textbox and a button, that then clicked opens a new windows with a modified URL.
<input type="text" name="enter" class="enter" value="" id="lolz" />
<button type="button" id="the_button">Count</button>
document.getElementById('open').addEventListener('click', myFunction());
function myFunction() {
var button = document.getElementById("the_button");
var siteid = document.getElementById('lolz').value
button.onclick = count();
function count() {
window.location = "http://www.websiteimusing.com/" + siteid;
}
}
You can check the code out here
The Actually generate output from that website's code is this
Updated Code
document.getElementById('the_button').addEventListener('click', myFunction);
function myFunction() {
var button = document.getElementById("the_button");
var siteid = document.getElementById('lolz').value
button.onclick = count();
function count() {
window.location = "http://www.websiteimusing.com/" + siteid;
}
}
There's no element with id open in your code, so you're trying to add an event listener to null. The console will tell you the same:
Uncaught TypeError: Cannot call method 'addEventListener' of null
Also make sure to remove the parens from your event listener function, as the other posters have stated.
Change to:
document.getElementById('open').addEventListener('click', myFunction);
When you put () after a function name, it means to call the function at that time.
On this line
document.getElementById('open').addEventListener('click', myFunction());
you are calling the function by adding the ()
change that to:
document.getElementById('open').addEventListener('click', myFunction);

javascript onclick not firing on button click

I am trying to call a JS function when the user clicks a button. But the onclick event is not being fired. The developer tools shows me the following error:
Error executing:
function (/*Event*/ e){
// summary:
// Handler when the user activates the button portion.
if(this._onClick(e) === false){ // returning nothing is same as true
e.preventDefault(); // needed for checkbox
}else if(this.type == "submit" && !this.focusNode.form){ // see if a nonform widget needs to be signalled
for(var node=this.domNode; node.parentNode/*#5935*/; node=node.parentNode){
var widget=dijit.byNode(node);
if(widget && typeof widget._onSubmit == "function"){
widget._onSubmit(e);
break;
}
}
}
}
ReferenceError
arguments: Array[1]
get message: function () { [native code] }
get stack: function () { [native code] }
set message: function () { [native code] }
set stack: function () { [native code] }
type: "not_defined"
__proto__: Error
Here is my code:
HTML
<td>
<button dojoType = "xwt.widget.form.TextButton" id = "pingButton" baseClass = "defaultButton" onclick = "onPing();">Ping
</button>
</td>
JS:
onPing : function() {
alert('works');
}
Any suggestions on what to do?
In lieu of continuing a rather bang-head-against-table thread, I will explain to both the OP and others why he is having problems.
Problem 1: The OP did not post all relevant code. The OP is apparently new to both OOP and SO and he made the fatal error of assuming less is more. We can see that there is an onPing function which is part of an object as per the colon : syntax. If he were to post all of his code, his javascript would look something like this:
var myObject = {
onPing: function() {
alert("works");
}
};
It should be noted here that I am not sure what the name of his object is. I used the name myObject so as to imply "your object name here".
Problem 2: There is an onclick function which is defined inline with a button. This is not good practice and can lead to bugs... especially when so many cut-and-paste javascript snippets are written inside of closure:
(function() {
/*
This is an example of closure.
Any variables/objects/functions defined in here are not accessible to the outside world
*/
})();
Problem 3: The code appears to rely on an attribute type with a value submit. Therefore the button should have that attribute set:
<button type = "submit" dojoType = "xwt.widget.form.TextButton" id = "pingButton" baseClass = "defaultButton" onclick = "onPing();">Ping</button>
While a quick and dirty solution might be to declare a global function called onPing, this might cause problems with other libraries, makes the code more difficult to maintain, and is just plain ol' bad practice and should never be encouraged. So lets explore a better solution which will do the following:
Show complete working code
Define objects within closure
Bind events through code, not inline
Here goes...
<button type="submit" dojoType="xwt.widget.form.TextButton" id="pingButton" baseClass="defaultButton">Ping</button>
<script>
(function() {
var myObject = {
onPing: function() {
alert("works");
}
};
document.getElementById('pingButton').onclick = myObject.onPing;
}());
</script>
And to be super nice, we include a jsfiddle.
This works
function onPing() {
alert("this");
}
Can leave button as it is....
<button dojoType = "xwt.widget.form.TextButton" id = "pingButton" baseClass = "defaultButton" onclick = "onPing();">Ping</button>

Calling JavaScript functions from HTML

How do I execute a JS object's function property from an HTML link?
I have the following JS:
function Tester(elem) {
this.elem = document.getElementById(elem);
}
Tester.prototype.show = function() {
this.elem.innerHTML = 'test';
};
Tester.prototype.test = function() {
alert("a");
};
​
Here is the HTML:
<script type="text/javascript">
var test = new Tester("test");
test.show();
</script>
When I click on the link that gets rendered, it cannot identify the test() function. How would I get it so when a user clicks on the link, the test() function is executed?
The proper way would be to create a DOM element and attach the event handler with JavaScript:
Tester.prototype.show = function() {
var a = document.createElement('a'),
self = this; // assign this to a variable we can access in the
// event handler
a.href = '#';
a.innerHTML = 'test';
a.onclick = function() {
self.test();
return false; // to prevent the browser following the link
};
this.elem.appendChild(a);
};
Since the event handler forms a closure, it has access to the variables defined in the outer function (Tester.prototype.show). Note that inside the event handler, this does not refer to your instance, but to the element the handler is bound to (in this case a). MDN has a good description of this.
quirksmode.org has some great articles about event handling, the various ways you can bind event handlers, their advantages and disadvantages, differences in browsers and how this behaves in event handlers.
It's also certainly helpful to make yourself familiar with the DOM interface.

Categories