Sum of the selected items of a pages drop down menus - javascript

My page has a table which has a series of drop down menus in one column (all of which contain a series of numbers), I want to run a function every time one of the values is changed, that takes the sum of the values and displays the result on the page. I believe my function (totalMarks), gets a collection of all my drop down menus, then loops through them, adding to the total the value of the selected index, and then displaying the total marks within a some h2 tags. Is my problem within the summing of the drop down menus or somewhere else?
function markForm(tagID) {
var x = document.getElementById(tagID)
var pre = document.createElement("pre");
x.appendChild(pre);
var SectionDetails = [
{ name: "Dynamic Table", maxMarks: 20},
{ name: "IntelliJ usage", maxMarks: 10},
{ name: "Calendar Controller", maxMarks: 30},
{ name: "Active Form", maxMarks: 20},
{ name: "Object Database", maxMarks: 20}
];
var table = pre.appendChild(document.createElement("table"));
var tableHeader = table.appendChild(document.createElement("thead"));
var tableRow = tableHeader.appendChild(document.createElement("tr"));
var headRow = tableRow.appendChild(document.createElement("th"));
headRow.appendChild(document.createTextNode("Section"));
headRow = tableRow.appendChild(document.createElement("th"));
headRow.appendChild(document.createTextNode("Max Mark"));
headRow = tableRow.appendChild(document.createElement("th"));
headRow.appendChild(document.createTextNode("Comments"));
headRow = tableRow.appendChild(document.createElement("th"));
headRow.appendChild(document.createTextNode("Mark"));
var resultsRows = table.appendChild(document.createElement("tbody"));
for (var i = 0; i < SectionDetails.length; i++) {
tableRow = resultsRows.appendChild(document.createElement("tr"));
var tableData = tableRow.appendChild(document.createElement("td"));
tableData.appendChild(document.createTextNode(SectionDetails[i].name));
tableData = tableRow.appendChild(document.createElement("td"));
tableData.appendChild(document.createTextNode(SectionDetails[i].maxMarks));
tableData = tableRow.appendChild(document.createElement("td"));
var tarea = document.createElement("textarea");
tarea.value = "Enter Comments";
tableData.appendChild(tarea);
tableData = tableRow.appendChild(document.createElement("td"));
var dropDown = document.createElement("select");
dropDown.name = SectionDetails[i].name;
dropDown.setAttribute("onchange", totalMarks());
for (var j = 0; j < (SectionDetails[i].maxMarks + 1); j++) {
var listItem = new Option(j);
listItem.value=j;
dropDown.appendChild(listItem);
}
tableData.appendChild(dropDown);
}
var h2 = document.createElement("h2");
h2.id = "headline";
h2.innerHTML = "Total Marks: 0";
x.appendChild(h2);
}
function totalMarks() {
var total = 0;
var ddmenus = document.getElementsByTagName("select");
for (var a = 0; a < ddmenus.length; a++) {
total = total + ddmenus[a].options[ddmenus[a].selectedIndex].value;
}
document.getElementsByTagName("h2").innerHTML = "Total Marks: " + total;
}
How the page should look, and does if I don't include the line "document.getElementById("marksline").innerHTML = "Total Marks: " + total;"
How the page looks if I leave the above mentioned line in the code.

there are two things to take care of:
parseInt the value of selected option
total = total + parseInt(ddmenus[a].options[ddmenus[a].selectedIndex].value);
Give the h2 an id (e.g. 'headline') and assign the value with getElementById
document.getElementById("headline").innerHTML = "Total Marks: " + total;
Edit: for clarification. If you getElementsByTagName you get an array of elements. For assigning a value you need to choose one out of the array e.g. document.getElementByTagName('h2')[0] would be the first h2 on the page.

You need to parse value of dropdown in integer as value is a string by default.
total = total + parseInt(ddmenus[a].options[ddmenus[a].selectedIndex].value);

Related

Is option to assign ID to every checkbox inside dynamic table

