I have a subtotals function that does some calculations on an html table (sums up columns that have assigned classes). I have modified it so that I can pass arguments to it, and on the first function call it works as desired. When I call it again it creates the cell and assigns the class, but the math or apparently something else is wrong because it is returning NaN. Here is my JSFiddle and below is my function. Any help would be appreciated!
//v is parent,z is child element,w is which child column....ex: 0 or 1, y is first run or not, z is class name you want assigned
function subtotals(v, w, x, y, z) {
$(v).each(function (index, element) {
var subTotalAmt = 0;
var numRows = parseInt($(this).attr("rowspan"));
var firstRow = $(this).parent();
var lastRow = firstRow.nextAll('tr').slice(numRows - 2, numRows - 1);
var currentRow = firstRow;
for (i = 0; i < numRows; i++) {
subTotalAmt += parseInt($(currentRow.children(w)[x]).text());
currentRow = currentRow.next("tr");
}
if(y == 'yes'){
lastRow.after('<tr><td class="sub0">Sub Total</td><td class="' + z + '">' + subTotalAmt + '</td></tr>');
$(this).attr('rowspan', numRows + 1);
}
else {
lastRow.append('<td class="' + z + '">' + subTotalAmt + '</td>');
}
});
}
$(function doSubtotals() {
subtotals('.parent','.child','1','yes','sub1');
subtotals('.parent','.child','2','no','sub2');
});
Some of your <td> are not containing a valid number , which case the calculation to fail and put NaN (stands for 'Not a Number') instead of a valid number (NaN + number = NaN).
To fix this i added this condition to your code :
for (i = 0; i < numRows; i++) {
var tdValue=0;
if(!isNaN(parseInt($(currentRow.children(w)[x]).text())))
{
tdValue=parseInt($(currentRow.children(w)[x]).text());
}
subTotalAmt += tdValue;
currentRow = currentRow.next("tr");
}
Related
I have a problem with the following code. I am trying remove rows from a table if that row does not contain the meat in the td. To clarify, when the function is called, it takes in 2. (Which is where the word meat can be found in the table)
Some of the rows do not contain the word meat, x = rows[i].getElementsByTagName("td")[a]; The word meat can be found in [a] of the row. I think the problem is with x.innerHTML, as I don't think it returns a value to compare to b.
Any help or leads are appreciated. Right now when the button is clicked to call the function, nothing happens.
function clearTable(a) {
var table, rows, switching, i, x, c, shouldSwitch;
table = document.getElementById("Invtable");
switching = true;
var b = "meat";
while (switching){
switching = false;
rows = table.getElementsByTagName("tr");
for (i = 0; i < (rows.length); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("td")[a];
if(x.innerHTML.toLowerCase() != b){
shouldSwitch= true;
break;
}
}
if (shouldSwitch) {
table.deleteRow(i);
switching = true;
}
}
}
var table = "<tr>";
for (var i = 0; i < array.length; i++) {
table += "<tr>";
for (var j = 0; j < array[i].length; j++) {
if (j == 6) {
table += "<td> <img src='CSV_Photos/" + array[i][j] + "' style ='width:250px;height:250px'>" + "<br>" //every 6th column is a picture
+ "<center> " + '<button id="btn" onClick="clickMe(\''+ array[i][1] + ',' + array[i][5] + '\')"> Buy / Add To Cart </button> </td>' + "</center>"; //button onclick takes (name+price)
} else {
table += "<td>" + array[i][j] + "</td>";
}
}
table += "</tr>";
}
Edit: Starting from the var table, that's how the table was made in javascript in a function.
The table code in html looks like this :
<tr><td>1000</td><td>Chicken</td><td>Meat</td><td>Perfect</td><td>Yes</td><td>$2.99</td><td>image</td> </tr>
The problem is you are passing the incorrect column number as the argument. You only have two td per row and the index starts at 0. So you have to pass 1 as your argument: clearTable(1).
I created a simple table so you can see your function works with the correct argument.
EDIT
I recreated my table to have 6 columns and I created a button that runs the function onClick.
var table = '<table id="Invtable"><tr><td>Food</td><td>chicken</td><td>Veggies</td><td>Ceral</td><td>Soda</td><td>Water</td></tr><tr><td>Food</td><td>water</td><td>Soda</td><td>Meat</td><td>Water</td><td>Ceral</td></tr><tr><td>Third-Food</td><td>Meat</td><td>Chicken</td><td>Ceral</td><td>Water</td><td>Soda</td></tr></table>';
var btn = '<button onClick="clearTable(1)">Meat</button>';
document.body.innerHTML = table + btn;
//clearTable(1);
function clearTable(a) {
var table, rows, switching, i, x, c, shouldSwitch;
table = document.getElementById("Invtable");
switching = true;
var b = "meat";
while (switching){
switching = false;
rows = table.getElementsByTagName("tr");
console.log(rows);
for (i = 0; i < (rows.length); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("td")[a];
if(x.innerHTML.toLowerCase() != b){
shouldSwitch= true;
break;
}
}
if (shouldSwitch) {
table.deleteRow(i);
switching = true;
}
}
}
I have some JavaScript code that should display a matrix of checkboxes. I want to list the column titles across the top, and then put rows where there is a column of checkboxes under each header, plus a left-hand column with row names under a blank header box. I'm going for the look on this page:
http://codepen.io/marclundgren/pen/hgelI
I wrote a Fiddle that almost works:
https://jsfiddle.net/bv01xvdf/
The first problem is that my table displays the checkboxes on a separate line from the cell with the row name. I checked my HTML, and it seems correct, but I'm wondering if I'm missing a <tr> or a </tr> somewhere. I add the row name cell like this (see the Fiddle for complete code):
var chugNames = ["Ropes", "Cooking", "Outdoor Cooking"];
for (x = 0; x < chugNames.length; x++) {
// Add a row for each name.
target.append("<tr><td>" + chugNames[x] + "</td>");
for (y = 0; y < chugNames.length; y++) {
target.append("<td><input type=\"checkbox\" />");
checkbox = $('</input>', {
'type': 'checkbox',
'data-x': chugNames[x],
'data-y': chugNames[y],
});
target.append(checkbox);
target.append("</td>");
}
target.append("</tr>");
}
The other problem is that data-x and data-y return "undefined" when I access them later in my "on" method:
target.on('change', 'input:checkbox', function() {
var $this = $(this),
x = $this.data('x'),
y = $this.data('y'),
checked = $this.prop('checked');
alert('checkbox changed chug intersection (' + x + ', ' + y + '): ' + checked);
});
When I check a box, I get "checkbox changed chug intersection (undefined, undefined): true". It should print something like (Ropes, Cooking), depending on which box was checked.
Any help would be greatly appreciated.
When you append with jQuery the tag is automatically closed.
check the jsfiddle
Try this:
$(function() {
var target = $('#checkboxes');
var chugNames = ["Ropes", "Cooking", "Outdoor Cooking"];
var i, x, y, checkbox, html;
html = "<table class=\"responsive-table-input-matrix\"><thead><tr><th></th>";
// Table column headers
for (i = 0; i < chugNames.length; i++) {
html += "<th>" + chugNames[i] + "</th>";
}
html += "</tr></thead><tbody>";
for (x = 0; x < chugNames.length; x++) {
// Add a row for each chug.
html += "<tr><td>" + chugNames[x] + "</td>";
for (y = 0; y < chugNames.length; y++) {
html += "<td>";
checkbox = '<input type=checkbox ';
checkbox += ' data-x=' + chugNames[x]
checkbox += ' data-y=' + chugNames[y]
checkbox += '/>'
html += checkbox;
html += "</td>";
}
html += "</tr>";
}
html += "</tbody></table>";
target.append(html).width(function() {
return $(this).find("input:checkbox").outerWidth() * chugNames.length
});
target.on('change', 'input:checkbox', function() {
var $this = $(this),
x = $this.data('x'),
y = $this.data('y'),
checked = $this.prop('checked');
alert('checkbox changed chug intersection (' + x + ', ' + y + '): ' + checked);
});
});
I fixed your jsfiddle here.
For the record, you had a few problems, an extra <th></th> in the opening string, an extra output of ChugName[x] and you didn't use the attr() jQuery function to get the data attributes properly.
I have a function with this specific array in it.
var elementsArray = xmlDocument.documentElement.getElementsByTagName('track');
// console.log(elementsArray);
var arrayLength = elementsArray.length;
var output = "<table>";
for (var i=0; i < arrayLength; i++)
{
var title = elementsArray[i].getElementsByTagName('title')[0].firstChild.nodeValue;
var artist = elementsArray[i].getElementsByTagName('artist')[0].firstChild.nodeValue;
var length = elementsArray[i].getElementsByTagName('length')[0].firstChild.nodeValue;
var filename = elementsArray[i].getElementsByTagName('filename')[0].firstChild.nodeValue;
console.log(title + ' ' + artist + ' ' + length + ' ' + filename);
output += "<tr>";
output += ("<td onclick='songSelect(\"" + filename + "\")'>" + title + "</td><td>" + artist + "</td>");
output += "</tr>";
}
With this array how would i generate a previous and next button to move.
http://jsfiddle.net/xbesjknL/
Once could use a linked list or even the notion of C-like pointers that point at the prev/curr/next tracks. But alas this is Javascript and the client side is too processing burdened.
So you could just build your own simplified idea of pointers in a cursor like object that is constantly pointing at the current track's index, the previous track's index and the next. And you'd call the refresh method everytime the user clicks the prev or next buttons to update the cursor's pointers accordingly.
var cursor = {
prev:(elementsArray.length-1),
curr:0,
next:(1 % (elementsArray.length-1)),
refresh: function(button){ //button is either the btnPrev or btnNext elements
if (button.getAttribute("id") === "btnPrev") {
old_curr = this.curr;
this.curr = this.prev;
if ((this.curr-1) < 0)
this.prev = elementsArray.length-1;
else
this.prev = this.curr - 1;
this.next = old_curr;
} else {
old_curr = this.curr;
this.curr = this.next;
if ((this.curr+1) > (elementsArray.length-1))
this.next= 0;
else
if (elementsArray.length === 1)
this.next = 0;
else
this.next = this.curr+1;
this.prev = old_curr;
}
}
};
// example usage:
cursor.refresh(btnPrev);
elementsArray[cursor.curr]; // gives the previous track, which is now the current track
You can even simplify this even more by just keeping track of only the current track. Note
Most of the action is in the function next. The other functions are provided for context. The global variable tally increments as it should when the right answer is selected. However the variable nr is not incremented and I can't figure out way it is not.
You can see that I commented out that the next function returned an object with tally and nr and assigned those values in the event listener. When I did it that way, it worked. But it should work the other way as well, right.
var nr = 0;
var tally = 0;
function onLoadEvent(nr) {
//alert('onload');
var quiz = document.getElementById('quiz');
var question = allQuestions[nr];
var next = quiz.lastElementChild;
var qHeader = "<h2>" + question.question + "</h2>";
var q = "";
for(var i=0;i<question.choices.length;i++){
q = q + '<p><label for="a' + i + '">' +
'<input type="radio" id="a' + i + '" name="q" value="' +
i + '">' + question.choices[i] + '</label></p>';
}
quiz.innerHTML = qHeader + q + next.outerHTML;
//next = document.getElementById('next');
}
function getChecked(){
var radios = document.getElementsByName('q');
var radio;
for(var i=0;i<radios.length;i++){
if(radios[i].checked){
radio = radios[i];
break;
}
}
return radio;
}
function next(nr){
if (getChecked() !== undefined) {
var answer = getChecked();
if(answer.value == allQuestions[nr].correctAnswer){
tally = tally + 1;
}
nr = nr + 1;
if (nr>=allQuestions.length){
alert("You got " + tally + " points!");
} else {
onLoadEvent(nr);
}
} else {
alert('You need to check a radio button');
}
//return {nr: nr, tally: tally};
}
var form = document.getElementById('quiz');
form.addEventListener('click', function(event){
if(event.target.id === 'next'){
next(nr);
//nr = obj.nr;
//tally = obj.tally;
} else if(event.target.id === 'prev'){}
}, false);
window.addEventListener('load', function(event){onLoadEvent(nr);}, false);
You are accepting parameters with same name nr which is hiding global scope nr.
Solution to your problem is remove nr as parameter. So use function onLoadEvent() instead of function onLoadEvent(nr)
Hi i tried to access a variable as follows,
for(var k=0;k<resultSet.length;k++)
{
alert(resultSet[k]);
$.get('/api/TagsApi/ElementsTagsIntersect?ids='+resultSet[k], function (data) {
testingarr = [];
for (var i = 0; i < data.length; i++) {
testingarr.push(data[i]["ID"]);
}
for (var w = 0; w <3; w++) {
if (($.inArray(testingarr[w], selectedloc)) > -1) {
var str = "<input type='checkbox' name ='test[]' value='" + resultSet[k] + "'/>" + resultSet[k] + "</br>";
$('#childs').append(str);
alert(resultSet[k]);
break;
}
}
}, 'json');
where first alert displays the exact value what i am expecting but when it comes to the inner for loop, alert returns undefined and adds a check box with undefined side to it.. i think i am using the proper initializations but confused why it does so?
The reason is that k changes value, so by the time the inner function gets called, k is already equal to resultSet.length. You can wrap the whole thing in another function and pass k as a parameter to bind it to a new variable that won't change with the original k:
for(var k=0;k<resultSet.length;k++)
{
(function (result) {
$.get('/api/TagsApi/ElementsTagsIntersect?ids='+result, function (data) {
var testingarr = [];
for (var i = 0; i < data.length; i++) {
testingarr.push(data[i]["ID"]);
}
for (var w = 0; w <3; w++) {
if (($.inArray(testingarr[w], selectedloc)) > -1) {
var str = "<input type='checkbox' name ='test[]' value='" + result + "'/>" + result + "</br>";
$('#childs').append(str);
break;
}
}
}, 'json');
})(resultSet[k]);
}