Creating unique Id buttons in a javascript loop - javascript

I need to create a table populated with buttons. Each button must have a unique id in order to edit values in it's row. I set an alert displaying button's id on click, but all created buttons seem to have the same ID. What's wrong with my code?
plz help, im really newbie in js. Any help will be highly appreciated.
this is my code:
<!doctype html>
<html>
<head>
<title>js table</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<table id="TableA" dir="ltr" width="500" border="1">
<tr>
<td>Old top row</td>
</tr>
</table>
</body>
<script type="text/javascript" >
for (var i = 0; i<6; i++) {
// Get a reference to the table
var tableRef = document.getElementById("TableA");
// Insert a row in the table at row index 0
var newRow = tableRef.insertRow(0);
// Insert a cell in the row at index 0
var boton = newRow.insertCell(0);
// Append a text node to the cell
var newButton = document.createElement("BUTTON");
newButton.id = i;
newButton.innerHTML = "Unique id button";
boton.appendChild(newButton);
// Insert a cell in the row at index 0
var newCell = newRow.insertCell(0);
// Append a text node to the cell
var newText = document.createElement("P");
newText.innerHTML = "item" +" "+ i;
newCell.appendChild(newText);
newButton.onclick = function(){
alert("Button Id: " + newButton.id);
}
}
</script>

Change your client handler to refer to the actual button that was clicked. Change from this:
newButton.onclick = function(){
alert("Button Id: " + newButton.id);
}
to this:
newButton.addEventListener("click", function(e) {
alert("Button Id: " + this.id);
});
The variable newButton is used over and over again in your for loop so by the time any of your onclick handlers actually run, all the buttons have been created and newButton will contain the last value it ever had.
Instead, you can use this to refer to the element that was clicked on so this.id will the id value of the button that was clicked.
Note: I also switch to using .addEventListener() which also passes an event data structure to the event handler (shown as the e argument in my code). This is a generally better way to register event listeners as it allows multiple listeners and gives you automatic access to other info about the event that occurred.

Related

Trying to collect input from user and print out in same page

I'm new to javascript and programming, and I am trying to create a webpage where the user can input the data on the page, and then I wrap it around HTML code to create an HTML template. I've tried using a couple methods but the document.write() command seems to be working for what I need. However, I'm trying to add the HTML tags around the input text and not getting a usable format.Full code below:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta charset="utf-8"/>
</head>
<body>
<h1>Title<input type="textarea" id="top_field" value="" style="width:100px; height:30px"></h1>
<br/>
<h2>Position/Proposal<input type="textarea" id="subtitle_field" value="" style="width:100px; height:30px"></h2>
<br/>
<p>Body Text: <input type="textarea" id="field1" value="" style="width:100px; height:30px"></p><br/>
<button id="sub_button" type="button" onclick="myFunction()">Copy</button>
<div id="full_code" hidden>
<p id="must_have" value='text'><!DOCTYPE> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta charset="utf-8"/><br></head>
</p>
<p id="less_than"><</p>
<p id="more_than">></p>
</div>
<script>
function myFunction() {
//const html_array = ["<!DOCTYPE>", "<html>", "<head>", "<meta name="viewport" content="width=device-width, initial-scale=1"/>", "<meta charset="utf-8"/>", "</head>"];
if(document.getElementById("field1").value != "" || document.getElementById("top_field").value != "" || document.getElementById("subtitle_field").value != ""){
let p_elem = document.getElementById("less_than").innerText + "p" + document.getElementById("more_than").innerText;
let pend = document.getElementById("less_than").innerHTML + "/p" + document.getElementById("more_than").innerHTML;
let body = document.getElementById("less_than").innerHTML + "body" + document.getElementById("more_than").innerHTML;
let bodyend = document.getElementById("less_than").innerHTML + "/body" + document.getElementById("more_than").innerHTML;
var top_text = document.getElementById("must_have").innerText;
var newParagraph2 = document.createElement("p"); //creates a new paragraph element
var newText2 = document.createTextNode(top_text); //creates text along with output to be displayed
newParagraph2.appendChild(newText2); //created text is appended to the paragraph element created
document.body.appendChild(newParagraph2); // created paragraph and text along with output is appended to the document body
var main_text = document.getElementById("field1").value;
var newParagraph = document.createElement("p"); //creates a new paragraph element
var newText = document.createTextNode(main_text); //creates text along with output to be displayed
newParagraph.appendChild(newText); //created text is appended to the paragraph element created
document.body.appendChild(newParagraph); // created paragraph and text along with output is appended to the document body*/
var title_text = document.getElementById("top_field").value;
var newParagraph3 = document.createElement("p"); //creates a new paragraph element
var newText3 = document.createTextNode(title_text); //creates text along with output to be displayed
newParagraph3.appendChild(newText3); //created text is appended to the paragraph element created
document.body.appendChild(newParagraph3); // created paragraph and text along with output is appended to the document body
var less_symbol = document.getElementById("less_than").value;
var newParagraph4 = document.createElement("p"); //creates a new paragraph element
var newSymbol = document.createTextNode(less_symbol); //creates text along with output to be displayed
newParagraph4.appendChild(newSymbol); //created text is appended to the paragraph element created
document.body.appendChild(newParagraph4); // created paragraph and text along with output is appended to the document body*/
document.writeIn(newParagraph2.innerText); //
}
else{
document.write("No text");
}
}
</script>
</body>
</html>
By now I'm able to read the text input and output in the same page below, but not able to add anything around the appended child or make the original tags above appear vertically. If someone can lead me in the right direction on method I should be using I would greatly appreciate it.
I would suggest NOT writing html strings with document.write. Instead, you can use createElement and appendChild to create html tags and add them to the page. It's much more readable and less likely to cause syntax errors in your html tags.
For example, to create a div that contains text from your inputfield:
let fieldValue = document.getElementById("myfield").value
let div = document.createElement("div")
div.innerHTML = fieldValue
document.body.appendChild(div)
Hope this generic example points you in the right direction!

