Getting the getElementId Dynamically from HTML - javascript

So I am writing a Js script that accepts a number of rows and number of columns from the HTML. This will generate an HTML template for the customer using for loops . A customer should have the ability to select a product that features on the HTML template. this will take up 2 columns on the template instead of one.
The way I am trying to allow the customer to choose where the featured product displays a table.
function featProdDisplay(column, row) {
let body;
body = `<table style = "border-collapse: collapse;">`;
for (let i = 0; i < row; i++) {
body += `<tr>`
for (let j = 0; j < column; j++) {
pos = Number(i) + Number(j);
body += `<td id = "` + pos + `onclick="Selected()">
<div>
</div>
</td>`
};
body += `</tr>`
};
body += `</table>`;
return body;
}
function DisplayTable(column, row) {
body = featProdDisplay(column, row);
document.getElementById("FeatDisplay").innerHTML = body;
}
The way i was thinking is that the customer clicks on a block and drags it down to where the he/she would like it to end. those s will then change color.
So my question is is there any way to get the position or IDs of those s that have been selected as the ID is generated Dynamically and getElementById() requires a preexisting ID? Or should I try a different approach entirely?
Thank you in advance

Related

Javascript method not toggling as expected

I have a word matching exercise game that is written in javascript and html. When the user clicks add more the add_more() method adds a new key, description pair to the keys and descriptions input boxes. Then when the user clicks generate html the generate_html() method should create a new textarea box with the html to be generated.
Expected:
The user clicks add more then clicks generate html new html is generated once.
Actual:
The user clicks add more then clicks generate html new html is generated more than once.
The program is relatively simple. These are the two methods
function generate_html() {
// retrieve the keys and descriptions. Then load them into their respective arrays.
const e_inputs = document.querySelectorAll("[id^='el']");
const d_inputs = document.querySelectorAll("[id^='dl']");
let elArray = [];
let dlArray = [];
const title = document.getElementById('title_input').value;
e_inputs.forEach( i => { if(i.value) elArray.push(i.value) });
d_inputs.forEach( i => { if(i.value) dlArray.push(i.value) });
//have we added more?
if(addMore && htmlGenerated){
// then delete the old textarea.
textarea = document.getElementById("generated_html_textarea");
textarea.remove();
// delete the controls.
controls = document.getElementById("program1");
controls.remove();
}
//has the html already been generated?
if(!htmlGenerated){
//fetch the results box
results = document.getElementById("results");
//create textarea
textarea = document.createElement("textarea");
textarea.setAttribute("id","generated_html_textarea");
// initialize blank html
let html = '';
html += '<div id=\"maincontentstyle\">\n'
html += '\t<center>\n'
html += '\t\t<div id=\"boxstyle\">\n'
html += '\t\t\t<h3 id=\"title\">'+title+"</h3>\n";
//create key inputs
html += '\t\t\t\t<center>\n'
html += '\t\t\t\t\t<div class="source">\n'
for (let i = numberOfInputs; i < elArray.length+numberOfInputs; i++){
html += '\t\t\t\t\t\t<div id="s';
id = (1+i-numberOfInputs);
html += id;
html +='\" class=\"draggyBox-small\">\n';
html += `\t\t\t\t\t\t\t${elArray[i-numberOfInputs]}\n`;
html +='\t\t\t\t\t\t</div>\n';
}
html += '\t\t\t\t\t</div>\n'
html += '\t\t\t\t\t</center>\n'
//create description inputs
html += '\t\t\t\t\t<table id=\"tablestyle\">\n'
for (let i = numberOfInputs; i < dlArray.length+numberOfInputs; i++){
html +='\t\t\t\t\t\t<tr>\n'
html += '\t\t\t\t\t\t<td id="row';
id = (1+i-numberOfInputs);
html += id;
html +='">\n';
html += '\t\t\t\t\t\t\t<div id=\"t';
html += id;
html +='" class=\"ltarget\">'
html +='</div>\n'
html +='\t\t\t\t\t\t</td >\n'
html +='\t\t\t\t\t\t<td id=\"d'
html += id
html += '\">\n'
html +=`\t\t\t\t\t\t\t${dlArray[i-numberOfInputs]}\n`;
html +='\t\t\t\t\t\t\t</td >\n'
html +='\t\t\t\t\t\t</tr>\n';
}
html += '\t\t\t\t\t</table>\n';
html += '\t\t\t\t</center>\n'
html += '\t\t</div>\n'
html += '\t</center>\n'
html += '</div>'
// html generation is done.
htmlGenerated = true;
textarea.value = html;
results.appendChild(textarea);
// Generate reset, show answer, , and render html buttons
controls = document.createElement("div");
controls.setAttribute("id","program1");
controls.setAttribute("style","border: 1px solid #EB0D1B; width: 360px; font-family: courier; font-size: 100.5%; margin: 0px auto; border: 1px; text-align: center; margin-top: 5px;");
controls.innerHTML += '<button id = "renderHTMLButton" class="button" type="button" onClick="render_html()">Render html</button> <span id = "audio" style=""> <img id="bg" src="audioOff.png" height="30" width="30" style="margin-bottom:-10px; padding-bottom:-20px;"/> </span>';
results.appendChild(controls);
}
}
function add_more() {
// we've added more inputs.
addMore = true;
// set html generated to false, because new inputs have been added.
htmlGenerated = false;
// increment the number of inputs.
numberOfInputs++;
//fetch the input boxes.
inputs = document.getElementById("inputBoxes");
//create a new row for a key term.
row = document.createElement("div");
row.setAttribute("class","row");
// set the key term text.
row.innerHTML = "Key Term ";
row.innerHTML +=numberOfInputs;
row.innerHTML +=" :";
// create the input for the key.
key = document.createElement("input");
key.setAttribute("id","el"+numberOfInputs);
//add the key to the row.
row.appendChild(key);
//create a row for the new description.
row2 = document.createElement("div");
row2.setAttribute("class","row");
// set the description text.
row2.innerHTML = "Description "
row2.innerHTML+=numberOfInputs;
row2.innerHTML+=" :";
// create the description input
description = document.createElement("input");
description.setAttribute("id","dl"+numberOfInputs);
// add the description to the row.
row2.appendChild(description);
// add the rows for the key and the description to the inputBoxes.
inputs.appendChild(row);
inputs.appendChild(row2);
}
the gitub link is here.
Your issue is that you are appending child nodes to the result:
211 results.appendChild = textarea;
Change this to use replaceChildren so you rather replace the content and not keep appending:
211 results.replaceChildren(textarea);

