Jump to content
xisto Community
vizskywalker

Problems Dynamically Adding A Table With Dom

Recommended Posts

I'm writing a search function to search a MySQL database I have. The search uses AJAX with a php server to search the database and generate a result. The result is passed back as a DOM object to the javascript, which then parses the result into an xhtml table. I then add the table to my page. This works just fine under Firefox. However, under IE (version 7, so I assume others as well), the table doesn't display. I used the IE Developer Toolbar to look at the DOM, and the table has been successfully added to the DOM, but it isn't showing up. Interestingly, the property hasLayout is set to -1, which I assume means false even though MSDN claims that tables always have a hasLayout property of true. The javascript snippet is as follows:

/* Add the Headers */    // Create the Headers Row  var headers = document.createElement("tr");  headers.setAttribute("class", "Compendium");  // Create the Number Header  var number = document.createElement("td");  number.setAttribute("class", "Compendium");  //number.innerHTML = "Number";  number.innerHTML = "Number";  headers.appendChild(number);  // Create the Name Header  var name = document.createElement("td");  name.setAttribute("class", "Compendium");  name.innerHTML = "Name";  headers.appendChild(name);  // Create the Element Header  var element = document.createElement("td");  element.setAttribute("class", "Compendium");  element.innerHTML = "Element";  headers.appendChild(element);  // Create the Expansion Header  var expansion = document.createElement("td");  expansion.setAttribute("class", "Compendium");  element.innerHTML = "Expansion";  headers.appendChild(expansion);  // Create the Card Type Header  var cardtype = document.createElement("td");  cardtype.setAttribute("class", "Compendium");  cardtype.innerHTML = "Card Type";  headers.appendChild(cardtype);  // Create the Primary Type Header  var primarytype = document.createElement("td");  primarytype.setAttribute("class", "Compendium");  primarytype.innerHTML = "Type 1";  headers.appendChild(primarytype);  // Create the Secondary Type Header  var secondarytype = document.createElement("td");  secondarytype.setAttribute("class", "Compendium");  secondarytype.innerHTML = "Type 2";  headers.appendChild(secondarytype);  // Create the Cost Header  var cost = document.createElement("td");  cost.setAttribute("class", "Compendium");  cost.innerHTML = "Cost";  headers.appendChild(cost);  // Create the Cost Header  var actions = document.createElement("td");  actions.setAttribute("class", "Compendium");  actions.innerHTML = "Actions";  headers.appendChild(actions);  // Create the Attack Header  var attack = document.createElement("td");  attack.setAttribute("class", "Compendium");  attack.innerHTML = "Attack";  headers.appendChild(attack);  // Create the Defense Header  var defense = document.createElement("td");  defense.setAttribute("class", "Compendium");  defense.innerHTML = "Defense";  headers.appendChild(defense);  // Create the Move Header  var move = document.createElement("td");  move.setAttribute("class", "Compendium");  move.innerHTML = "Move";  headers.appendChild(move);  // Create the Game Text Header  var gametext = document.createElement("td");  gametext.setAttribute("class", "Compendium");  gametext.innerHTML = "Game Text";  headers.appendChild(gametext);  // Create the Story Text Header  var storytext = document.createElement("td");  storytext.setAttribute("class", "Compendium");  storytext.innerHTML = "Story Text";  headers.appendChild(storytext);  // Create the Rarity Header  var rarity = document.createElement("td");  rarity.setAttribute("class", "Compendium");  rarity.innerHTML = "Rarity";  headers.appendChild(rarity);  // Create the Artist Header  var artist = document.createElement("td");  artist.setAttribute("class", "Compendium");  artist.innerHTML = "Artist";  headers.appendChild(artist);    compendiumResults.appendChild(headers);      // Add Each Card to the Table  for (var index = 0; index < cards.length; ++index) {	// Create the Headers Row	var card = document.createElement("tr");	card.setAttribute("class", "Compendium");	// Create the Number Header	var number = document.createElement("td");	number.setAttribute("class", "Compendium");	if (cards[index].childNodes[0].firstChild) {	  number.innerHTML = cards[index].childNodes[0].firstChild.nodeValue;	}	card.appendChild(number);	// Create the Name Header	var name = document.createElement("td");	name.setAttribute("class", "Compendium");	if (cards[index].childNodes[1].firstChild) {	  name.innerHTML = cards[index].childNodes[1].firstChild.nodeValue;	}	card.appendChild(name);	// Create the Element Header	var element = document.createElement("td");	element.setAttribute("class", "Compendium");	if (cards[index].childNodes[2].firstChild) {	  element.innerHTML = cards[index].childNodes[2].firstChild.nodeValue;	}	card.appendChild(element);	// Create the Expansion Header	var expansion = document.createElement("td");	expansion.setAttribute("class", "Compendium");	if (cards[index].childNodes[3].firstChild) {	  expansion.innerHTML = cards[index].childNodes[3].firstChild.nodeValue;	}	card.appendChild(expansion);	// Create the Card Type Header	var cardtype = document.createElement("td");	cardtype.setAttribute("class", "Compendium");	if (cards[index].childNodes[4].firstChild) {	  cardtype.innerHTML = cards[index].childNodes[4].firstChild.nodeValue;	}	card.appendChild(cardtype);	// Create the Primary Type Header	var primarytype = document.createElement("td");	primarytype.setAttribute("class", "Compendium");	if (cards[index].childNodes[5].firstChild) {	  primarytype.innerHTML = cards[index].childNodes[5].firstChild.nodeValue;	}	card.appendChild(primarytype);	// Create the Secondary Type Header	var secondarytype = document.createElement("td");	secondarytype.setAttribute("class", "Compendium");	if (cards[index].childNodes[6].firstChild) {	  secondarytype.innerHTML = cards[index].childNodes[6].firstChild.nodeValue;	}	card.appendChild(secondarytype);	// Create the Cost Header	var cost = document.createElement("td");	cost.setAttribute("class", "Compendium");	if (cards[index].childNodes[7].firstChild) {	  cost.innerHTML = cards[index].childNodes[7].firstChild.nodeValue;	}	card.appendChild(cost);	// Create the Cost Header	var actions = document.createElement("td");	actions.setAttribute("class", "Compendium");	if (cards[index].childNodes[8].firstChild) {	  actions.innerHTML = cards[index].childNodes[8].firstChild.nodeValue;	}	card.appendChild(actions);	// Create the Attack Header	var attack = document.createElement("td");	attack.setAttribute("class", "Compendium");	if (cards[index].childNodes[9].firstChild) {	  attack.innerHTML = cards[index].childNodes[9].firstChild.nodeValue;	}	card.appendChild(attack);	// Create the Defense Header	var defense = document.createElement("td");	defense.setAttribute("class", "Compendium");	if (cards[index].childNodes[10].firstChild) {	  defense.innerHTML = cards[index].childNodes[10].firstChild.nodeValue;	}	card.appendChild(defense);	// Create the Move Header	var move = document.createElement("td");	move.setAttribute("class", "Compendium");	if (cards[index].childNodes[11].firstChild) {	  move.innerHTML = cards[index].childNodes[11].firstChild.nodeValue;	}	card.appendChild(move);	// Create the Game Text Header	var gametext = document.createElement("td");	gametext.setAttribute("class", "Compendium");	if (cards[index].childNodes[12].firstChild) {	  gametext.innerHTML = cards[index].childNodes[12].firstChild.nodeValue;	}	card.appendChild(gametext);	// Create the Story Text Header	var storytext = document.createElement("td");	storytext.setAttribute("class", "Compendium");	if (cards[index].childNodes[13].firstChild) {	  storytext.innerHTML = cards[index].childNodes[13].firstChild.nodeValue;	}	card.appendChild(storytext);	// Create the Rarity Header	var rarity = document.createElement("td");	rarity.setAttribute("class", "Compendium");	if (cards[index].childNodes[14].firstChild) {	  rarity.innerHTML = cards[index].childNodes[14].firstChild.nodeValue;	}	card.appendChild(rarity);	// Create the Artist Header	var artist = document.createElement("td");	artist.setAttribute("class", "Compendium");	if (cards[index].childNodes[15].firstChild) {	  artist.innerHTML = cards[index].childNodes[15].firstChild.nodeValue;	}	card.appendChild(artist);		compendiumResults.appendChild(card);  }
Any ideas would be appreciated.