Javascript cloneNode for adding new elements

what I'm trying to do is. when I click
function runIt(text) {
var counter = 1;
var comment = document.getElementById("name");
comment.innerText = text;
comment.cloneNode(true);
comment.id += counter;
}
document.addEventListener("click", function(e){
runIt("test")
}, true);
I want it to ADD a new element underneath that output "test".
it's keep getting replaced. :(
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>t</title>
</head>
<body>
<p id="name" class="someclass"></p>
</body>
</html>
cloneNode returns the new code, which you can then append to the DOM. Also counter should be defined outside the function and then incremented each time.
var counter = 1;
function runIt(text) {
var comment = document.getElementById("name");
newcomment = comment.cloneNode(true);
newcomment.innerText = text;
newcomment.id += counter;
counter++;
document.querySelector('body').append(newcomment)
}
document.addEventListener("click", function(e){
runIt("test")
}, true);
<p id="name" class="someclass">-</p>

addEventListener click doesn't working when I dynamically changing buttons

I have 3 inputs: for name, last name and education. The last input (for education) might be multiple so I have button to add more inputs. This process work dynamically but it has one flaw. The addEventListener method works only for the very first static button but not for buttons created in the process. In my opinion addEventListener couldn't catch updated ID for the element and work for the previous element only... Any ideas?
let counter = 0;
let buttonName, additionalId, additionalEducation, buttonId, dynamicButton, buttonIdListener, counter1;
additionalId = "education" + counter;
additionalEducation = "Education " + counter;
buttonId = "add"+counter;
buttonName = "name"+counter;
document.getElementById(buttonId).addEventListener('click', function(){
// let hide = document.getElementById(buttonId);
// hide.style.display = 'none';
counter= counter+1;
additionalId = "education" + counter;
additionalEducation = "Education " + counter;
buttonId = "add"+counter;
buttonName = "name"+counter;
let additionalLabel = document.createElement('label');
additionalLabel.innerHTML = additionalEducation;
additionalLabel.setAttribute('for',additionalId);
let additionalInput = document.createElement('input');
additionalInput.setAttribute('id',additionalId);
additionalInput.style.borderRadius = "5px";
additionalInput.style.backgroundColor = "blue";
additionalInput.style.color = "white";
let additionalButton = document.createElement('button');
additionalButton.setAttribute('type','button');
additionalButton.setAttribute('id',buttonId);
additionalButton.setAttribute('name',buttonName);
additionalButton.innerHTML = "Add";
document.getElementById("form").appendChild(additionalLabel);
document.getElementById("form").appendChild(additionalInput);
document.getElementById("form").appendChild(additionalButton);
})
and its my html code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="#">
<label for="name0">სახელი</label>
<input type="text" id="name0" name="name">
<label for="last_name0">გვარი</label>
<input type="text" id="last_name0" name="last_name">
<div>
<label for="education0">განათლება</label>
<input type="text" id="education0" name="education">
<button type="submit" id="add0">დამატება</button>
</div>
</form>
<script src="main.js"></script>
</body>
</html>
You need to set your listener on a static object - one that won't be removed or added. So you can use 'form' and set it like this:
First, update your static html button with a class - for this example 'the-button'
<button type="submit" class='the-button' id="add0">დამატება</button>
Then setup your event listener. Im going wrap this in a window.onload function to make sure it doesn't run until the HTML has rendered.
window.onload = function() {
document.getElementById("form").addEventListener('click', function (evt) {
if (evt.target.classList.contains('the-button')) theFunction(evt.target);
});
}
Then we stick your logic into a function, making sure to add the class the-button to any newly created buttons so they can pick up the listener.
function theFunction(fromButton) {
// fromButton is just in case you want a reference from the button that was clicked
counter= counter+1;
additionalId = "education" + counter;
additionalEducation = "Education " + counter;
buttonId = "add"+counter;
buttonName = "name"+counter;
let additionalLabel = document.createElement('label');
additionalLabel.innerHTML = additionalEducation;
additionalLabel.setAttribute('for',additionalId);
let additionalInput = document.createElement('input');
additionalInput.setAttribute('id',additionalId);
additionalInput.style.borderRadius = "5px";
additionalInput.style.backgroundColor = "blue";
additionalInput.style.color = "white";
let additionalButton = document.createElement('button');
additionalButton.setAttribute('type','button');
additionalButton.setAttribute('id',buttonId);
additionalButton.classList.add('the-button');
additionalButton.setAttribute('name',buttonName);
additionalButton.innerHTML = "Add";
document.getElementById("form").appendChild(additionalLabel);
document.getElementById("form").appendChild(additionalInput);
document.getElementById("form").appendChild(additionalButton);
}

