Variable Id Called in JS Function - javascript

I've spent the past couple hours googling and browsing W3Schools and couldn't find a way to do exactly what I wanted. I've found similar articles but they don't answer my question perfectly.
So what I'm trying to do is this, create a JS function that when called in HTML will take the information given to return the appropriate information. E.G, I want there to be two HTML buttons. If the user presses the first button, it calls the function "onclick='show(x, y)'" and x and y which stand for another paragraph and an image. If the user presses the second button, it calls the same function with different variables "onclick='show(x, z)'" which would display the same paragraph as the other button would but would display a different image.
Basically, is it possible for HTML elements to have IDs that can be variable in JS so I that I do not have to create an individual JS function for every single button?
My Javascript:
<script>
var Show = function(elID, elID2) {
var el1 = document.getElementByID(elID);
var el2 = document.getElementByID(elID2);
var both = (elID) + " " + (elID2);
document.getElementById(elID).innerHTML = both;
}
</script>
My HTML:
<p id="demo">
<button onclick="Show(77, demo)">Click to convert</button>
</p>
I am still learning the ins and outs of Javascript so any and all help would be appreciated.

yes, enclose the arguments in quotes
<button onclick="Show('77', 'demo')">Click to convert</button>
without quotes 77 will be passed correctly but demo will not be since it will look for a demo property in window scope.