This is my dynamic table
After clicking button it generate table based on input.
$(function () {
$("#btnGenerate").click(function () {
var textarea = document.getElementById("inglist");
var lines = textarea.value.replace(/\r\n/g,"\n").split(/:|,|\n/);
var lines2 = textarea.value.split(/(\d+(?:\.\d+)?)/);
lines.forEach((o, i) => o.id = i + 1);
var array1=new Array();
for (var i = 1; i < lines .length; i++) {
array1.push(lines [i].replace(/\[.*?\]/g, ''));}
const results = [];
array1.forEach(line => {
const filtered = line.split(/([\s\w]+)\s(\d+(?:\.\d+)?)(%?)\s*(\[\d\])?/g).filter(Boolean);
results.push(filtered);
});
var build = new Array();
build.push(["ING name:", "Total:","unit", "Count it?:","x2?"]);
var table1 = $("<table />");
for(var i=0;i<results.length;i++){
build.push(results[i]);
}
var countColumns = build[0].length;
console.log(countColumns);
var tables = $("<table /><class='form-control input-md'>");
//Add the header row.
var rows = $(tables[0].insertRow(-1));
for (var i = 0; i < countColumns; i++) {
var headerCell = $("<th /><class='form-control input-md'>");
headerCell.html(build[0][i]);
rows.append(headerCell);
}
//Add the data rows.
for (var i = 1; i < build.length; i++) {
row = $(tables[0].insertRow(-1));
for (var j = 0; j < countColumns; j++) {
var cell = $('<td><input type="checkbox"/>');
cell.html(build[i][j]);
row.append(cell);
}
}
var dvTable1 = $("#dvTable1");
dvTable1.html("");
dvTable1.append(tables);
});
How i can assign dynamic ID to every checkbox ?
And then how to filter only rows where is tick checkbox in 3rd column ( count in?: )

How to change number inside of div class and update it?

I'm trying to change the existing HTML code on a site. See the example below:
var multiplier = 1.5;
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0
})
//for first two occurences
var priceEls = document.getElementsByClassName("price");
for (var i = 0; i < priceEls.length; i++) {
var price = priceEls[i].innerText;
var priceN = getNumber(price)*multiplier;
alert("Price: " + formatter.format(priceN));
}
//for last occurence
var priceEls = document.getElementsByClassName("column--container value-item");
for (var i = 0; i < priceEls.length; i++) {
var price = priceEls[i].innerText;
//alert("Price: " + price);
var priceN = getNumber(price)*multiplier;
alert("Price: " + formatter.format(priceN));
}
function getNumber(myString) {
var numb = myString.match(/\d/g);
numb = numb.join("");
//alert (numb);
return(parseInt(numb));
}
<div class="price">$2,000</div>
<div class="price">
<span>$</span>
3,000
</div>
<div class="column--container value-item">
<span class="text-semibold-xs">Price</span>
$1,500
</div>
How do I update the HTML code with those new values?
One thing you can do after calculating the new prices is set the innerText of an element with the text you are using on the alert. So one of your loops can look like this
for (var i = 0; i < priceEls.length; i++) {
var price = priceEls[i].innerText;
var priceN = getNumber(price)*multiplier;
priceEls[i].innerText = "Price: " + formatter.format(priceN);
}
I would recomend using forEach for looping instead of for.

HTML Table Row Creation