How to change an image using an onclick button

I cannot get my images to change when I click each button name. Anyone know what the issue is with my code?
It's not letting me put my code in the description.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hmwk02</title>
</head>
<body>
<h1>Octocats</h1>
<img id="octocats" src= "https://octodex.github.com/images/original.png" alt="octocat" width="150"/>
<div id="buttons"></div>
<script>
let names= ["Castello", "Grinchtocat", "Mummytocat", "Adventure-Cat"];
let urls= ["https://octodex.github.com/images/catstello.png",
"https://octodex.github.com/images/grinchtocat.gif",
"https://octodex.github.com/images/mummytocat.gif",
"https://octodex.github.com/images/adventure-cat.png"];
let lines = "";
for(let i = 0; i< names.length; i++){
lines += '<button onlick="showPicture(' + i +')">' + names[i] + '</button><br/>'
}
document.getElementById("buttons").innerHTML = lines;
console.log(lines);
</script>
<script src="octocats.js"></script>
</body>
function showPicture(i) {
document.getElementById("octocat").src = urls[i];
console.log(i);
}
Your code is fine other than syntax errors, you misspelled onclick in your button tag and you misspelled the ID for the picture--it should be document.getElementById("octocats") not document.getElementById("octocat")
corrected code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hmwk02</title>
</head>
<body>
<h1>Octocats</h1>
<img id="octocats" src= "https://octodex.github.com/images/original.png" alt="octocat" width="150"/>
<div id="buttons"></div>
<script>
let names= ["Castello", "Grinchtocat", "Mummytocat", "Adventure-Cat"];
let urls= ["https://octodex.github.com/images/catstello.png",
"https://octodex.github.com/images/grinchtocat.gif",
"https://octodex.github.com/images/mummytocat.gif",
"https://octodex.github.com/images/adventure-cat.png"];
let lines = "";
for(let i = 0; i< names.length; i++){
lines += '<button onclick="showPicture(' + i +')">' + names[i] + '</button><br/>'
}
document.getElementById("buttons").innerHTML = lines;
console.log(lines);
</script>
<script>
function showPicture(i) {
document.getElementById("octocats").src = urls[i];
console.log(i);
}</script>
</body>
working codepen: https://codepen.io/anon/pen/YBYxgr
An alternative to using the for loop would be to map() the names array and simply use createElement() method to create a new <button> element with a click listener for each item in your names array (you should avoid using inline on* handlers (onclick, oninput, etc) and use IDs and event listeners instead).
Check and run the following Code Snippet for a practical example of what I have described above:
let names= ["Castello", "Grinchtocat", "Mummytocat", "Adventure-Cat"];
let urls= ["https://octodex.github.com/images/catstello.png", "https://octodex.github.com/images/grinchtocat.gif", "https://octodex.github.com/images/mummytocat.gif", "https://octodex.github.com/images/adventure-cat.png"];
names.map((e, i) => { // add function to each element in "names" array
let name = document.createElement("button"); // create <button> element for each item in "names" array
name.id = i; // assign respective index as id of each element
name.textContent = e; // assign item string as button text content
name.addEventListener("click", () => document.getElementById("octocats").src = urls[i]); // add click listener to each <button> that changes image src on click
document.getElementById("buttons").appendChild(name); // append the <button> elements to your `#buttons` div.
});
<h1>Octocats</h1>
<img id="octocats" src= "https://octodex.github.com/images/original.png" alt="octocat" width="150"/>
<div id="buttons"></div>