You should get innerHTML before inserting. Also note that, you must pass id attributes wrapped in quotes(').
ID attributes should at least have one character and it should not start with NUMBER
function Show(elID, elID2) {
var el1 = document.getElementByID(elID).innerHTML;
var el2 = document.getElementByID(elID2).innerHTML;
var both = (elID) + " " + (elID2);
document.getElementById(elID).innerHTML = both;
}
<p id="demo">
<button onclick="Show('77', 'demo')">Click to convert</button>
</p>

You could lay aside the inline JavaScript and opt for a different way, separating your markup from your logic.
https://jsfiddle.net/tricon/p2esv818/
HTML:
<button id="button" data-parameter-one='{ "keyOne": "valueOne", "keyTwo": "valueTwo" }'>
Some button
</button>
JavaScript:
var button = document.getElementById("button");
button.addEventListener("click", function() {
var parameters = this.getAttribute("data-parameter-one");
parameters = JSON.parse(parameters);
console.log(parameters);
});

Related

Count multiple div class in same page

I am trying to make a correct and incorrect question counter that shows groups of 4.
If I click on the first correct answer the counter works correctly and increases as I click, but it does not work with the second correct answer. The same happens with the wrong answers
This is the codes that I use, anyone could help me? Thx
HTML CODE:
¿Which of the following operations results in 8?
<input class="solucioncorrecta" value="6+2">
<input class="solucioncorrecta" value="7+1">
<input class="solucionincorrecta" value="1+1">
<input class="solucionincorrecta" value="2+2">
And the JS CODE:
<!-- CONTADOR FALLOS TEST -->
<script type="text/javascript">
var root = document.querySelector('.solucionincorrecta');
root.onclick = function() {
var elem = document.getElementById('contadorfallos');
elem.innerHTML = +elem.innerText + 1;
};
</script>
<!-- CONTADOR FALLOS TEST -->
<!-- CONTADOR ACIERTOS TEST -->
<script type="text/javascript">
var root = document.querySelector('.solucioncorrecta');
root.onclick = function() {
var elem = document.getElementById('contadoraciertos');
elem.innerHTML = +elem.innerText + 1;
};
</script>
The issue is that you are using document.querySelector() and not document.querySelectorAll()
document.querySelector() Returns the first match
document.querySelectorAll() Returns all matches
As a result, you are only setting an onclick property on the first .correcta and .incorrecta elements, not all of them.
To set this on all of them, you need to do two things:
You need use document.querySelectorAll() instead of document.querySelector(). This returns a list (specifically, a NodeList) of matching elements.
Loop over the items in your list, and attach onclick handlers to each of them. There are many ways to loop over a NodeList, listed here.
Here is an example:
// get all incorrect elements
var incorrectElements = document.querySelectorAll('.incorrecta');
// loop over each elements
for (var element of incorrectElements) {
// add an onclick
element.onclick = incorrectClickHandler
}
// this is the function being called by onclick
function incorrectClickHandler() {
score.innerText = parseInt(score.innerText) - 1;
}
It would be better if you upload your full codes. But anyway I write you some notes that probably answer your question.
-dont use the same name (root) for your .correcta and .incorrecta
-in your second <script>, you didnt defined button as an object . So browser cant understand it.

inputting grades (javascript function)

How do I make it so that the numbers I input are all on top of one another and another together in one spacing.
It supposed to show all the 3 grades I have input and when the button is clicked it should show the average and either pass or fail (I know it's supposed to be an if else statement but I really can't comprehend the codes and where will I put it)
If someone helps me solve this one can someone give me more user input / function related exercises that I can work on? thanks.
var p = prompt ("enter first grade");
var c = prompt ("enter second");
var o = prompt ("enter third grade");
document.write (p);
document.write (c);
document.write (o);
function xxx (p,c,o)
{
document.getElementById("demo4").innerHTML = ((parseInt(p)+parseInt(c)+parseInt(o)) / 3)
}
<p id="demo"></p>
<p id="demo2"></p>
<p id="demo3"></p>
<button onclick="xxx()">calculate</button>
<p id="demo4"></p>
<p id="demo5"></p>
Let me start first with the main non-logic problems with your code:
You shouldn't use prompt, it's just bad user experience. Dynamically create HTML elements instead.
You shouldn't use document.write. You aren't able to specify where the text should go and it makes your code vulnerable towards XSS vulnerabilities.
You shouldn't use onclick. You should never mix the JS with your HTML like that. (React's HTML-like syntax is not HTML, it's JSX. It's okay to do that there.)
Now, back to the main logic which your code should follow.
Provide the user with one <input type='number'> field and an "Add" button.
Recalculate the result on every change, don't rely on a "Calculate" button to update your state.
You can use an if statement to detect a failing grade.
Here is an example of a more proper implementation of what you're trying to accomplish. I know I'm basically doing the homework task for you so I would like you to learn from this.
// Storing references to elements.
const grades = document.getElementById('grades');
const template = document.getElementById('template');
const addButton = document.getElementById('add');
const averageOut = document.getElementById('average');
const failedOut = document.getElementById('failed');
function recalculate() {
// Let's create a sum variable.
let sum = 0;
// Let's query the document for grade input fields.
const numberFields = document.querySelectorAll('#grades input');
// Iterate over number fields with for ... of.
for (let field of numberFields) {
// Unary + converts the value into a number.
// parseInt can be used instead as well.
sum += +field.value;
}
// .length gives you the total amount of input fields.
// .length works on any array and some lists. (querySelectorAll returns a NodeList instead of an array)
const average = sum/numberFields.length;
// Use innerText to prevent XSS.
averageOut.innerText = average;
// If statement to check if the person has failed.
if (average < 3.0) {
failedOut.innerText = 'FAIL';
} else {
failedOut.innerText = 'NOT FAIL';
}
}
// Let's recalculate the average on any change made in ANY field in the document.
// This is basically what jQuery does in its '.on(eventType, selector, listener)' method.
// This technique relies on event bubbling.
// Make sure to replace this once you start adding more functions into the document.
// Also, () => is a closure in JavaScript, which is a function but with a different context.
document.addEventListener('change', () => recalculate());
// Adding new fields.
addButton.addEventListener('click', () => {
// Clone the template...
const templateClone = template.cloneNode(true);
// ...and append it to our grades.
grades.appendChild(templateClone);
// Also recalculate.
recalculate();
});
// Recalculate on load.
recalculate();
<ul id="grades">
<li id="template">
<input type="number" value="1" min="1" max="5" />
</li>
</ul>
<button id="add">Add</button>
<div>
<span>Average:</span> <span id="average"></span>
</div>
<div>
<span>Failed?:</span> <span id="failed"></span>
</div>
What you could improve upon is adding a "Remove" button.

