i have this situation:
...
for (var i = 0; i < json.length; i++)
{
output += '<tr>';
for ( var objects in json[i])
{
if (objects == 'amt_1')
{
output += '<td id="amt">' + json[i][objects] + '</td>';
}
}
output += '</tr>';
}
output += '<tr">';
var amt = 0;
$('#amt').each(function() {
amt += $(this).text();
});
output += '<td>' + amt + '</td>';
output += '</tr>';
$('#details').append(output);
}
this is a part of a table that give's me something like this:
<td id="amt">4.58</td>
<td id="amt">55.74</td>
<td id="amt">193.5</td>
<td></td>
and in the last td i would like the sum of the rest of them with the id = amt
what i have seems not to work
any ideas?
Thnaks
The problem is that you are using id's instead of classes, id's are supposed to be unique, so javascript only returns 1 td. Multiple elements however, can share the same class.
Also, the jQuery won't work because the elements haven't been added to the document yet.
for (var i = 0; i < json.length; i++)
{
output += '<tr>';
for ( var objects in json[i])
{
if (objects == 'amt_1')
{
output += '<td class="amt">' + json[i][objects] + '</td>';
}
}
output += '</tr>';
}
output += '<tr">';
$('#details').append(output); //Copied here, this will add the above elements
//to the document subtree, which allows jquery
//to search for them
output = ""; //Reset output
var amt = 0;
$('.amt').each(function() { //Changed to class selector
amt += parseInt($(this).text());
});
output += '<td>' + amt + '</td>';
output += '</tr>';
$('#details').append(output); //Append result
Like they said you should use a class instead of id
output += '<td class="amt">' + json[i][objects] + '</td>';
Then you must add the output to the DOM before your jQuery selector, $('.amt'), can find the elements
$('#details').append(output); //<--append BEFORE you select the .amt elements
var amt = 0;
$('.amt').each(function() {
amt += parseFloat($(this).html()); //parseFloat on the html
});
output = '<tr">'; //<-- reset output here
output += '<td>' + amt + '</td>';
output += '</tr>';
$('#details').append(output);
Still it would be better to just sum the amount in your for loop
var total = 0;
...
if (objects == 'amt_1')
{
var curAmt = json[i][objects];
output += '<td class="amt">' + curAmt + '</td>';
total += parseFloat(curAmt);
}
...
output += '<td>' + total + '</td>';
You can't have more than one element with the same id on a page. $("#someId") will always select at most 1 element. So, your first problem is you don't even have a list of elements. You can solve that by using class instead.
Once you resolve the id issue, the trouble you'll have is you are trying to add text as though it were a number. First, you convert text to a number in one loop, then you loop through your entire collection again and try to add the textual numbers. Just get the total during the first loop. You'll be adding numbers instead of text, and you'll only have to iterate your collection once.
Also, you don't need to iterate the keys of an object just get a property. You can just reference the property directly: json[i].amt_1
While we're at it, let's not build up the html string, but instead just create the DOM elements directly. And take advantage of $.each() to do our looping.
var total = 0;
$.each(json, function (i, item) {
var row = $('<tr>').appendTo("#details");
$("<td>").appendTo(row).addClass("amt").text(item.amt_1);
total += item.amt_1;
});
var row = $("<tr>").appendTo("#details");
$("<td>").appendTo(row).text(total);
Related
I want to make some part of my code stop looping, but keep looping for another variable. How can I possibly do that ? I tried this code but it's not working
// Looping based on number of data
for ( var i = 0; i < data.length; i++ ) {
// Looping HTML table data output
if ( !search || data[i].some(someSearch) ) {
// Output table HTML + indexing number
outputTable: {
output += '<tr>';
output += '<td>' + index + '</td>';
for ( var j = 0; j < data[i].length; j++ ) {
output += '<td>' + data[i][j] + '</td>';
}
output += '</tr>';
index++;
}
// Data display limitation
// based on combobox value
if ( index > parseInt(searchLimit.val()) ) {
break outputTable;
}
}
// Count filtered data
searchFiltered++;
}
From that code, I want to break the part of code inside outputTable label, but keep searchFiltered looping. Can someone help me? Thanks :)
No need to use break statement here. Put if condition like this. Every time the index value check it is lesser than parseInt(searchLimit.val()). if it is not it exit the if statement.
if ( index < parseInt(searchLimit.val()) ) {
outputTable: {
output += '<tr>';
output += '<td>' + index + '</td>';
for ( var j = 0; j < data[i].length; j++ ) {
output += '<td>' + data[i][j] + '</td>';
}
output += '</tr>';
index++;
}
}
I have a for loop that pushes targeted properties into an array if they pass a certain condition. I would like to create a table that outputs each item into its own row. The tricky part for myself is understanding how this can be done dynamically. It's easy to hardcode each item from the array and insert it into a row. But can this be done automatically using pure JS?
script.js
var myArray = [];
for (var i = 0; i < ccirdata.length; i++) {
if (ccirdata[i].catType === 'I') {
myArray.push(ccirdata[i].catNum);
}
};
In the same file,
I have the outline for my table where I'm trying to insert the iterations from 'myArray':
var header =
"<thead>" +
"<tr>" +
"<td class='legend-color-guide'><div style='background-color: " + series.color + ";'></div></td>" +
"<td class='key'>" + " My Table:</td>" +
"</tr>" +
"</thead>";
var rows =
"<tr>" +
"<td class='key'><strong>" + <INSERT HERE> + "</strong></td>" +
"</tr>"
return "<table>" + header + "<tbody>" + rows +"</tbody>" + "</table>";
How can I create a new row dynamically for each item in myArray?
Here's one approach:
// using the same header code you provided
var rows = "";
myArray.forEach(function(item, index) {
rows += "<tr>";
rows += "<td class='key'><strong>" + item + "</strong></td>";
rows += "</tr>";
});
return "<table>" + header + "<tbody>" + rows +"</tbody>" + "</table>";
You can loop through myArray to create each row and concatenate them into a larger string.
var rows = "";
for (var r = 0; r < myArray.length; r++) {
var row = "<tr>" + "<td class='key'><strong>" + myArray[r] + "</strong></td></tr>";
rows = rows.concat(row);
}
Instead of building a text string to later set as HTML, I would opt for using a cleaner approach with insertRow like this:
<table>
<thead>
<tr><td>A header</td></tr>
</thead>
<tbody>
</tbody>
</table>
<script type="text/javascript">
var values = ['foo', 'bar', 'baz']; // Values to insert in table
// Get a reference to the <tbody> element
var tbody = document.querySelector('tbody');
for (var i = 0; i < values.length; i++) {
// This appends a new row to the <tbody> and returns a reference
// to that element
var row = tbody.insertRow();
// Similarly to append a cell to the row
var cell = row.insertCell();
// Create a text node for the textual content and append it
// to the cell
var text = document.createTextNode(values[i]);
cell.appendChild(text);
}
</script>
As demonstrated in this JSFiddle.
For example : I want to insert many tr in a table like this
var tbody = $('#tbody')
// Suppose the articlelist is the data from ajax
while (articlelist.length > 0) {
var article = articlelist.shift(),
var tr = $(' <tr>'
+' <td>'+article.id+'</td>'
+'<td>' + article.channelid +'</td>'
+ '<td>'+article.comment+'</td>'
+'<td>'+article.last_edit_time+'</td><td>'
)
tbody.append(tr)
}
To avoid create the <tr>...</tr> in loop .Is it possible to use a class to generate the tr content ?
An optimized version:
var tbody = $('#tbody'),
htmlStr = "";
for (var i = 0, len = articlelist.length; i < len; i++) { // avoid accessing 'length' property on each iteration
htmlStr += '<tr><td>' + articlelist[i].id + '</td>'
+ '<td>' + articlelist[i].channelid + '</td>'
+ '<td>' + articlelist[i].comment + '</td>'
+ '<td>' + articlelist[i].last_edit_time + '</td><td><tr>';
}
tbody.append(htmlStr); // parses the specified text as HTML or XML and inserts the resulting nodes
You could use a loop to concatenate all the strings, then append this lengthy string all at once. This would help with performance for many trs
var tbody = $('#tbody')
var rows = ''
while (articlelist.length > 0) {
var article = articlelist.shift(),
rows += '<tr><td>'+article.id+'</td>'
+'<td>' + article.channelid +'</td>'
+ '<td>'+article.comment+'</td>'
+'<td>'+article.last_edit_time+'</td><tr>';
}
tbody.append(rows)
add a function like this to do this for you.
while (articlelist.length > 0) {
make_content(article);
}
function make_content(article) {
var tbody = $('#tbody');
var tr = $(' <tr>'
+' <td>'+article.id+'</td>'
+'<td>' + article.channelid +'</td>'
+ '<td>'+article.comment+'</td>'
+'<td>'+article.last_edit_time+'</td><td>'
)
tbody.append(tr)
}
I have a piece of code that I am working with where the user can choose to download a "Slice" of a pie chart or the whole thing.
When they click on a slice, I send a variable called source which tells me which slice it came from.
Right now I am working on the "Download All" button. The source for this will be simply all.
This is what my loop looks like if the user selects slice:
// Loop over our data
$.each(seed.dataset,function(key, value){
if(this[col] == slice){
table += '<tr>';
table += '<td>'+this.escalationID+'</td>';
table += '<td>'+this.escReasonID+'</td>';
table += '<td>'+this.reasonText+'</td>';
table += '<td>'+this.escCreatedBy+'</td>';
table += '<td>'+this.escCreatorFirst+'</td>';
table += '<td>'+this.escCreatorLast+'</td>';
table += '</tr>';
}
});
The IF statement within the loop is what controls the data its including in the table variable. My question is, how can I choose when I want to enforce this IF statement or ignore it (allowing all data to be added to the table var)?
The obvious would be wrapping it in another IF statement but I feel there might be a cleaner way without having to duplicate all of the table data.
End result would be a bool saying if source=All include all the rows else if source=slice enforce the IF statement to include only the data we are looking for.
UPDATE
Essentially I am looking for a more clean way to do this:
// Loop over our data
$.each(seed.dataset,function(key, value){
if(source == 'slice'){
if(this[col] == slice){
table += '<tr>';
table += '<td>'+this.escalationID+'</td>';
table += '<td>'+this.escReasonID+'</td>';
table += '<td>'+this.reasonText+'</td>';
table += '<td>'+this.escCreatedBy+'</td>';
table += '<td>'+this.escCreatorFirst+'</td>';
table += '<td>'+this.escCreatorLast+'</td>';
table += '</tr>';
}
// We are downloading all so ignore the constraint
}else{
table += '<tr>';
table += '<td>'+this.escalationID+'</td>';
table += '<td>'+this.escReasonID+'</td>';
table += '<td>'+this.reasonText+'</td>';
table += '<td>'+this.escCreatedBy+'</td>';
table += '<td>'+this.escCreatorFirst+'</td>';
table += '<td>'+this.escCreatorLast+'</td>';
table += '</tr>';
}
});
You can use another boolean say ignoreAll as "OR" condition with existing if condition as shown below
// Loop over our data
var ignoreAll = true; // change its value as per your requirement
$.each(seed.dataset,function(key, value){
if(ignoreAll || this[col] == slice){
table += '<tr>';
table += '<td>'+this.escalationID+'</td>';
table += '<td>'+this.escReasonID+'</td>';
table += '<td>'+this.reasonText+'</td>';
table += '<td>'+this.escCreatedBy+'</td>';
table += '<td>'+this.escCreatorFirst+'</td>';
table += '<td>'+this.escCreatorLast+'</td>';
table += '</tr>';
}
});
$.each(seed.dataset,function(key, value){
if (source != 'slice' || this[col] == slice){
table += '<tr>';
// etc.
Alternatively:
$.each(seed.dataset,function(key, value){
if (source == 'all' || this[col] == slice){
table += '<tr>';
// etc.
Check out the below code.
If the current item is a slice, it's checked to make sure it is the correct slice. If it is, getSlice() is called and the $.each() loop breaks to avoid unnecessary iterations.
function getSlice(that) {
var table = '';
table += '<tr>';
table += '<td>' + that.escalationID + '</td>';
table += '<td>' + that.escReasonID + '</td>';
table += '<td>' + that.reasonText + '</td>';
table += '<td>' + that.escCreatedBy + '</td>';
table += '<td>' + that.escCreatorFirst + '</td>';
table += '<td>' + that.escCreatorLast + '</td>';
table += '</tr>';
return table;
}
// Loop over our data
$.each(seed.dataset, function (key, value) {
table += source == 'slice' ? (this[col] == slice ? true & getSlice(this) : false) : getSlice(this);
if (table === true) return false; // break out of loop
});
I want to add a class to the first three database objects, then another class for the 4 to 6 objects and so on...
I found ways to break the loop but I hope there are better ways to accomplish bunches of three than to have to hardcode a lot of loops?
I'm thankful for all help!
http://jsfiddle.net/r61bce3z/
this is the basics of the loop i have:
var tableContent = '';
$.getJSON( '/users/insights', function( data ) {
userListData = data;
$.each(data, function(){
tableContent += '<ul>';
tableContent += '<li class="sub">' + this.date + '</li>';
tableContent += '</ul>';
});
The $.each() method calls your function with an index for the element it is up to. So use that with a little arithmetic as an index into an array of class names:
var classes = ['class1', 'class2', 'class3', 'class4'];
$.getJSON( '/users/insights', function( data ) {
userListData = data;
$.each(data, function(i){
tableContent += '<ul>';
tableContent += '<li class="' + classes[Math.floor(i/3) % classes.length]
+ '">' + this.date + '</li>';
tableContent += '</ul>';
});
});
Using Math.floor(i/3) gives you your groups of 3. Adding in % classes.length allows for if you have more groups of 3 than classes (so that you don't go past the end of the array of classes, it'll just start reusing the classes from the beginning of the array).
You can make it with some helper variables.
var tableContent = '';
var classIndex=-1;
$.getJSON( '/users/insights', function( data ) {
userListData = data;
$.each(data, function(index){
if(index % 3 == 0) classIndex++;
var css = classes[classIndex];
tableContent += '<ul>';
tableContent += '<li class="myClass' + classIndex + '">' + this.date + '</li>';
tableContent += '</ul>';
});
}