Issue with getting a keyup function to get sum of input field values using plain Javascript

I'm working on a personal project and I've run into an issue that I haven't been able to solve.
Here is a function that generates new table rows into a table (with id of "tableData") when a button is clicked:
function addNewRow(){
var tableEl = document.getElementById("tableData");
var newLine = '<tr class="newEntry">';
var classArray = ["classA", "classB", "classC", "classD"];
for (var i = 0; i < classArray.length; i++){
newLine += '<td><input class="' + classArray[i] + '"></td>';
}
newLine += '</tr>';
tableEl.insertAdjacentHTML("beforeend", newLine);
}
document.getElementById("addRow").addEventListener("click", addNewRow, false);
//the element with id="addRow" is a button
I've simplified the code for the above function for the sake of readability as it's not the focus of the problem. When the button is clicked, a new row is added successfully.
The problematic part involves another function that takes the sum of the respective classes of each row and displays them in a div.
The goal is to get the sum of the values of all input fields with matching class names. For example, let's say I use the addNewRow function to get six rows. Then I want to have the div showing the sum of the values of all input fields with the class name of "classA"; the number in that div should be the sum of those six values, which gets updated as I type in the values or change the existing values in any of the input fields with class name of "ClassA".
function sumValues(divId, inputClass){
var sumVal = document.getElementsByClassName(inputClass);
var addedUp = 0;
for (var j = 0; j < sumVal.length; j++){
addedUp += Number(sumVal[j].value);
}
document.getElementById(divId).innerHTML = addedUp;
}
Here are a couple (out of several) failed attempts:
document.input.addEventListener("keyup", sumValues("genericDivId", "classA"), false);
document.getElementsByClassName("classA").onkeyup = function(){sumValues("genericDivId", "classA");}
Unfortunately, after scouring the web for a solution and failing to find one, I just added an event listener to a button that, when clicked, would update the div to show the sum of values. Also had to modify the sumValues function to take values from an array rather than accepting arguments.
My question is: How can I modify the code so that the sum value updates as I type in new values or change existing values using pure Javascript (vanilla JS)?
You are very close, document.getElementsByClassName() returns an array of DOM objects, you need to set the onkeyup function for each and every element by looping through that array.
var classA = document.getElementsByClassName('classA'); // this is an array
classA.forEach(function(elem){ // loop through the array
elem.onkeyup = function(){ // elem is a single element
sumValues("genericDivId", "classA");
}
}
Hopefully this fixes your issue
Maybe the example below is not same with your situation, but you'll get the logic, easily. Anyway, do not hesitate to ask for more guide.
document.getElementById("row_adder").addEventListener("click", function() {
var t = document.getElementById("my_table");
var r = t.insertRow(-1); // adds rows to bottom - change it to 0 for top
var c = r.insertCell(0);
c.innerHTML = "<input class='not_important_with_that_way' type='number' value='0' onchange='calculate_sum()'></input>";
});
function calculate_sum() {
var sum = ([].slice.call(document.querySelectorAll("[type=number]"))).map(e=>parseFloat(e.value)).reduce((a, b) => a+b);
document.getElementById("sum").innerHTML = sum;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
<p>
<strong>Sum</strong>:<span id="sum">0</span>
</p>
</div>
<button id="row_adder">
Click me
</button>
<table id="my_table">
</table>
</body>
</html>

Simple ToDo-List doesn't work

My ToDo List dont wanna work the way i want. I've just been working with JavaScript for 2 weeks sthis is very new to me, therefor the code maybe doesnt look that nice.
The result comes out wrong. If I type in "buy food" the first line gonna show just that, but the next time I wanna add "walk the dog", then it displays
buy food
buy food
walk the dog
I hope you understand my problem. It also ends the unordered list tag after the first click and adds the rest of the things in another.
Here's the JavaScript:
var taskList = [];
var text = "<ul>"
function addToList() {
var task = document.getElementById("toDoTask").value;
taskList.push(task);
for(i = 0; i < taskList.length; i++){
text += "<li>" + taskList[i] + "</li>" ;
}
text += "</ul>";
document.getElementById("todoList").innerHTML = text;
}
The issue is you're closing the ul tag after adding each item. Instead of concatenating raw HTML, consider using element objects and appending, and using a text node object to handle the user input - this removes the possibility of a DOM Based XSS vulnerability.
window.onload = function() {
var taskList = [];
var container = document.getElementById("todoList");
document.getElementById("add").onclick = addToList;
function addToList() {
var task = document.getElementById("toDoTask").value;
taskList.push(task);
var ul = document.createElement('ul');
var li;
for (i = 0; i < taskList.length; i++) {
li = document.createElement('li');
li.appendChild(document.createTextNode(taskList[i]))
ul.appendChild(li);
}
container.innerHTML = '';
container.appendChild(ul);
}
};
Task:
<input id="toDoTask" /> <input type="button" id="add" value="Add" />
<div id="todoList">
</div>
You should not use the innerHtml. This replace all the text of your content. You should just add the li to your ul.
You can do that by using the append function by jquery Append
your <ul> must contain an id like this <ul id="toDoList">
then you make $("#toDoList").append("yourTask");
yourTask must contains the li.
With this, you don't need to iterate on all your element list
Not sure, but you seem to keep adding to text the second time, so text will be something like <ul><li>buy food</li></ul><li>buy food</li><li>walk the dog</li></ul>, which is invalid HTML by the way, but gets outputted anyway...
On each call of function addToList() you should reset the variable text.
For example:
function addToList() {
var task = document.getElementById("toDoTask").value;
taskList.push(task);
text="";
for(i = 0; i < taskList.length; i++){
text += "<li>" + taskList[i] + "</li>" ;
}
text += "</ul>";
document.getElementById("todoList").innerHTML = text;
}
The whole list of items in array will appends to variable text on each call.

Questions about dynamically creating divtags

I'm trying to dynamically create divtags for each cell of my table so that I can later fill them in with other stuff. However, when I tried doing this:
newhtml+="<div id ='" + (j) +"'><td class = 'unselected'>&nbsp?&nbsp</td></div>"
and later using it it acted as if it never created it.
So after browsing stackoverflow I found out that you should use this line of code to dynamically create a div tag:
var divtag = document.createElement('div');
But my question is how do I implement it into my js code?
Here is the section of code that is supposed to create divtags for later referencing:
newhtml+="<tr>";
for (var j = 0; j < $tblcols; j++){
newhtml+="<div id ='" + (j) +"'><td class = 'unselected'>&nbsp?&nbsp</td></div>";
And here is the section that uses it:
divtag = document.getElementById("'" + (++$counter2) + "'");
newhtml +="<td class = 'solved'><img src ='sc2units/" + $counter2 + ".jpg'></td>";
divtag.innerHTML = newhtml;
each section is a nested for loop that goes through the entire array of data that needs outputted.
EDIT: If there is an easier way to fill cells with data in an array I would be happy to know.
I'm not sure on your table, or setup, or exact needs.... But I believe you want to give content to certain table cells after you've already created the cells. You're on to the right idea with naming them, but you can't wrap <td>s in <div>s so your next best option is to simply name the <td>s themselves.
You could also add the content right inside the second loop, but we'll run with this.
HTML
<table id="myTable">
<tr>
<td>[ content ]</td>
</tr>
<tr>
<td>[ content ]</td>
<td>[ content ]</td>
</tr>
[ etc ]
</table>
JavaScript
var tbl = document.getElementById("myTable"),
rows = tbl.getElementsByTagName("tr");
// loop all rows
for (var r = 0; r < rows.length; r++){
// loop all cols within the row
var cols = rows[r].getElementsByTagName("td");
for (var c = 0; c < cols.length; c++){
cols[c].id = "row-" + r + "_col-" + c;
}
}
// usage
document.getElementById("row-1_col-1").innerHTML = "JS POWER";
http://jsfiddle.net/daCrosby/tJYNM/
You can create the elements separately then organize them later, inserting one inside the other. Something like:
var mydiv = document.createElement("DIV");
var mytd = document.createElement("TD");
mytd.innerHTML = "some basic text";
mydiv.appendChild(mytd); // insert the TD inside the DIV
document.body.appendChild(mydiv); // insert the DIV in the document's body
I just don't know what's about putting TD's inside DIV's...

Fill Array with div elements populated dynamically in codebehind. C#, javascript

I have a report populated as a table with a stringbuilder from the codebehind. The first TD of every row is a checkbox, the id of each checkbox is assigned dynamically:
sb.Append("<td><input type='checkbox' id='chkSelectAll_" + i + "' name='chk_" + i + "' onclick='JavaScript: chkAll_click(this);' /> </td>"
The aspx page uses a master page and
<asp:Content><div id='divMain'></div></asp:Content>
format other than a form to populate. The problem I am running in to is that I am having trouble finding all the elements (or any actually) of the div to work with. Here is the javascript I have been given. (Team project at work, I was just assigned 1 task on the project so changing anything is not an option.)
function divBatchBuild_click() {
debugger
var form = document.forms[0];
var visitList = '';
for (i = 0; i < form.elements.length; i++) {
if (form.elements[i].type == 'checkbox') {
//alert(form.elements[i].id.toString());
if (form.elements[i].checked == true &&
form.elements[i].id != 'chkSelectAll') {
var y = form.elements[i].id;
//alert('id=' + y[1].toString());
visitList = visitList + y[i].toString() + '|';
}
}
}
}
Apparently this worked on a previous project, but when used with this report the process never goes inside the if statement. Any help on what is going wrong is appreciated.
I think you want to first get the div, then get the elements in the div with the checkbox tagname. Something like:
var div = document.getElementById('divMain');
var elements = div.getElementsByTagName('checkbox');
for (i = 0; i < elements.length; i++) {

Categories