Simply working on a homework assignment, at the end, just need to display this method 5 times. Issue is as title states once I invoke the function the next invoke overwrites past invoke.
Heres what I am currently doing.
<p id="table">
<script type="text/javascript">
showResults(race[0], name1, party1, votes1);
showResults(race[1], name2, party2, votes2);
showResults(race[2], name3, party3, votes3);
showResults(race[3], name4, party4, votes4);
showResults(race[4], name5, party5, votes5);
</script>
</p>
I have used a debugger to try and find a fix, browsed the internet for about an hour now, tried to use a .call but couldn't quite get that working either and I know document.write isn't a viable option because it rewrites everything.
Any help or useful links on the issue would be really appreciated!
Here is the showresults function
function showResults(race, name, party, votes)
{
var totalV = totalVotes(votes);
var result = "";
result += "<h2>" + race + "</h2>";
result += "<table cellspacing = '0'>";
result += "<tr>";
result += "<th>Candidate</th>"
result += "<th class='num'>Votes</th>";
result += "<th class='num'>%</th>";
result += "</tr>";
for (var i = 0; i < name.length; i++)
{
result += "<tr>";
result += "<td>" + name[i] + '(' + party[i] + ')' + "</td>";
result += "<td class='num'>" + votes[i] + "</td>";
var percent = calcPercent(votes[i], totalV)
result += "<td class='num'>(" + percent + "%)</td>";
result += createBar(party[i], percent);
result += "</tr>";
}
result += "</table>";
document.getElementById("table").innerHTML = result;
}
The Statement
document.getElementById("table").innerHTML = result;
Sets the innerHTML of your "table" element, thus overwriting it each time you set it.
try to
append(result);
to a existing DOM node so your result gets appended to the document.
Related
I have a class project where I need to pull data from my SQLite DB and place it into <table>.
But every time I reload the page I get this Table image and I was hoping for some help. I'm new to JavaScript and I need to finish this task in a few hours, I've tried to pull the data into an object and from the object into this line str += "<td>" + results.rows.item(i).Firstname + "</td>" and still it didn't work.
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM Customers_Table ', [], function (tx, results) {
var len = results.rows.length, i;
document.getElementById("tablea").innerHTML = '';
var str = '';
str += "<th>FirstName</th>";
str += "<th>LastName</th>";
str += "<th>Address</th>";
str += "<th>City</th>";
str += "<th>Email</th>";
for (i = 0; i < len; i++) {
str += "<tr>";
str += "<td>" + results.rows.item(i).Firstname + "</td>";
str += "<td>" + results.rows.item(i).Lastname + "</td>";
str += "<td>" + results.rows.item(i).Address + "</td>";
str += "<td>" + results.rows.item(i).City + "</td>";
str += "<td>" + results.rows.item(i).Email + "</td>";
str += "</tr>";
document.getElementById("tablea").innerHTML += str;
str = '';
}
});
});
Well, considering that you have data in results. It should be used as:
results.rows.item[i].Firstname
NOT
results.rows.item(i).Firstname
Finally figured out the problem, the .Firstname and the rest didn't match the column names from the Db table, it was lowercase,look carefully at your code guys!!
I know I'm asking really simple questions but I'm a beginner and it the process of learning. I've got this code but I don know how to make it work. The output i expect is upon clicking the button it activates function insertAfter and adds text/paragraph that ill write.
I've tried: onclick='insertAfter(test,index.this)'
It didn't work and consoled said it was undefined.
var content = "";
Applications.forEach(generatetable);
function testfn(index, tdElement) {
console.log(tdElement.parentElement);
console.log(index);
console.log(Applications[index].Name);
}
function generatetable(item, index, arrays) {
var columns = "";
columns = columns + "<td onclick='testfn(\"" + index + "\", this)'>" + "<button onclick='insertAfter(test?,???)' type=\"button\">Click Me!</button>" + item.UAID + "</td>";
columns = columns + "<td>" + item.Name + "</td>";
columns = columns + "<td>" + "<a href='www.wahtever.com'>map</a>" + "</td>";
content = content + "<tr>" + columns + "</tr>";
}
var test = "<tr><td>fsdf</td></tr>";
document.getElementById("table").innerHTML = content;
function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
It is supposed to insert a paragraph preferably what i put in the test variable but if there is better is better solution please let me know.
<button onclick='insertAfter(test,ElementID)>
The second refference node (ElementID) should be be the id of the element after which it is to be put. So it has to be somehow refferenced for example by id.
I can show orderB.id as table data. I want to use this value in the href, but I am struggling with syntax.
var output = results.reduce(function (orderA, orderB){
var row = "<tr>";
row += "<td>" + orderB.name + "</td>";
row += "<td>" + orderB.type + "</td>";
row += "<td>" + orderB.id + "</td>";
row += "<td><a href='/update/' + orderB.id + >Update</a></td>";
return orderA + row;
},"")
I have tried:
row += "<td><a href='/update/' + orderB.id + >Update</a></td>";
row += "<td><a href='/update/' + 'orderB.id' + >Update</a></td>";
row += "<td><a href='/update/orderB.id' + >Update</a></td>";
These output:
/update/
/update/
/update/orderB.id
I want for example: /update/3
use template literals :
row += `<td>Update</td>`;
or simply concat your variables with the htmml string like :
row += '<td>Update</td>';
As has been suggested, template literals are a good way to go, but you have to be careful about just sticking strings together to create HTML -- if there are characters like <, >, or & there can be problems. I'd use Lodash and modify the answer given by another poster like this:
row += `<td>Update</td>`;
I have the following code, in which a table is built in JavaScript and passed to the HTML using an ID.
html += "<tbody>"
for (var i = 0; i < list.length; i++) {
html += "<tr><td>" + list[i].GroupId + "</td>";
html += "<td>" + list[i].GroupType + "</td>";
html += "<td>" + list[i].GroupName + "</td>";
html += "<td>" + list[i].Updated + "</td>";
html += "<td>" + list[i].MemberCount + "</td>";
}
html += "</tbody>"
My problem is that list[i].Updated returns a date and it looks like the following /Date(1448996589783)/. How can I convert this so it displays as the proper date on the page?
Thanks for the help people, but after messing around and a lot of google searching I managed to figure this out. I created another function as shown below in the JavaScript file:
function parseJsonDate(jsonDateString)
{
return new Date(parseInt(jsonDateString.substr(6))).toLocaleString();
}
and updated my list[] to this:
html += "<td>" + parseJsonDate(list[i].Updated) + "</td>";
and when run it displays exactly what I wanted: 12/1/2015 7:03:09 PM
I know that the a in ajax means asynchronous, and as such there is no guarantee which order my responses will come back in, in fact its reasonable to expect the largest payload to return last.
My question however is regarding the callbacks. Sometimes when I notice my responses come back in a different order to which they were sent, the 'wrong' callback is invoked.
Take the function below.
There are some values (rangesize, dropskus, limit) (commented below) which are unique to each call, and defined in the success callback for each. When I run the script and send 5 calls, if they do come back in a different order to which they were sent. Let's say the largest response was the 2nd call to be made, that response comes back last and also invokes the last callback function.
So my question:
Does or should JavaScript / jQuery know which callback function to invoke when returning multiple responses?
Or would it be better for me to use synchronous calls?
Other notes:
When debugging in chrome, I noticed that the console logs of the responses say filename.js:linenumber. Whereas previously when I've used multiple ajax calls the console logs say VM12*:linenumber. I don't know if this has anything to do with the issue I'm facing, but I did notice that when this was the case the correct callbacks were always invoked.
function generateReview(){
var subcategories = subcatstring.split(",");
$("#rangereviewtable").html("");
$("#rangereviewtable").append(thead);
var i = 0;
var iterations = subcategories.length;
$.each(subcategories, function(key, value) {
var postdata = {group: group,
class: rrclass,
category: category,
subcategory: value,
period: period,
periodval: periodval,
stores: storesarray};
console.log(postdata);
$.ajax({
url: "ajaxrangereview.php",
type: "post",
dataType: 'json',
data: postdata,
success: function (response) {
//VALUES UNIQUE TO EACH CALL
var rangesize = parseInt($("#rangesize" + i).text());
console.log("range size: " + rangesize);
var dropskus = parseInt($("#dropskus" + i).text());
console.log("dropskus: " + dropskus);
var limit = rangesize - dropskus;
console.log("limit: " + limit);
console.log(response);
var rrtable = "";
$.each(response, function(i, item) {
rrtable += "<tr>";
rrtable += "<td class='rangereviewtext'>" + item.category + "</td>";
rrtable += "<td class='rangereviewtext'>" + item.subcategory + "</td>";
rrtable += "<td class='rangereviewtext'>" + item.brand + "</td>";
rrtable += "<td class='rangereviewtext'>" + item.sku + " - " + item.product + "</td>";
rrtable += "<td class='rangereviewnumber'>" + item.py3.toLocaleString("en") + "</td>";
rrtable += "<td class='rangereviewnumber'>" + item.py2.toLocaleString("en") + "</td>";
rrtable += "<td class='rangereviewnumber'>" + item.py1.toLocaleString("en") + "</td>";
rrtable += "<td class='rangereviewnumber'>" + item.average.toLocaleString("en") + "</td>";
rrtable += "<td class='rangereviewnumber'>" + item.sales.toLocaleString("en") + "</td>";
rrtable += "<td class='rangereviewnumber'>" + item.share + "%</td>";
rrtable += "<td>✔</td>";
if(limit >= item.idnum){
rrtable += "<td>✔</td>";
rrtable += "<td class='checkboxcell' onClick=\"toggleCheckMark(this, '" + item.brand + "')\">✔</td>";
} else {
rrtable += "<td></td>";
rrtable += "<td class='checkboxcell' onClick=\"toggleCheckMark(this, '" + item.brand + "')\"></td>";
}
rrtable += "</tr>";
});
// increment iterations
i += 1;
$("#rangereviewtable").append(rrtable);
if(i == iterations){
var headimage = "<img src='http://url.com/images/oimage.png' width='63.5px' height='76px'>";
var table = $("#rangereviewtable").DataTable({
buttons: [{extend: 'excelHtml5', title: 'Range Review', text: 'Export to Excel'},
{extend: 'print', title: 'Range Review', message: headimage}],
});
//insert export to excel button into #rrbuttons div above actual table.
table.buttons().container().appendTo( $('#rrbuttons') );
$("#rangereviewpanel").show();
$("#generatebutton").hide();
$("#loadbutton").hide();
$("#saveasbutton").show();
generateReviewSummary(summaryarray);
} else {
//do nothing not all iterations complete
}
},
error: function(jqXHR, textStatus, errorThrown) {
i+= 1;
console.log(textStatus, errorThrown);
}
});
});
}
In your specific case I think it will work fine (your code does something like):
var j = 0;
for (var i = 0; i < 10; i++) {
setTimeout(function () {
console.log(j);
j++
}, 1000)
}
This code will outputs numbers 0..9;
But let see another example:
for (var i = 0; i < 10; i++) {
setTimeout(function () {
console.log(i);
}, 1000)
}
It outputs 9..9
So it is not safe approach to call async functions inside synchronous loop. You can use async.each (https://github.com/caolan/async#each) or promises to handle it.
JavaScript / jQuery knows exactly what callback to invoke, and is doing so correctly.
You need to learn more about JavaScript closures and scope.
I'm not sure what you mean by 'wrong' and 'right' callback with respect to your logic. If you want the special-logic to kick-in when you receive the response to the last request, then perhaps you could try replacing your use of i with references to key instead (or if I'm reading your logic correctly, you might want to use key + 1)