Thanks,
~Viz

Share this post


Link to post
Share on other sites

You haven't mentioned what compendiumResults is. I am assuming it is the table. The table element contains a tbody element which in turn contains the tr elements. So, set the compendiumResults to the table's tbody.

 

compendiumResults = documents.getElementById('myTableName').getElementsByTagName('tbody')[0];

Firefox seems to allow addition of trs to the table element itself. Whereas, Internet Explorer is a bit strict on this.

 

Hope this helps.

 

Max.

Share this post


Link to post
Share on other sites

Thanks, I actually figured that out before I read your post. After looking at the DOM specification, it seems that in theory, tbody is not required. Interesting tidbit, though, when running the code under Safari 2, or the original Safari 3 beta for windows, the elements are added, but do not appear to be in a table, and no class is associated with them. Any ideas as to why?Edit: I think I've determined the problem, but not the cause of the problem. No matter what tag type I pass to document.createElement(), I seem to be getting an Element as opposed to an HTML<Type>Element. This would cause display issues, but I'm not sure why this is happening.Edit: So, after further experimentation, it seems I can successfully change the class using the className properly, but only if I pick an internal style. It doesn't seem to work for external styles unless the object was always present.~Viz

Share this post


Link to post
Share on other sites

You are correct. Because its XHTML, any type of tag can be created and added by using the DOM functions - Document.CreateElement and <Element>.AppendChild. But, only those that are in the HTML specification will effect the Document. I don't think Internet Explorer allows creation of arbitrary tags, although Firefox certainly does.