EDIT: With significant help from others, I was able to work up a solution.
I'm taking data from a Google Spreadsheet and then attempting to render it as an HTML table in a WebApp.
I'd like the data to show up like
<tr>
<td>
<td>
<td>
exactly how it looks in a spreadsheet, with each value in a separate cell.
Big picture, I'd like to be able to do different things to each <td>, so I want to make sure I structure the data in a usable way.
Code.GS
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function webAppTest() {
getTeamArray();
}
function getTeamArray() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('Sheet1');
var range = sheet.getRange('A2:H1000');
var values = range.getValues();
//Logger.log(values);
var teamsArray = [];
for (var i = 0; i < values.length; ++i) {
var column = values[i];
var colA = column[0];
var colB = column[1];
var colC = column[2];
var colD = column[3];
var colE = column[4];
var colF = column[5];
var colG = column[6];
var colH = column[7];
if (colA != '') {
teamsArray.push(values[i][0]);
teamsArray.push(values[i][3]);
teamsArray.push(values[i][4]);
}
}
var array2 = [];
while(teamsArray.length) array2.push(teamsArray.splice(0,3));
var lengthDivName2 = array2.length;
var widthDivName2 = array2[0].length;
//Logger.log(teamsArray);
Logger.log(array2);
//return teamsArray;
return array2;
}
Index.HTML Function
function buildOptionsList(teamsArray) {
var div = document.getElementById('myList');
for (var i = 0; i < teamsArray.length; i++) {
var tr = document.createElement('tr');
var td = document.createElement('td');
var cLass = td.setAttribute('class','ui-state-default');
var iD = td.setAttribute('id',teamsArray[i]);
td.appendChild(document.createTextNode(teamsArray[i]));
div.appendChild(tr);
div.appendChild(td);
}
}
</script>
</head>
<body>
<div id="myList" class="connectedSortable">MY LIST</div>
</body>
</html>
ATTEMPT 1
ATTEMPT 2
I tried to change the array creation in code.gs which got all the correct data in the <tr> but didn't split into <td>s
I am not sure I understood the way you receive the data, but if teamsArray contain information about one line the solution would be something like this:
function buildOptionsList(teamsArray) {
var div = document.getElementById('myList');
var tr = document.createElement('tr');
for (var i = 0; i < teamsArray.length; i++) {
var td = document.createElement('td');
var cLass = td.setAttribute('class','ui-state-default');
var iD = td.setAttribute('id',teamsArray[i]);
td.appendChild(document.createTextNode(teamsArray[i]));
tr.appendChild(td);
}
div.appendChild(tr);
}
Use Array#map, Array#reduce, and Array#join to surround the elements of the inner array with the required HTML tags and then condense to a single string. Currently you have an implicit Array#toString call which creates a comma-separated string of the inner array's elements (the inner array is at teamData[i]), and thus you only have a single cell in your previous attempts' output.
This simple function assumes you aren't applying any column- or row-specific styles or attributes, so it can simply treat every <td> element equivalently. If you have symmetric styling to apply, you would want to process the headers/row variables with .map first (since you can then use the elements' indices) and then .join("") instead of just .join using the tag delimiters.
function getTableHTMLFrom(array, hasHeaders) {
if (!array || !array.length || !array[0].length)
return "";
const headerString = (hasHeaders ?
"<tr><th>" + array.shift().join("</th><th>") + "</th></tr>"
: "");
const tdTag = "<td class=\"ui-state-default\">";
const bodyString = array.reduce(function (s, row) {
s += "<tr>" + tdTag + row.join("</td>" + tdTag) + "</td></tr>";
return s;
}, "");
return "<table>" + headerString + bodyString + "</table>";
}
I found a solution (applied to Index.HTML) that worked based on THIS.
function buildOptionsList(array2) {
var table = document.createElement('table');
var tableBody = document.createElement('tbody');
array2.forEach(function(rowData) {
var row = document.createElement('tr');
rowData.forEach(function(cellData) {
var cell = document.createElement('td');
var cLass = td.setAttribute('class','ui-state-default');
cell.appendChild(document.createTextNode(cellData));
row.appendChild(cell);
});
tableBody.appendChild(row);
});
table.appendChild(tableBody);
document.body.appendChild(table);
}
buildOptionsList(array2);

How to prevent additional table creation

I've been looking for workarounds to ensure that only one table is created. So far the only one i have come up with is to disable the button after it had been pressed. Here is my code:
function bikeData() {
// Select the Table
var tbl = document.getElementById('bikeInnerTable');
var th = document.getElementById('tableHead_B');
var headerText = ["ID", "Bike Status", "Bike Location", "Depot ID"];
// Set number of rows
var rows = 10;
// Set number of columns
var columns = headerText.length;
// create table header
for (var h = 0; h < columns; h++) {
var td = document.createElement("td");
td.innerText = headerText[h];
th.appendChild(td);
}
// create table data
for (var r = 0; r < rows; r++) {
var cellText = ["UNDEFINED", "UNDEFINED", "UNDEFINED", "UNDEFINED"];
// generate ID
x = getRandomNumber(1000, 1);
cellText[0] = x;
// generate Status
x = getStatus();
cellText[1] = x;
// generate Name
x = getLocation();
cellText[2] = x;
// generate depot ID
x = getRandomNumber(1000, 1);
cellText[3] = x;
var tr = document.getElementById("b_row" + r);
for (var c = 0; c < columns; c++)
{
var td = document.createElement("td");
td.innerText = cellText[c];
tr.appendChild(td);
}
}
}
If the button is pressed multiple times then the table is created multiple times. However how can I adapt the code to ensure that it if the table is already present within the div, then it doesn't continue in creating the table additional times.
You can set a flag and then only execute the code when applicable.
let firstTime = true;
function(){
...
if (firstTime) {
firstTime = false;
...
}
}
This is what Javascript variables are for. You can make a variable, then test that against a condition in the function. Let me show you what I mean:
window.timesRan = 0;
function bikeData() {
//Check if the variable is > 1
if (timesRan > 1) {
return false;
}
//code here
//then just add 1 to the variable every time
timesRan += 1;
}
All the best, and I hope my answer works for you :)

