How to handle events simpler in javascript? - javascript

As a beginner with javascript, I am following this tutorial . At the top of that page simple forms and the use of an event handler is explained, while at the bottom of the page an exercise to create a simple calculator is given calculator.html.
I have come up with a very cumbersome solution to handle events when a number or operation is pressed. Here is what I have implemented:
function pressingNumber(number) {
document.getElementById("calc-output").innerHTML = number;
}
function press1() {pressingNumber(1);}
function press2() {pressingNumber(2);}
function press3() {pressingNumber(3);}
var button1 = document.getElementById("button-1");
var button2 = document.getElementById("button-2");
var button3 = document.getElementById("button-3");
button1.onclick = press1;
button2.onclick = press2;
button3.onclick = press3;
Is this the way to go? Is there a simpler way? I tried the following syntax which does not seem to work:
function pressingNumber(number) {
document.getElementById("calc-output").innerHTML = number;
}
var button1 = document.getElementById("button-1");
var button2 = document.getElementById("button-2");
var button3 = document.getElementById("button-3");
button1.onclick = pressingNumber(1);
button2.onclick = pressingNumber(2);
button3.onclick = pressingNumber(3);

Look at this line of code:
button1 = document.getElementById("button-1");
What does it do? It calls the function document.getElementById and assigns its return value to button1.
Now look at this line of code:
button1.onclick = pressingNumber(1);
What does this do? It calls the function pressingNumber and assigns its return value to button1.onclick.
So what does pressingNumber(1) return? Well, nothing, since pressingNumber has no return statement.
So you're assigning nothing to button1.onclick, and then wondering... why is it doing nothing? ;)
One of the things you'll learn is that if you just read your code aloud, explaining what it does step by step, you'll quickly solve your own problems. I have a rubber duck on my desk that I explain things to, and most of the time that's all I need to solve a problem.
In this case, you want to stick with the original code. It assigns the function itself, it doesn't call it. It is only called when onclick triggers.

In this particular case, this is your shortest method
<input type="button" value="1" onclick="pressNumber(1)">
<input type="button" value="2" onclick="pressNumber(2)">
function pressNumber(number) {
document.getElementById("calc-output").innerHTML = number;
}
The problem in your original code was that you are calling a function with ()in a place where you have to assign a function.

Note that onclick events always come with a link to the div that triggered the event. You should make use of that to capture which button was clicked. e in below function will refer to the clickevent. e.target will refer to the div, e.target.id will refer to the id of said div.
function buttonClicked(e){
console.log(e.target.id);
console.log('clicked in',document.getElementById(e.target.id).parentNode.id);
}
You could then attach said function to your div like so.
document.getElementById(buttonDivName).addEventListener("click", buttonClicked)

You can use
button1.addEventListener("click", pressingNumber(1));
button2.addEventListener("click", pressingNumber(2));
button3.addEventListener("click", pressingNumber(3));

Related

.addEventListener vs .onclick