Dynamically created JQUERY buttons defaulting to last element created

Trying to create dynamic JQUERY elements to get added to an HTML page. Would like to click on an event, create elements from an array and then the new elements go to different functions. So far I've got:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<head>
<title>Adding buttons dynamically to JQuery </title>
<link type = "text/css" rel="stylesheet" href="jquery-ui.css">
<script type = "text/javascript" src="jquery.min.js"></script>
<script type = "text/javascript" src="jquery-ui.min.js"></script>
</head>
<body>
<p>Firing off without a hitch, HTML page loaded properly</p>
<button id="classChoice">Show Classes</button>
<div id='classSection' style="margin:50px">This is our new section test
area</div>
<script type="text/javascript">
//Classes Array
var classesArray = [ 'Spanish','English','French'];
var classIndex = 0;
//Button functionality
var btn = document.getElementById('classChoice');
btn.addEventListener("click",click2Handler,false);
//Button handler
function click2Handler(){
alert('clicked button!'); /*Code to create variable for new button */
evaluator();
}
//Evaluator function
function evaluator()
{
if(classIndex<classesArray.length)
{//Only operate to the length of the classes array
for(var i = 0; i< classesArray.length;i++)
{
var whereCreated = jQuery('#classSection');//where to add
var id = 'btn' + classesArray[classIndex];
whereCreated.append('<br><button id="' + id + '">' + classesArray[classIndex] + '</button>');
jQuery('#'+id).button().click(function(){
alert('Dynamically added button: '+ id + ' has been clicked...going to selector function');alert('id of button clicked: ' + id);
selector(id);
});
console.log('whereCreated: '+whereCreated+". id: " +id);
classIndex++;
}
console.log('classIndex: ' + classIndex);
}
}
function selector(btnSelection)
{
switch(btnSelection)
{
case 'btnSpanish':
alert('Buenos Dias!'); break;
case 'btnEnglish':
alert('Howdy Partner!');break;
case 'btnFrench':
alert('Oui oui monsieur!');break;
default : alert('Unhandled exception inside selection');
break;
}
}
</script>
</body>
</html>
The problem is only the last button created has its id evaluated inside the selector function, in this case btnFrench. How do I get each button to pass the right ID?
You could create a closure:
(function (id) {
jQuery('#' + id).button().click(function () {
alert('Dynamically added button: ' + id + ' has been clicked...going to selector function');
alert('id of button clicked: ' + id);
selector(id);
});
})(id);
The closure defines a new scope. This is necessary because your
handler isn't called until after the loop has finished, so i is not
part of the scope at the time it is called, or (in some cases) has the
last possible value from the loop.
(src)

Categories