using OOP on .click function in javascript

I am making a webpage that has a baseball strikezone with 25 buttons that will be clickable in 25 locations. I need to know if there is a easier way to do this then what I am doing. Maybe something that will take up far less lines. The button is clicked and then the counter is added by one to another table.
$('#one').click(function(){
counter++;
$('#ones').text(counter);
});
var countertwo = 0;
$('#two').click(function(){
countertwo ++;
$('#twos').text(countertwo);
});
A bit of a guess here, but:
You can store the counter on the button itself.
If you do, and you give the buttons a common class (or some other way to group them), you can have one click handler handle all of them.
You can probably find the other element that you're updating using a structural CSS query rather than id values.
But relying on those ID values:
$(".the-common-class").click(function() {
// Get a jQuery wrapper for this element.
var $this = $(this);
// Get its counter, if it has one, or 0 if it doesn't, and add one to it
var counter = ($this.data("counter") || 0) + 1;
// Store the result
$this.data("counter", counter);
// Show that in the other element, basing the ID of what we look for
// on this element's ID plus "s"
$("#" + this.id + "s").text(counter);
});
That last bit, relating the elements by ID naming convention, is the weakest bit and could almost certainly be made much better with more information about your structure.
You can use something like this:
<button class="button" data-location="ones">One</button>
...
<button class="button" data-location="twenties">Twenty</button>
<div id="ones" class="location">0</div>
...
<div id="twenties" class="location">0</div>
$('.button').on('click', function() {
var locationId = $(this).data('location')
, $location = $('#' + locationId);
$location.text(parseInt($location.text()) + 1);
});
Also see this code on JsFiddle
More clean solution with automatic counter
/* JS */
$(function() {
var $buttons = $('.withCounter'),
counters = [];
function increaseCounter() {
var whichCounter = $buttons.index(this)+1;
counters[whichCounter] = counters[whichCounter] ? counters[whichCounter] += 1 : 1;
$("#counter"+whichCounter).text(counters[whichCounter]);
}
$buttons.click(increaseCounter);
});
<!-- HTML -->
<button class="withCounter">One</button>
<button class="withCounter">Two</button>
<button class="withCounter">Three</button>
<button class="withCounter">Four</button>
<p id="counter1">0</p>
<p id="counter2">0</p>
<p id="counter3">0</p>
<p id="counter4">0</p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Javascript: How to get innerHTML of clicked button