Function not running on button click? [duplicate]

This question already has answers here:
Is "clear" a reserved word in Javascript?
(4 answers)
Closed 6 years ago.
I have a button on my page that is intended to clear all the textareas that are in the document, however when I click said button it appears that the function isn't being run. I've tried adding a button listener to the document, and that still didn't seem to work, I don't understand what the problem is, as the line with the alert isn't even running.
function markForm(tagID) {
var x = document.getElementById(tagID)
var pre = document.createElement("pre");
x.appendChild(pre);
var SectionDetails = [
{ name: "Dynamic Table", maxMarks: 20},
{ name: "IntelliJ usage", maxMarks: 10},
{ name: "Calendar Controller", maxMarks: 30},
{ name: "Active Form", maxMarks: 20},
{ name: "Object Database", maxMarks: 20}
];
var table = pre.appendChild(document.createElement("table"));
var tableHeader = table.appendChild(document.createElement("thead"));
var tableRow = tableHeader.appendChild(document.createElement("tr"));
var headRow = tableRow.appendChild(document.createElement("th"));
headRow.appendChild(document.createTextNode("Section"));
headRow = tableRow.appendChild(document.createElement("th"));
headRow.appendChild(document.createTextNode("Max Mark"));
headRow = tableRow.appendChild(document.createElement("th"));
headRow.appendChild(document.createTextNode("Comments"));
headRow = tableRow.appendChild(document.createElement("th"));
headRow.appendChild(document.createTextNode("Mark"));
var resultsRows = table.appendChild(document.createElement("tbody"));
for (var i = 0; i < SectionDetails.length; i++) {
tableRow = resultsRows.appendChild(document.createElement("tr"));
var tableData = tableRow.appendChild(document.createElement("td"));
tableData.appendChild(document.createTextNode(SectionDetails[i].name));
tableData = tableRow.appendChild(document.createElement("td"));
tableData.appendChild(document.createTextNode(SectionDetails[i].maxMarks));
tableData = tableRow.appendChild(document.createElement("td"));
var tarea = document.createElement("textarea");
tarea.value = "Enter Comments";
tableData.appendChild(tarea);
tableData = tableRow.appendChild(document.createElement("td"));
var dropDown = document.createElement("select");
dropDown.name = SectionDetails[i].name;
for (var j = 0; j < (SectionDetails[i].maxMarks + 1); j++) {
var listItem = new Option(j);
listItem.value=j;
dropDown.appendChild(listItem);
}
tableData.appendChild(dropDown);
}
var h2 = document.createElement("h2");
h2.innerHTML = "Total Marks: " + document.createTextNode(totalMarks);
x.appendChild(h2);
}
function totalMarks() {
var total = 0;
for (var a = 0; a < SectionDetails.length; a++) {
var e = document.getElementById(SectionDetails[a].name);
var total = total + Number(e.options[e.selectedIndex].value);
}
return total;
}
function clear() {
var textareas = documents.getElementsByTagName("textarea");
console.log(textareas);
for (var i = 0; i < textareas.length; i++) {
textareas[i].value="Enter Comments";
}
alert("Fields Cleared");
}
<body onload="markForm('conversion')">
<h2>Marking Form: </h2>
<p id='conversion'>
</p>
<p id='clear'>
<input type="button" id="but" value="Clear" onclick="clear()"/>
</p>
There seems an error in your clear() function. it should be document.getElementsByTagName(). and yours is "documents" - also clear is a word used elsewhere: document.clear

Categories