dynamic ajax populated table not working in IE 8 - javascript

Hi all I've an IE8 issure, here's the code:
Html code:
<table id=\"myTable\" border="1">
javascript function:
function loadTableContent() {
$.ajax({
type : 'GET',
url : '/sohara/viewResults.do',
contentType : 'application/json; charset=utf-8',
success : function(response) {
result = response;
var html_Table = '';
html_Table += '<tr><th bgcolor="silver">Type</th>
<th bgcolor="silver">Quantity A</th>
<th bgcolor="silver">Quantity B</th></tr>';
for ( var i = 0; i < result.length; i++) {
html_Table += '<tr>';
html_Table += '<td>'+result[i].description+'</td>';
html_Table += '<td>'+result[i].quantityA+'</td>';
html_Table += '<td>'+result[i].quantityB+'</td>';
html_Table += '</tr>';
}
html_Table += '</table>';
$("#myTable").append(html_Table);
},
error : function(response) {
alert("Error");
}
});
}
Always is perfect in Firefox, Chrome and Opera but in IE8 nothing is displayed in the table. How can I manage that?

I not 100% what is going on but some possibilities:
Your <table> element is incomplete, as it doesn't have an ending tag. I originally assumed that this was just because you were being concise and didn't include it in your example, but then I noticed you included </table> inside your JavaScript. You need to terminate the tag normally in HTML, like so:
<table id=\"myTable\" border="1"></table>
And then work with it in JavaScript (and remove the ending tag in you're appending from JS)
Furthermore, I think the HTML spec says that that table header rows (such as yours with the TH tag) should be wrapped in a <thead> element (e.g. <table><thead><tr><th>Header</th></tr></thead></table>, while body elements are then wrapped in a <tbody> element. Most browsers seem pretty good about parsing tables even without these, but I point it out as a possible source of your problem.
One last potential problem is that IE all the way up to IE9 cannot set innerHTML on tables. See IE9 createElement and setting innerHTML dropping tags on a set operation? and can't innerHTML on tbody in IE for more information. I don't know how JQuery updates table data. I think if they relied on this method we would see more questions here on SO about it, but who knows.

Working solution:
According to Matt first I declare the table this way:
<table id=\"myTable\" border="1"></table> // FULL working method
In fact IE8 automatically closes the html tag this way if I don't close it, causing several issues in appending new html code:
<table id=\"myTable\" border="1"></> // NOT working method
Then instead of using:
$("#myTable).append(html_Table);
I use:
$("#myTable).html(html_Table);
Obviously I have to remove from ajax:
html_Table += '</table>';
Full Working :)

Related

DataTables Initialized/Executed too Early on Dynamic HTML Data

I have a function that creates an HTML table based on an array. Once the HTML table is finished being created, I then want to call jQuery DataTables to render the table.
However, this doesn't work. I get the "No data Available in Table" line whenever I do this, and my table data appears. But, as soon as I click a filter for it, all the <td> HTML data disappears. I've checked my table's HTML, it's correctly defined, has all the necessary tags, and matches with what my function creates.
From what I've read, the issue lies with the DataTables function firing too early. I confirmed this by using the setTimeout function- it creates the table perfectly and with no errors. However, this solution isn't scalable and would cause the same problem once the data expands.
I've tried fixing this by using a callback (DataTables still fires too early, I used renderTable(function(){$('#divtable').DataTable();}), and a promise (it still fires too early, I tried to use function.done()...). How can I call the render function as only when the HTML table div is finished updating?
Here is my (shortened) code:
HTML Table render:
function renderTable() {
for (var i = 0; i < array.length; i++) {
var tableRow = '';
tableRow += '<tr><td class="ID">' + array[i].id + '</td><td>' + array[i].date + '</td><td>' + array[i].total + '</td><td><input type=button class="editValues" value="Edit Values" /></td></tr>';
$("#divtable > tbody").append(tableRow);
}
jQuery:
$(document).ready(function() {
renderTable();
$('#divtable').DataTable();
}

Why doesn't this Javascript code execute sequentially?

Using jQuery I'm doing a call to my server which returns some json. I then have a callback defined using .done to create a callback, which doesn't seem to behave sequentially.
I've got a div in my html (<div id="properties"></div>), and I try to fill that div with a table of results:
request.done(function(data){
if (data['result'].length == 0) {
$("#properties").html("<h3>No results were found..</h3>");
} else {
$("#properties").html("<table><thead><tr><th>Status</th><th>Title</th></tr></thead><tbody>");
data['result'].forEach(function(prop){
$("#properties").append("<tr>");
$("#properties").append("<td>prop.status</td>");
$("#properties").append("<td>prop.title</td></tr>");
});
$("#properties").append("</tbody></table>");
}
});
The result I get is this:
<div id="properties">
<table class="table table-hover"><thead><tr><th>Status</th><th>Title</th></tr></thead><tbody></tbody></table>
<tr></tr>
<td>prop.status</td>
<td>prop.title</td>
</div>
I know that .done is only called once the ajax call returns something, but withint that call, it should behave sequentially right? There are 2 things I really really don't understand here:
Why do the table row and data get written after the </table> tag?
And why on earth does the <tr></tr> gets written before the <td> tags, even though the last </tr> is appended together with the last <td> in the lastappend()` in the foreach loop?
So I also tried appending the whole table row in one go:
$("#properties").append("<tr><td>prop.status</td><td>prop.title</td></tr>");
This works a bit better, but still only produces this:
<div id="properties">
<table class="table table-hover"><thead><tr><th>Status</th><th>Title</th></tr></thead><tbody></tbody></table>
<tr><td>prop.status</td><td>prop.title</td></tr>
</div>
Javascript has puzzled me before, but this really blows my mind. Any tips are welcome!
What you are seeing here are tags closing out on you, because those elements are getting created in whole on append/html. In order to get the behavior you're expecting build in a string, say something more like this:
request.done(function(data){
if (data['result'].length == 0) {
$("#properties").html("<h3>No results were found..</h3>");
} else {
var propertiesTableHTML = "<table><thead><tr><th>Status</th><th>Title</th></tr></thead><tbody>";
data['result'].forEach(function(prop){
propertiesTableHTML += "<tr>";
propertiesTableHTML += "<td>" + prop.status + "</td>";
propertiesTableHTML += "<td>" + prop.title + "</td>";
propertiesTableHTML += "</tr>";
});
propertiesTableHTML += "</tbody></table>";
$("#properties").html(propertiesTableHTML);
}
});
You are expecting .html() and .append() to work like document.write() but they don't. When used with HTML, they expect proper HTML. Broken HTML (for example missing end tags) is corrected which leads to the unexpected behavior. This part of your code for example:
$("#properties")
.html("<table><thead><tr><th>Status</th><th>Title</th></tr></thead><tbody>");
Produces the following result:
<table>
<thead>
<tr>
<th>Status</th>
<th>Title</th>
</tr>
</thead>
<tbody>
</tbody><!-- tag closed automatically -->
</table><!-- tag closed automatically -->
Along the same lines, this code:
$("#properties").append("<tr>");
$("#properties").append("<td>prop.status</td>");
$("#properties").append("<td>prop.title</td></tr>");
Produces the following result:
...
</table>
<tr></tr><!-- tag closed automatically -->
<td>prop.status</td>
<td>prop.title</td><!-- </tr> ignored -->
One possible solution is to revise your code like this:
$("#properties").html("<table><thead><tr><th>Status</th><th>Title</th></tr></thead><tbody></tbody></table>");
data['result'].forEach(function(prop){
var $tr = $("<tr></tr>").appendTo("#properties > table > tbody");
$("<td></td>").text(prop.status).appendTo($tr);
$("<td></td>").text(prop.title).appendTo($tr);
});
You can't add tags to the DOM, you can only add elements. When you try to add a <table> tag, it will add a complete table element. When you try to add the ending tag, it will be ignored (or possibly cause an error, depending on the browser) because it's not code that can be parsed into an element.
Rewrite the code to add elements instead of tags:
$("#properties").html("<table><thead><tr><th>Status</th><th>Title</th></tr></thead><tbody></tbody></table>");
var tbody = $("#propertis tbody");
data['result'].forEach(function(prop){
var row = $("<tr>");
row.append($("<td>").text(prop.status));
row.append($("<td>").text(prop.title));
tbody.append(row);
});
By creating table cells as elements and use the text method to set the content, you avoid the problem with any special characters that would need HTML encoding (e.g. <. >, &) to mess up the HTML code.

Is there a way to add raw html as new table rows with javascript?

Let's say I have the following table:
<table>
<tr id="1">...</tr>
<tr id="2">..</tr>
...
<tr id="last">..</tr>
</table>
I also have a third-party service from which I get some raw html, also table rows like this:
<tr id="additional-1">...</tr>
<tr id="additional2">...</tr>
Is there a relatively simple javascript way to insert those new rows after the tr with the id "last"?
I'm asking for simple built-in ways to avoid having to do a lot of parsing, replacing and stuff.
I prefer YUI 3 to jQuery solution.
Wrap the string in <table><tbody>..rows here...</tbody></table>. Then, create a dummy element, eg <div>, and set the innerHTML property to the previously constructed string. Finally, loop through all rows, and move the rows to the table using insertBefore(newelem, reference).
This method also works in IE, where setting the innerHTML property on a cell triggers an error.
var raw_html, prev_element, last_element_parent, rows, i;
raw_html = '<tr>....etc....</tr>';
prev_element = document.getElementById('last_element');
last_element_parent = prev_element.parentNode;
dummy = document.createElement('div');
dummy.innerHTML = '<table><tbody>' + raw_html + '</tbody></table>';
rows = dummy.firstChild.rows;
for (i=rows.length-1; i>=0; i--) {
last_element_parent.insertBefore(rows[i], prev_element.nextSibling);
}
What's about table.innerHTML += trs with var table stores the table-Object and var trs stores the additional rows.
Following code should work
$("tr #last").after("ur raw html");
its Jquery though.
In YUI3 you can do:
Y.one('#last').insert(rawHTML, 'after');

Table size is 0 in IE 7

I add content of table in Javascript like this
function (data) {
$("#forum-content").html(data);
}
data is a string with table content("<tr>...</tr><tr>...</tr>...") and I want to add that content to my table.
<table id="forum-content"></table>
In majority browsers it's look fine, but in IE 7 after adding content I don't see table anyway... I check that problem is that IE 7 is calculating size of my table 0(width=0,height=0) after adding content.
How can I solve this issue?
You should avoid writing a table body like that. In IE tables have been traditionally very fragile when using innerHTML (which jQuery's html() method basically is).
Try building the whole table instead:
function (data) {
$("#forum-content").html("<table>" + data + "</table>");
}
with
<div id="forum-content"></div>
In my test, I saw nothing wrong. Do you check whether the content was added to the table? Is there any error thrown.
<table id="forum-content">
</table>
<script>
$(function() {
function addContent(data) {
$("#forum-content").html(data);
}
addContent('<tr><th>Title</th><td>Content</td></tr>');
});
</script>
</body>

Update a tbody's html with javascript (no lib): possible?

I want to update the contents of a TBODY (not the entire TABLE, because there's much more semi-meta data (LOL) in that). I get >= 0 TR's from the server (XHR) and I want to plump those in the existing table. The fresh TR's must overwrite the existing TBODY contents.
I've made a very simple, static example on jsFiddle that works in Chrome and probably all the rest, except for IE (I only use Chrome and test in IE8).
In Chrome, the very first attempt works: plump the TR's in the TBODY. No problem!
In IE it doesn't... I've included a not working example of what I had in mind to get it working.
I'm sure this problem isn't new: how would I insert a string with TR's in an existing TBODY?
PS. jQuery doesn't have a problem with this!? It's used here on SO. jQuery does something to the HTML and then inserts it as HTML nodes..? Or something? I can't read that crazy lib. It happens in this file (look for "html: function(". That's where the magic starts.
Anybody have a function or idea for this to work without JS library?
Here is a good resource about the problems of innerHTML and IE.
The bottom line is that on tbody the innerHTML property is readonly.
Here is a solution presented in one of the comments:
var innerHTML = "<tr><td>Hello world!</td></tr>";
var div = document.createElement("DIV");
div.innerHTML = "<table>" + innerHTML + "</table>";
// Get the tr from the table in the div
var trElem = div.getElementsByTagName("TR")[0];
Regarding the jQuery part of the question:
//inside the html() function:
// If using innerHTML throws an exception, use the fallback method
} catch(e) {
this.empty().append( value );
}
//inside the empty() function (basically removes all child nodes of the td):
while ( elem.firstChild ) {
elem.removeChild( elem.firstChild );
}
//append calls domManip applying this to all table rows:
if ( this.nodeType === 1 ) {
this.appendChild( elem );
}
//domManip as far as I can tell creates a fragment if possible and calls the three lines above with this=each row in turn, elem=the tbody(created if missing)
Using plain JavaScript, you can set the innerHTML property of the relevant element. The text that you set can contain a mix of HTML and text. It will be parsed and added to the DOM.

Categories