Built a tip calculator but want to shorten the code by getting the innerHTML of the button that is being clicked.
Total Bill: <input id="bill" type="text">
<button type="button" onclick="tip15()">15</button>
<button type="button" onclick="tip18()">18</button>
<button type="button" onclick="tip20()">20</button>
<div id="tip">You owe...</div>
function tip15(){
var totalBill = document.getElementById("bill").value;
var totalTip = document.onclick.innerHTML
var tip = totalBill * 0.15;
document.getElementById("tip").innerHTML = "$" +tip
}
Problem with this method is that I have to write out three versions of the function to correspond with the tip amount. I want to create one function that grabs the innerHTML of the button being clicked and uses that value in the function. I want it to look something like this
function tip(){
var totalBill = document.getElementById("bill").value;
**var totalTip = GET INNERHTML OF CLICKED BUTTON**
var tip = totalBill * ("." + totalTip);
document.getElementById("tip").innerHTML = "$" +tip
}
That way I can run the same function on the different buttons.
Use HTML5 data attributes.
<button type="button" data-tip="15" onclick="getTip(this)">15</button>
The parameter this that you're passing to the function refers to the button that is being clicked. Then you get the value of the attribute like this:
function tip(button){
var tip= button.getAttribute("data-tip");
...
}
I leave the rest for you.
Change like this:Pass value to tip function.
<button id="15" type="button" onclick="tip(15)">15</button>
<button id="18" type="button" onclick="tip(18)">18</button>
<button id="20" type="button" onclick="tip(20)">20</button>
function tip(tip_value)
{
/*use here tip_value as you wish you can use if condition to check the value here*/
var totalBill = document.getElementById("bill").value;
var totalTip = tip_value;
var tip = totalBill * ("." + totalTip);
document.getElementById("tip").innerHTML = "$" +tip;
}
Pass this.innerHTML as an argument to your tip function.
So your tip function should look like this:
function tip(totalTip) {
var totalBill = document.getElementById("bill").value;
var tip = totalBill * ("." + totalTip);
document.getElementById("tip").innerHTML = "$" +tip
}
Therefore, if you have a button element that looks like this:
<button type="button" onclick="tip(this.innerHTML)">15</button>
The tip function will be called as tip(15).
I'll write up a quick solution, then explain why I did it that way.
PROPOSED SOLUTION
Part 1, the HTML
<div id="tip-wrapper">
<label for="bill">Total bill:</label>
<input name="bill" id="bill" type="text">
<br/>
<label for="tipratio">Tip ratio:</label>
<button name="tipratio" value="15" type="button">15%</button>
<button name="tipratio" value="18" type="button">18%</button>
<button name="tipratio" value="20" type="button">20%</button>
<div id="final-value">You owe...</div>
</div>
Part 2, the JavaScript
var parent = document.getElementById('tip-wrapper'),
buttons = parent.getElementsByTagName('button'),
max = buttons.length,
i;
// function that handles stuff
function calculate (e) {
var bill = document.getElementById('bill'),
tipRatio = e.target.value;
document.getElementById('final-value').textContent = bill.value * (1+tipRatio/100);
}
// append event listeners to each button
for(i = 0; i < max; i++) {
buttons[i].addEventListener('click', calculate, true);
}
EXPLANATIONS
About the HTML, not "much" has changed. The only thing being I'm using something that is a little more standards compliant.
I've added a wrapper element, this is just to isolate some DOM traversal instead of going through the whole document object to do your lookups (this will speed up your script).
Your buttons use "value" attribute, which is best. Since you can display button text one way, but use a proper value (see I added % characters).
Other than that, I mostly added proper identifiers and labels.
The JavaScript, this is where i'll go a little more in detail, I'll go step by step:
The first thing you want to do in a script is set the variables you'll need (and fetch the DOM elements you'll be using. This is what I've done on the first 4 lines of code.
Create a generic function that will handle your calculations and update your elements, no matter their numeric value. The feature I used here is adding a parameter (e) to your function, because EVENTS in javascript attach an EVENT OBJECT to your callback function (in this case calculate();). The EVENT OBJECT actually has a bunch of useful properties, of which I use:
target: this is the element that triggered the event (i.e. one of your buttons)
All we have to do is grab the target's value (e.target.value) and use that in the math that returns the final bill.
Using addEventListener. It's generally agreed on that you should keep your JavaScript outside of your HTML, so using the old event methods (onclick="") is discouraged. The addEventListener() method isn't too complicated, without going into detail it works as follows:
htmlObject.addEventListener('event type', 'callback function', 'bubbles true/false');
All I did was loop through all your buttons and append the event lsitener.
Closing notes
With this script, you can now add any "buttons" you want, the script will take them all into account and adapt accordingly. Just make sure to set their "value".
As I was writing this up a few people gave some quick answers. I can't comment yet (low reputation) so I'll leave my comments here.
Some of the proposed answers tell you to use innerHTML to fetch the tip value. This is wrong, you are using form fields and should use element.value that's what it is made for.
Some have even dared to say use the HTML5 data-* attributes. sure, you could. But why would you? HTML and the DOM already provide every necessary tool to accomplish your task WITHOUT the need to polute your HTML with unnecessary attributes. the value="" attribute is meant to be used in forms, it should be used over data-* attribute for field values.
As a general note innerHTML is meant to get HTML, not necessarily text or values. There are other methods to get the values you are seeking. In the case of form elements, it's element.value, in the case of most other HTML elements, it's element.textContent.
Hope these explanations help
function tip(o) {
var input = document.querySelector("input[id='bill']");
var total = input.value * o.innerHTML;
document.querySelector("#tip").innerHTML = "$" + total;
}
Total Bill: <input id="bill" type="text">
<button type="button" onclick="tip(this)">15</button>
<button type="button" onclick="tip(this)">18</button>
<button type="button" onclick="tip(this)">20</button>
<div id="tip">You owe...</div>