I keep reading that there is no difference between the two but I am writing a quiz app and am seeing some differences
For example:
Quiz.prototype.handleGuess = function (id, guess) {
let button = document.getElementById(id);
button.addEventListener('click', function(){
quiz.guess(guess);
console.log(guess);
}
if(!quiz.hasEnded){
quiz.displayNext();
} else {
quiz.displayScore();
};
};
When using an event listener, I will log the guess to the console on the first button choice. When I choose an answer for the second question the console will read not only the new selection but also the choice I made from the previous question. This does not happen when using .onclick() and I am not sure why!
Consider the following code:
var el1 = document.getElementById("someEl1"),
el2 = document.getElementById("someEl2");
function firstHandler() {
alert("First handler");
}
function secondHandler() {
alert("Second handler");
}
el1.addEventListener("click", firstHandler);
el1.addEventListener("click", secondHandler);
el2.onclick = firstHandler;
el2.onclick = secondHandler;
<div id="someEl1">First Element</div>
<div id="someEl2">Second Element</div>
In case 1, clicking on el1 will alert with both messages. In case 2, clicking on el2 will only alert with the second because we overwrote what onclick does with the second assignment.
addEventListener effectively assigns a callback to some internal array of listener callbacks that will all be called whenever the event is triggered.
onclick is a single property with a single value. When you assign to it, the old value is replaced by the new assignment.
I would highly suggest that you do not use the onclick method. It makes code harder to maintain. If you are in a large code base and you set the onclick of an element and then later on another coder also sets the onclick without knowing that that element already had its onclick set, then you will run into a difficult time trying to figure out why your code is broken all of a sudden. Using the event listener pattern makes for more extensible and decoupled code.

Change onclick function in javascript

the code below is used to change the onclick event when pressed, however it only alters the function of the parameter, which it simply will not do.
function addWhere(nameID)
{
document.getElementById('addWhereButton').setAttribute("onclick",addWhere(nameID++), false);
document.getElementById('addWhereButton').onclick = function () {addWhere(nameID++)};
}
neither code works and no one else seems to have asked this specific questions before.
Thanks
EDIT
Further testing shows something complete bizarre, a bit of code to display the nameID like so
document.getElementById('Testing').innerHTML = nameID++;
shows that nameID is actually getting incremented, but the number passed by the onclick never changes.
Like:
function addWhere(nameID) {
console.log(nameID);
};
let nameID = 1;
document.getElementById('addWhereButton').onclick = function () {addWhere(nameID++)};
<button id="addWhereButton">click to increment nameID</button>

My EventListener to a button continues to fire despite ownership being changed, why? (JavaScript)

I have a function, which at the end of its task assigns a button to a new id.
function altChecker() {
var doc = document,
out = [],
appButton = doc.getElementById('appButton'),
//re = /click-me/gi,
output = doc.createElement('p');
output.setAttribute('id', 'output');
EventUtility.addHandler(appButton, 'click', function(e) {
//I have not included all the function details to concentrate on the question
appButton.id = 'appButtonNextChecker';
var appButtonNextChecker = doc.getElementById('appButtonNextChecker');
nextChecker(appButtonNextChecker);
});
}
function nextChecker(newBtnName) {
EventUtility.addHandler(newBtnName, 'click', function(e) {
$('#output').innerHTML = "";
console.log('next Checker, button!')
});
}
So basically there is one button in the DOM assigned to appButton ID initially, and then I change it doing:
appButton.id = 'appButtonNextChecker';
when the altChecker function fires...
Then I assign the button to a new variable, and pass in the variable to the next function...
var appButtonNextChecker = doc.getElementById('appButtonNextChecker');
nextChecker(appButtonNextChecker);
While I can see the buttons' ID change in the DOM, and I see the console.log fire in the nextChecker function,
$('#output').innerHTML = ""; //doesn't fire
AND the altChecker function fires as well (again)?! Haven't I severed the connection to the click function when I reassigned the new ID?
Any help would be appreciated!
Javascript doesn't remember that you initially attached the event through it's id. The event is attached to the element itself, not the ID. It's not like CSS that way.
In fact your variables are still holding the same element as well, so there's no need to create a new variable after changing the ID, either. Since you're using jQuery you can just type $(appButton).unbind(); to remove the event handler. You may also want to look into .on() and .off()
The problem is that you're trying to use the innerHTML property in a jQuery's object.
That property belongs to Element, and it will not work in the way you're using it.
You can use the document.getElementById method, and it will work fine:
document.getElementById('output').innerHTML = '';
Or you can use jQuery's html method:
$('#output').html('');
And you can even use the first element of the jQuery's array, and use innerHTML again:
$('#output')[0].innerHTML = '';
It's up to you, but the first option will be faster, for sure.

Simple onClick Every Other Click Javascript HTML

onclick="HandleAction(\'playnow\');HandleAction(\'stop\');"
Performs the two functions simultaneously. No good since it just does the action \playnow\ and then \stop\ immediately after.
I need onClick to perform the function every other click.
Click 1: \playnow\
Click 2: \stop\
Click 3: \playnow\
etc.
Is there a simple way to achieve this?
Define a var which holds the current state:
var state = false;
function handleAction() {
if (state == false) {
// stuff for 'playnow' action
state = true;
return;
}
if (state == true) {
// stuff for 'stop' action
state = false;
return;
}
}
Declare a global variable and interchange it depending on what is passed:
var switch = "playnow";
function handleAction(a) {
if a === switch {
alert(a);
}
else {
alert(a);
switch = a;
}
}
See my answer to this question.
Lets make a function called toggle that lets you specify actions that happen every other click
var toggle = function (a, b) {
var togg = false;
return function () {
// passes return value back to caller
return (togg = !togg) ? a() : b();
};
};
We would then setup our click handler like this
button.addEventListener('click', toggle(function () {
//play now logic
}, function () {
// stop logic
}));
Your click handler now alternates between the first and second functions with every click.
Yes. You could do something like
var play=false,
button = document.getElementById('playbtn'),
audiotag = document.getElementById('audio');
button.addEventListener('click', function(){
if(play){
audiotag.pause()
play=true;
}else{
audiotag.play();
play=false;
}
})
to make this work you could use html like this:
<div id="audioplayer">
<button id="playbtn">play</button>
<audio id="audiotag" src="path/to/audiofile"></audio>
</div>
so you would add the audio html like above and use getElementById to get each element in javascript. after that you attach an event listener to listen for the click event and call the handler which is the anonymous function. Inside that function, you can use the native play and pause methods directly on the audio object to stop audio when it's playing and then play it again when it's stopped.
there are other attributes you can add to the audio tag to start it playing as soon as the page loads. When you click the button, the play variable is set to true so it will pause on the first click and then sets that to false. A subsequent click will play it again and set the variable to true again and so on
Tyr gave you an answer how to solve your problem. Here you go some notes which can help you design better code.
If you have i.e. one big animation and one button on your web, your code is perfectly ok, to keep the code simple is a good idea. But if you have something like this
<button onclick="...">Animation A</button>
<button onclick="...">Animation B</button>
Then you need better design. If you insert state global var into HandleAction, you break low coupling, HandleAction is bound to your single event and can't be reused elsewhere.
It is good to ask yourself What does this function do? In the first case, it is useful to choose better name, like HandleIntroAnimation. If it handles (any) animation, then it is good to specify it in the parameter.
function HandleAnimation(animation, play) {
if(play) ... // playnow
else ... // stop
}
This indeed does what the name tells. To use it in your code, write a proxy function:
<script>
// If you enhance your web, you only alter this code.
// HandleAnimation stays the same, regardless the changes.
var animationStatus = {}
function ToggleAnimation(animation) {
animationStatus[animation] = !animationStatus[animation];
HandleAnimation(animation, animationStatus[animation]);
}
</script>
<button onclick="toggleAnimation(this)">Animation A</button>
<button onclick="toggleAnimation(this)">Animation B</button>
Finally, you could completely decouple HTML and JS:
animations.js
window.addEventListener("load",function() {
// HandleAnimation and ToggleAnimation definitions goes here
// to avoid collisions in global namespace
var anims = document.getElementsByClassName("animation");
for(var i=0; i<anims.length; ++i) anims[i].addEventListener("click",function() {
ToggleAnimation(anims[i]);
});
});
your html
<script src="animations.js"></script>
<button class="animation">Animation A</button>
<button class="animation">Animation B</button>
and you have animation framework: every element with animation class magically toggles its animation. The animation data could be provided in data-* attribute, data-animation in this case.
Then you can provide it as open-source on github or use someone elses open code to fill the missing parts in your code where you were too lazy to code it yourself. Since many wheels were already invented, the only thing you need to code is usually proxy functions. That's how coders save each others time. Happy coding.

How can I add a link to dynamically created button?

Once the buttons are created, is there anyway I can add a link or use window.location method like this: `window.location = 'nextpage.html?foo=number'. I currently have this
var typeValue = location.search;
var typeStringValue= typeValue.replace("?type=","");
var containers = typeValue.replace("?type=multi","");
var containersValue = parseInt(containers);
var sampleLetter = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
function createButton(buttonName){
var buttonDivBlock = document.getElementById("sampleSets");
var buttonElement = document.createElement("input");
buttonElement.setAttribute("type","button");
buttonElement.setAttribute("name",buttonName);
buttonElement.setAttribute("value","Sample Set"+" "+buttonName);
buttonElement.setAttribute("id",buttonName);
buttonDivBlock.appendChild(buttonElement);
// document.getElementById(sampleLetter[i]).setAttribute('onclick',window.location='SampleInfo.html'+typeStringValue+bottonName);<!--add the button link -->
}
function setButtons(numberOfContainers){
for(i=0;i<numberOfContainers;i++){
createButton(sampleLetter[i]);
}
}
window.onload = function(){
setButtons(containersValue);
}
But document.getElementById("'"+sampleLetter[i]+"'").setAttribute('onclick',window.location='SampleInfo.html'+typeStringValue+bottonName);<!--add the button link -->
returns a null value.
Well, maybe I can help you along with an example:
function getFive() { return 5;}
callOtherFunction("stringArgument", getFive());
The second argument to callOtherFunction is going to be 5, not the getFive function. In many cases, like adding event listeners and AJAX code, you actually want to pass the function itself as an argument, so it can be called later. But if you don't want to bother declaring that function seperately, it looks like this:
callOtherFunction("stringArgument", function() { return 5; });
To make code look cleaner, you can press Enter after the { and make a multi-line function.
Now, all that in mind, take another look at the line you've commented out. Do you see what's missing? (PS. Apologies for the "egging-on" format - I find people get much better at figuring things out if I help them find the solution, rather than just showing it to them)
The sampleLetter variable is not defined where you are trying to use it (judging by commented code). Use the value you had just set to the id attribute a few lines earlier.
document.getElementById(buttonName).setAttribute( /* ... */ );
Or if you are trying to set it in the loop instead of in the createButton function, do not add the single quotes
document.getElementById(sampleLetter[i]).setAttribute( /* ... */ );

Categories

Resources