JavaScript works in Chrome but not ie9 [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am facing an issue with JavaScript.I see that it works fine in chrome but not in IE9.This would not display what chrome is displaying on the web page as expected.
I am new to JavaScripting can I get help in fixing this issue.
<script type="text/javascript">
var tds = document.getElementById('course_table')
.getElementsByTagName('td');
var sum = 0;
for (var i = 0; i < tds.length; i++) {
if (tds[i].className == 'count-me') {
sum += isNaN(tds[i].innerHTML) ? 0
: parseInt(tds[i].innerHTML);
}
}
var lastrecord = tds[tds.length - 2].innerHTML;
var table = document.getElementById('course_table')
.getElementsByTagName('tr');
var max = table.length - 2;
document.getElementById('course_table').innerHTML += '<tr bgcolor=#FFCCFF><td></td><td>Total Courses</td><td>' + max + '</td><td>Total Credits Remaining</td><td>'+ sum + '</td><td> Expected Graduation Date</td><td></td><td>' + lastrecord + '</td><td></td></tr> ';
</script>
Thanks
Niveditha

The problem is most likely in the last line:
document.getElementById('course_table').innerHTML += '<tr bgcolor=#FFCCFF><td></td><td>fsffd</td><td>' + max + '</td><td>abcdRemaining</td><td>'+ sum + '</td><td> abc</td><td></td><td>' + lastrecord + '</td><td></td></tr> ';
IE doesn't handle trs being added by strings; besides it is non-standard. Replace that line with this, it programmatically builds up the row and is faster. I added the corresponding <td> as comments.
var table = document.getElementById('course_table');
var row = table.insertRow(-1);
row.style.backgroundColor = '#FFCCFF'; // `bgcolor` attribute is deprecated
row.insertCell(-1); // <td></td>
row.insertCell(-1).textContent = "fsffd"; // <td>fsffd</td>
row.insertCell(-1).textContent = max; // <td>' + max + '</td>
row.insertCell(-1).textContent = "abcdRemaining"; // <td>abcdRemaining</td>
row.insertCell(-1).textContent = sum; // <td>' + sum + '</td>
row.insertCell(-1).textContent = "abc"; // <td> abc</td>
row.insertCell(-1); // <td></td>
row.insertCell(-1).textContent = lastRecord; // <td>' + lastRecord + '</td>
row.insertCell(-1); // <td></td>
The important methods here are insertRow and insertCell, they are guaranteed to work. textContent is faster and safer than innerHTML. Please use CSS instead of the deprecated bgcolor attribute

Internet Explorer doesn't like adding <tr> elements to the <table> in that manner. What you can do is append a new <tbody> element to the table:
// ... the first part of your function ...
var lastrecord = tds[tds.length - 2].innerHTML;
var table = document.getElementById('course_table');
var newbody = document.createElement('tbody');
newbody.innerHTML = '<tr bgcolor=#FFCCFF><td></td><td>Total Courses</td><td>' + max + '</td><td>Total Credits Remaining</td><td>'+ sum + '</td><td> Expected Graduation Date</td><td></td><td>' + lastrecord + '</td><td></td></tr> ';
table.appendChild(newbody);

Related

Creating a table through local storage data?

How can I populate my table with an array of local storage data?
function savePlayer() {
let Player = {player,score};
localStorage.setItem("Player", JSON.stringify(Player));
let getPlayerScore = Player;
let text = document.getElementById("topScores");
for(let i = 0; i <Player.length; i++){
text += "<tr>";
text += "<td>" + getPlayerScore[i].player + "</td>";
text += "<td>" + getPlayerScore[i].score + "</td></tr>";
}
Here's the HTML:
<body>
<table id = "topScores">
<tr>
<th>Username</th>
<th>Score</th>
</tr>
</table>
</body>
What am I doing wrong?
The Player.toString() isn't what you think it is.
var player = "Mario";
var score = 1000;
var Player = {
player,
score
};
// Print Player
console.log(JSON.stringify(Player));
console.log(Player.toString());
You can't just add text to an element; you need to set it though
innerHTML. Sadly, however, you can't set it for each row, because the DOM will try to end the tr tag, so you need to set everything at the same time through a string.
I couldn't get localStorage to work in the snippet so I commented out the code without testing it.
Another solution would be to append the elements, and honestly, that's what I would prefer, but I didn't want to steer to far away from your original solution, and I didn't want fix the "feature" where the DOM is autocompleting tr tags.
function savePlayer() {
// This wasn't an array to begin with, so I fixed that.
let Player = [{"player": "player","score": 10}];
// It's usually preferred to refer to a public constant when accessing localStorage.
let localStorageKey = "player";
/* localStorage.setItem(localStorageKey, JSON.stringify(Player));
let getPlayerScore = JSON.parse(localStorage.getItem(localStorageKey));*/
let getPlayerScore = Player;
let text = document.getElementById("topScores");
var playerRow = "";
for(let i = 0; i < getPlayerScore.length; i++){
playerRow = "<tr>";
playerRow += "<td>" + getPlayerScore[i].player + "</td>";
playerRow += "<td>" + getPlayerScore[i].score + "</td></tr>";
}
text.innerHTML += playerRow;
}
<body onload="savePlayer()">
<table id="topScores">
<tr>
<th>Username</th>
<th>Score</th>
</tr>
</table>
</body>

Javascript page-break

I need help
I have a problem with making reports invoices with pre-printed paper. when an item of the invoice exceeds the capacity, automatically the rest of the items will be printed onto a second page.
I use a javascript programming language. No one can give a solution?
for (var x = 1; x <= lineCount; x++){
var strItem = '';
var strUnit ='';
var strJumlah ='';
var strHargaSatuan ='';
var strHargaTotal ='';
if(recIV.getLineItemValue('item','item', x)){
strItem = recIV.getLineItemText('item','item', x);
}
if(recIV.getLineItemValue('item','units', x)){
strUnit = recIV.getLineItemText('item','units', x);
}
if(recIV.getLineItemValue('item','quantity', x)){
strJumlah = recIV.getLineItemValue('item','quantity', x);
}
if(recIV.getLineItemValue('item','rate', x)){
strHargaSatuan = recIV.getLineItemValue('item','rate', x);
}
if(recIV.getLineItemValue('item','amount', x)){
strHargaTotal = recIV.getLineItemValue('item','amount', x);
}
strName += ' <tr style=\"font-size:13px\" line-height=\"11px\">';
strName += ' <td width=\"10%\" align=\"center\">'+ x +'</td>';
strName += ' <td width=\"35%\">'+strItem+'</td>';
strName += ' <td width=\"15%\">'+strUnit+'</td>';
strName += ' <td width=\"10%\">'+strJumlah+'</td>';
strName += ' <td width=\"20%\">Rp '+addCommas(strHargaSatuan)+'</td>';
strName += ' <td width=\"20%\">Rp '+addCommas(strHargaTotal)+'</td>';
strName += ' </tr>';
}
I have written a web app that does this for a friend's business. What I do is create the element, append it to the actual DOM, then measure the height in pixels using parseInt(getComputedStyle(item_list[i]).height)
As soon as the height exceeds the available space I remove the last item and start appending to the 2nd page.

Populate HTML table with javascript [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Hi all and thanks in advance. I need to learn how to fill a table ussing javascript using the structure below.
var contacts = [
{name:"name1", number:"number1", address:"address1", notes:"note1"},
{name:"name2", number:"number2", address:"address2", notes:"note2"},
{name:"name3", number:"number3", address:"address3", notes:"note3"},
{name:"name4", number:"number4", address:"address4", notes:"note4"},
{name:"name5", number:"number5", address:"address5", notes:"note5"}
]
HTML
<table id="tableID">
<tbody>
</tbody>
</table>
Javascript
var wrap= function(value) {
return "<td>" + value + "</td>";
};
$("#tableID tbody").append("<tr><th>Name</th><th>Number</th><th>Address</th><th>Notes</th></tr>");
for (var i = 0; i < contacts.length; i += 1) {
$("#tableID tbody").append("<tr>"+ wrap(contacts[i].name)+ wrap(contacts[i].number)+ wrap(contacts[i].address)+ wrap(contacts[i].notes)+ "</tr>")
}
var table = $('<table>');
var c, i, l, tr, td;
for (i = 0, l = contacts.length; i < l; i += 1) {
c = contacts[i];
tr = $('<tr>');
tr
.append($('<td>' + c.name + '</td>'))
.append($('<td>' + c.number + '</td>'));
table.append(tr);
}
Try this
HTML
<table>
</table>
Jquery
var output='';
for(var i in contacts)
{
output+='<tr><td>'+contacts[i].name+'</td><td>'+contacts[i].number+'</td><td>'+contacts[i].address+'</td><td>'+contacts[i].notes+'</td></tr>';
}
$('table').empty().append(output)
DEMO

How to find empty tr in table using Javascript [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I want to find Empty tr in table, is there any way to find it?
after finding empty row I want to insert some data in it.
Supposing you have this HTML :
<table id=tbl>
<tr><td>A</td><td>B</td></tr>
<tr><td>A</td><td>B</td></tr>
<tr><td></td><td></td></tr> <!-- this line is empty -->
<tr><td>A</td><td>B</td></tr>
</table>
Then you can fill the empty line like this :
var rows = document.getElementById('tbl').rows;
for (var i=0; i<rows.length; i++) {
var txt = rows[i].textContent || rows[i].innerText;
if (txt.trim()==="") rows[i].innerHTML="<td>Something</td>";
}
Demonstration
This uses :
the rows property of the table
textContent (or innerText for IE) to get the content without the tags
As this also use the trim function which isn't available in IE8, you might want to add this shim :
if(!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+|\s+$/g,'');
};
}
There might be better ways, this is what occurred to me.
$('tr').each(function() {
if($(this).find('td').length == 0) {
// empty tr
// id of tr is available through this.id
}
});
Maybe something like this $('table tr:empty').html('....')
var tables = document.getElementsByTagName('table');
var table = tables[0];
var trs = table.getElementsByTagName('tr');
for (var i = 0; i < trs.length; i++) {
if (trs[i].innerHTML === '') {
console.log('EMPTY', trs[i]);
} else {
console.log('NOT EMPTY', trs[i]);
}
}
I think its not easy. You can see this link.
HTML:
<table id="table" style="border: 1px solid green;"><tbody>
<tr id="empty"></tr>
<tr id="withText"><font style="color: red;">text</font></tr>
<tr id="withEmptyTd"><td></td></tr>
<tr id="withTdWithText"><td>text</td></tr>
</tbody></table>
<div id="output"></div>
Javascript:
var output = document.getElementById('output');
var table = document.getElementById('table');
var trs = table.querySelectorAll('tr');
var tr, id, text, tds, j, td, tdText;
for (var i = 0; i < trs.length; i++) {
tr = trs[i];
id = tr.id;
output.innerHTML += "Getting tr[" + id + "]<br />";
text = tr.innerHTML;
output.innerHTML += "tr[" + id + "].innerHTML = \"" + text + "\" it's length = " + text.length + "<br />";
tds = tr.querySelectorAll('td');
output.innerHTML += "tr[" + id + "] have " + tds.length + " tds<br />";
for (j = 0; j < tds.length; j++) {
td = tds[j];
tdText = td.innerHTML;
output.innerHTML += "tr[" + id + "] -> td[" + j + "].innerHTML = \"" + tdText + "\" its length = " + tdText.length + "<br />";
}
}
And output will be:
Getting tr[empty]
tr[empty].innerHTML = "" it's length = 0
tr[empty] have 0 tds
Getting tr[withText]
tr[withText].innerHTML = "" it's length = 0
tr[withText] have 0 tds
Getting tr[withEmptyTd]
tr[withEmptyTd].innerHTML = "" it's length = 9
tr[withEmptyTd] have 1 tds
tr[withEmptyTd] -> td[0].innerHTML = "" its length = 0
Getting tr[withTdWithText]
tr[withTdWithText].innerHTML = "text" it's length = 13
tr[withTdWithText] have 1 tds
tr[withTdWithText] -> td[0].innerHTML = "text" its length = 4
Cause any tag or text in tr but not in td shows before the table.

Dynamic creation of large html table in javascript performance

I have an application which is used for data analysis and I'm having a few performance issues with the creation of the table. The data is extracted from documents and it is important that all data is presented on one page (pagination is not an option unfortunately).
Using jQuery, I make an ajax request to the server to retrieve the data. On completion of the request, I pass the data to an output function. The output function loops through the data array using a for loop and concatenating the rows to a variable. Once the looping is complete, the variable containing the table is then appended to an existing div on the page and then I go on to bind events to the table for working with the data.
With a small set of data (~1000-2000 rows) it works relatively good but some of the data sets contain upwards of 10,000 rows which causes Firefox to either crash and close or become unresponsive.
My question is, is there a better way to accomplish what I am doing?
Here's some code:
//This function gets called by the interface with an id to retrieve a document
function loadDocument(id){
$.ajax({
method: "get",
url: "ajax.php",
data: {action:'loadDocument',id: id},
dataType: 'json',
cache: true,
beforeSend: function(){
if($("#loading").dialog('isOpen') != true){
//Display the loading dialog
$("#loading").dialog({
modal: true
});
}//end if
},//end beforesend
success: function(result){
if(result.Error == undefined){
outputDocument(result, id);
}else{
<handle error code>
}//end if
if($('#loading').dialog('isOpen') == true){
//Close the loading dialog
$("#loading").dialog('close');
}//end if
}//end success
});//end ajax
};//end loadDocument();
//Output document to screen
function outputDocument(data, doc_id){
//Begin document output
var rows = '<table>';
rows += '<thead>';
rows += '<tr>';
rows += '<th>ID</th>';
rows += '<th>Status</th>';
rows += '<th>Name</th>';
rows += '<th>Actions</th>';
rows += '<th>Origin</th>';
rows += '</tr>';
rows += '</thead>';
rows += '<tbody>';
for(var i in data){
var recordId = data[i].id;
rows += '<tr id="' + recordId + '" class="' + data[i].status + '">';
rows += '<td width="1%" align="center">' + recordId + '</td>';
rows += '<td width="1%" align="center"><span class="status" rel="' + recordId + '"><strong>' + data[i].status + '</strong></span></td>';
rows += '<td width="70%"><span class="name">' + data[i].name + '</span></td>';
rows += '<td width="2%">';
rows += '<input type="button" class="failOne" rev="' + recordId + '" value="F">';
rows += '<input type="button" class="promoteOne" rev="' + recordId + '" value="P">';
rows += '</td>';
rows += '<td width="1%">' + data[i].origin + '</td>';
rows += '</tr>';
}//end for
rows += '</tbody>';
rows += '</table>';
$('#documentRows').html(rows);
I was initially using a jQuery each loop but switched to the for loop which shaved off some ms.
I thought of using something like google gears to try offloading some of the processing (if that's possible in this scenario).
Any thoughts?
joinHi,
The rendering is a problem, but there is also a problem with concatenating so many strings inside the loop, especially once the string gets very large. It would probably be best to put the strings into individual elements of an array then finally use "join" to create the huge string in one fell swoop. e.g.
var r = new Array();
var j = -1, recordId;
r[++j] = '<table><thead><tr><th>ID</th><th>Status</th><th>Name</th><th>Actions</th><th>Origin</th></tr></thead><tbody>';
for (var i in data){
var d = data[i];
recordId = d.id;
r[++j] = '<tr id="';
r[++j] = recordId;
r[++j] = '" class="';
r[++j] = d.status;
r[++j] = '"><td width="1%" align="center">';
r[++j] = recordId;
r[++j] = '</td><td width="1%" align="center"><span class="status" rel="';
r[++j] = recordId;
r[++j] = '"><strong>';
r[++j] = d.status;
r[++j] = '</strong></span></td><td width="70%"><span class="name">';
r[++j] = d.name;
r[++j] = '</span></td><td width="2%"><input type="button" class="failOne" rev="';
r[++j] = recordId;
r[++j] = '" value="F"><input type="button" class="promoteOne" rev="';
r[++j] = recordId;
r[++j] = '" value="P"></td><td width="1%">';
r[++j] = d.origin;
r[++j] = '</td></tr>';
}
r[++j] = '</tbody></table>';
$('#documentRows').html(r.join(''));
Also, I would use the array indexing method shown here, rather than using "push" since, for all browsers except Google Chrome it is faster, according to this article.
Displaying that many rows is causing the browser's rendering engine to slow down, not the JavaScript engine. Unfortunately there's not a lot you can do about that.
The best solution is to just not display so many rows at the same time, either through pagination, or virtual scrolling.
The way you are building your string will cause massive amounts of garbage collection.
As the string gets longer and longer the javascript engine has to keep allocating larger buffers and discarding the old ones. Eventually it will not be able to allocate sufficient memory without recycling the remains of all the old strings.
This problem gets worse as the string grows longer.
Instead try adding new elements to the DOM one at a time using the jQuery manipulation API
Also consider only rendering what is visible and implement your own scrolling.
You can do couple of things to increase the performance:
your rows variable is getting bigger and bigger so, don't store the html in one variable. solution can be $.each() function and each function you append the element into DOM. But this is minor adjustment.
Html generating is good, but you can try DOM creating and appending. Like $('<tr></tr>').
And finally, this will solve your problem for sure : use multiple ajax call in the first ajax call collect how many data is available and fetch approximately 1,000 or may be more data. And use other calls to collect remaining data. If you want, you can use synchronous call or Asynchronous calls wisely.
But try to avoid storing the value. Your DOM size will be huge but it should work on moder browsers and forget about IE6.
#fuel37 : Example
function outputDocumentNew(data, doc_id) {
//Variable DOM's
var rowSample = $('<tr></tr>').addClass('row-class');
var colSample = $('<td></td>').addClass('col-class');
var spanSample = $('<span></span>').addClass('span-class');
var inputButtonSample = $('<input type="button"/>').addClass('input-class');
//DOM Container
var container = $('#documentRows');
container.empty().append('<table></table>');
//Static part
var head = '<thead>\
<tr>\
<th width="1%" align="center">ID</th>\
<th width="1%" align="center">Status</th>\
<th width="70%">Name</th>\
<th width="2%">Actions</th>\
<th width="1%">Origin</th>\
</tr>\
</thead>';
container.append(head);
var body = $('<tbody></tbody>');
container.append(body);
//Dynamic part
$.each(data, function (index, value) {
var _this = this;
//DOM Manupulation
var row = rowSample.clone();
//Actions
var inpFailOne = inputButtonSample.clone().val('F').attr('rev', _this.id).addClass('failOne').click(function (e) {
//do something when click the button.
});
var inpPromoteOne = inputButtonSample.clone().val('P').attr('rev', _this.id).addClass('promoteOne').click(function (e) {
//do something when click the button.
});
row
.append(colSample.clone().append(_this.id))
.append(colSample.clone().append(spanSample.colne().addClass('status').append(_this.status)))
.append(colSample.clone().append(spanSample.colne().addClass('name').append(_this.name)))
.append(colSample.clone().append(inpFailOne).append(inpPromoteOne))
.append(colSample.clone().append(_this.origin));
body.append(row);
});
}
in this process you need to create & maintain id's or classes for manipulation. You have the control to bind events and manipulate each elements there.
Answering to get formatting
What happens if you do
for(var i in data){
var record = data[i];
var recordId = record.id;
rows += '<tr id="' + recordId + '" class="' + record.status + '">';
rows += '<td width="1%" align="center">' + recordId + '</td>';
rows += '<td width="1%" align="center"><span class="status" rel="' + recordId + '"><strong>' + data[i].status + '</strong></span></td>';
rows += '<td width="70%"><span class="name">' + record.name + '</span></td>';
rows += '<td width="2%">';
rows += '<input type="button" class="failOne" rev="' + recordId + '" value="F">';
rows += '<input type="button" class="promoteOne" rev="' + recordId + '" value="P">';
rows += '</td>';
rows += '<td width="1%">' + record.origin + '</td>';
rows += '</tr>';
}//end for
Per others suggestions (I'm not reputable enough to comment yet, sorry!), you might try the TableSorter plugin to handle only displaying a usable amount of data at a time.
I don't know how it fares at very high numbers of rows, but their example data is 1000 rows or so.
This wouldn't help with JS performance but would keep the burden off the browser renderer.
Could try this...
Improve Loops
Improve String Concat
var tmpLst = [];
for (var i=0, il=data.length; i<il; i++) {
var record = data[i];
var recordId = record.id;
tmpLst.push('<tr id="');
tmpLst.push(recordId);
tmpLst.push('" class="');
tmpLst.push(record.status);
tmpLst.push('">');
tmpLst.push('<td width="1%" align="center">');
...ect...
}
rows += tmpLst.join('');
This might squeeze an extra bit of performance...
var lstReset = i * lstReset.length;
tmpLst[lstReset + 1]='<tr id="';
tmpLst[lstReset + 2]=recordId;
tmpLst[lstReset + 3]='" class="';

Categories

Resources