Working with getElementById( x ).onclick = someFunction

I thought for long how to define the question but i couldn't, i need to explain the code.
I want to make a simple organizer in JavaScript. You enter the task and click on the button "add to the list" and a script makes a checkbox with paragraph that contains the task's text. The second part is the disabling the checkbox, and striking through that tasks text when you click on it. I tried to do that by giving every checkbox i create a function (destroyIt() that gets element by id and than disables it, but it works only for the last checkbox added to the page. I am looking at this code for long time and i can't see what is wrong. Please help. Here is my code:
<html>
<head>
<style id="stil">
.over{
text-decoration:line-through;
}
</style>
<script type="text/javascript">
var numberOfTasks=1;
function insertNew(){
tekst = document.getElementById("zadatak").value;
if(tekst.length>0){
var idEl= "check"+numberOfTasks;
document.getElementById("ispis").innerHTML+="<input type='checkbox' id='check"+numberOfTasks+"'> "+"<span class='"+idEl+"'>"+tekst+"</span> <br/>";
document.getElementById(idEl).onclick= function(){ destroyIt(idEl); };
numberOfTasks++;
}
}
function destroyIt(idEl){
document.getElementById(idEl).disabled=true;
document.getElementById("stil").innerHTML+= "."+idEl+"{text-decoration:line-through;}";
alert(idEl+"{text-decoration:line-through;}");
}
</script>
</head>
<body>
Tasks for: <span id="date"> </span>
<script>
var date= new Date();
document.getElementById("date").innerHTML= ""+ date.getDay() +"." +date.getMonth() +"." +date.getFullYear();
</script>
<br/> <br/>
New task: <input type="text" id="zadatak"> <button onclick="insertNew()"> add to the list </button>
<button onclick="provera()">Provera</button>
<p id="ispis"> </p>
</body>
The problem is that when you do .innerHTML += "...", it destroys the existing nodes and their event handlers, and replaces them with new, clean nodes. For this and other reasons, you should almost never use += after .innerHTML.
A better way to insert new content from HTML markup is to use .insertAdjacentHTML() instead. The first argument describes the position relative to the element on which it was invoked, and the second argument is the new content.
So your code with .insertAdjacentHTML() would look like this:
function insertNew(){
tekst = document.getElementById("zadatak").value;
if(tekst.length>0){
var idEl= "check"+numberOfTasks;
document.getElementById("ispis")
.insertAdjacentHTML("beforeEnd", "<input type='checkbox' id='check"+numberOfTasks+"'> "+"<span class='"+idEl+"'>"+tekst+"</span> <br/>");
document.getElementById(idEl).onclick= function(){ destroyIt(idEl); };
numberOfTasks++;
}
}
Furthermore, you can modify the destroyIt function to operate on its this value, which will give you the input element that has the handler. You can then use its .id to get the class of the span, or you can just traverse to the next element.
Also, you shouldn't modify the style sheet to hide the element. Just add a class or a direct style property.
So in the above function, this:
document.getElementById(idEl).onclick= function(){ destroyIt(idEl); };
becomes this:
document.getElementById(idEl).onclick= destroyIt;
And then the destroyIt function becomes this:
function destroyIt(){
var span = this.nextElementSibling;
this.disabled=true;
span.style.textDecoration = "line-through";
}
The .nextElementSibling will need to be patched in IE8, but this is just for simple demonstration.

Categories