The following code for example, works properly with Opera, Firefox and Safari. But, Internet Explorer tells a different story.
 



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" xmlns="www.w3.org/1999/xhtml/" <body> <table id="myTable" border="1"> </table> </body> <script type="text/javascript"> window.onload = function() { var tab = document.getElementById('myTable'); var tr = document.createElement('tr'); var td = document.createElement('td'); td.innerHTML = "This is a column"; tr.appendChild(td); tab.appendChild(tr); alert(tab.innerHTML); } </script></html>

This will clear up the working on these browsers. Opera, Firefox and Safari will show a message box with the text: <tr><td>This is a column</td></tr>. Whereas, Internet Explorer displays <tbody></tbody><tr><td>This is a column</td></tr>. As you can see, IE adds the tbody element to the table as soon as it is created. So, our TR got appended at the end.

So, what if we added a tbody manually? Lets check it out.
 



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd xmlns="www.w3.org/1999/xhtml/ <body> <table id="myTable" border="1"> </table> </body> <script type="text/javascript"> window.onload = function() { var tab = document.getElementById('myTable'); var tbody = document.createElement('tbody'); var tr = document.createElement('tr'); var td = document.createElement('td'); td.innerHTML = "This is a column"; tr.appendChild(td); tbody.appendChild(tr); tab.appendChild(tbody); alert(tab.innerHTML); } </script></html>

Now, the code displayed by IE contains two tbody tags. Yet, it works. The other browsers display the expected code <tbody><tr><td>This is a column</td></tr></tbody>.

The question is, should the tbody be automatically added to a table? I don't think so. Columns are supposed to be added to Rows and Rows are meant to be added to the table. IE should follow the standards set by the others and save the developers from all the IE specific coding.



Share this post


Link to post
Share on other sites

I'd agree, except tbody isn't only a thing required by IE, it's also a well established part of the DOM for XHTML 1.1, so I see no problem with it. The sample code works fine in Safari, which is my current problem place. I even modified it so that the table was generated dynamically when the body loaded, and that worked. But I can't figure out what's wrong with my code that I showed you up above to prevent the table from appearing even as a table in Safari. All of the data just gets shown as seeming stream of text, with no proper style.Edit: I just tried another experiment, and found the cause of the issue. Since my pages are XHTML 1.1, they should be served as application/xhtml+xml, and I serve them as such to any browser that accepts it. Safari is included on that list. When the page is served as applicaton/xhtml+xml, Safari fails on your code. However, when the page is served as text/html, the code works. So the problem is somehow related to how Safari handles application/xhtml+xml. Since this code works in the new versions of Safari, is this likely to have been an issue with the old version of Safari? Or does the new version do nice error checking to display if I make a mistake and my code is wrong?~Viz

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.