By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,963 Members | 1,825 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,963 IT Pros & Developers. It's quick & easy.

Dynamic Table works in IE but not Firefox

P: 2
I wrote this pretty slick DHTML table that lets you add/remove rows and show/hide columns on the fly. It works perfectly in IE7, but it doesn't behave in Firefox 2.0.0.4. You can see it in action here:

http://www.phreelancer.com/dyn_table/

If you start to add/remove rows and then show/hide columns a few times in FF, you'll see that some table cells are bundled together or that some hidden cells don't get collapsed (but are still empty). It's driving me insane. I've tried several approaches. Any advice would be great. Here's the code:

Expand|Select|Wrap|Line Numbers
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  2. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
  3. <head>
  4. <title>Todomo Admin Section</title>
  5. <link rel="stylesheet" type="text/css" href="http://www.phreelancer.com/dyn_table/dyn_table.css"/>
  6. <script type="text/javascript">
  7. // these array values correspond to the current status of their checkboxes
  8. var languages = new Array();
  9. languages["English"] = true;
  10. languages["Spanish"] = true;
  11. languages["Portuguese"] = false;
  12.  
  13. document.getElementsByClassName = function(class_name) {
  14.    var docList = this.all || this.getElementsByTagName("*");
  15.    var matchArray = new Array();
  16.  
  17.    // create a regular expression object for class
  18.    var re1 = new RegExp("\\b"+class_name+"\\b");
  19.  
  20.    // create regular expression to handle dashes in class name
  21.    var re2 = new RegExp("[\S]"+class_name+"|"+class_name+"[\S]");
  22.  
  23.    for (var i = 0; i < docList.length; i++) {
  24.       if (re1.test(docList[i].className) && !re2.test(docList[i].className) ) {
  25.          matchArray[matchArray.length] = docList[i];
  26.       }
  27.    }
  28.    return matchArray;
  29. }
  30.  
  31. // add/remove table column for specified language
  32. function dyn_table_change_language(language) {
  33.    var cb = document.getElementById("cb"+language);
  34.  
  35.    languages[language] = cb.checked;
  36.  
  37.    // make sure at least one checkbox is checked
  38.    if (!cb.checked) {
  39.       var num_checked = 0;
  40.       for (var key in languages) {
  41.          if (languages[key]) {
  42.             num_checked++;
  43.          }
  44.       }
  45.  
  46.       if (num_checked == 0) {
  47.          languages[language] = true;
  48.          cb.checked = true;
  49.          alert("You must keep at least one language enabled.");
  50.          return;
  51.       }
  52.    }
  53.  
  54.    var cells = document.getElementsByClassName(language);
  55.    for (var i=0; i<cells.length; i++) {
  56.       cells[i].style.display = cb.checked ? "block" : "none";
  57.    }
  58. }
  59.  
  60. // hide all table cells that are part of a disabled language/column
  61. function dyn_table_hide_languages() {
  62.    for (var language in languages) {
  63.       if (!languages[language]) {
  64.          var cells = document.getElementsByClassName(language);
  65.          for (var i=0; i<cells.length; i++) {
  66.             cells[i].style.display = "none";
  67.          }
  68.       }
  69.    }
  70. }
  71.  
  72. // add a new table row
  73. function dyn_table_add_category() {
  74.    var tbody = document.getElementById("dyn_table_categories");
  75.  
  76.    // count up all the existing categories on the screen
  77.    var category_id = 1;
  78.    while (true) {
  79.       category_id++;
  80.       var row = document.getElementById("category"+category_id);
  81.       if (!row) {
  82.          break;
  83.       }
  84.    }
  85.  
  86.    var tr = document.createElement("tr");
  87.    tr.setAttribute("id", "category"+category_id);
  88.  
  89.    var td_label = document.createElement("td");
  90.    td_label.appendChild(document.createTextNode("Category "+category_id+" Name:"));
  91.    td_label.setAttribute("class", "left");
  92.    td_label.setAttribute("className", "left");
  93.  
  94.    var td_English = document.createElement("td");
  95.    td_English.setAttribute("class", "English");
  96.    td_English.setAttribute("className", "English");
  97.  
  98.    var td_Spanish = document.createElement("td");
  99.    td_Spanish.setAttribute("class", "Spanish");
  100.    td_Spanish.setAttribute("className", "Spanish");
  101.  
  102.    var td_Portuguese = document.createElement("td");
  103.    td_Portuguese.setAttribute("class", "Portuguese");
  104.    td_Portuguese.setAttribute("className", "Portuguese");
  105.  
  106.    var td_del_link = document.createElement("td");
  107.    var a_del_link = document.createElement("a");
  108.    a_del_link.setAttribute("id", "del_category"+category_id);
  109.    a_del_link.setAttribute("href", "javascript:dyn_table_del_category("+category_id+")");
  110.    a_del_link.appendChild(document.createTextNode("Delete Category "+category_id));
  111.    td_del_link.appendChild(a_del_link);
  112.  
  113.    var input_English = document.createElement("input");
  114.    input_English.setAttribute("type", "text");
  115.    input_English.setAttribute("name", "English"+category_id);
  116.    input_English.setAttribute("id", "English"+category_id);
  117.  
  118.    var input_Spanish = document.createElement("input");
  119.    input_Spanish.setAttribute("type", "text");
  120.    input_Spanish.setAttribute("name", "Spanish"+category_id);
  121.    input_Spanish.setAttribute("id", "Spanish"+category_id);
  122.  
  123.    var input_Portuguese = document.createElement("input");
  124.    input_Portuguese.setAttribute("type", "text");
  125.    input_Portuguese.setAttribute("name", "Portuguese"+category_id);
  126.    input_Portuguese.setAttribute("id", "Portuguese"+category_id);
  127.  
  128.    td_English.appendChild(input_English);
  129.    td_Spanish.appendChild(input_Spanish);
  130.    td_Portuguese.appendChild(input_Portuguese);
  131.  
  132.    tr.appendChild(td_label);
  133.    tr.appendChild(td_English);
  134.    tr.appendChild(td_Spanish);
  135.    tr.appendChild(td_Portuguese);
  136.    tr.appendChild(td_del_link);
  137.  
  138.    tbody.appendChild(tr);
  139.  
  140.    dyn_table_hide_languages();
  141. }
  142.  
  143. // remove specified category/row
  144. function dyn_table_del_category(category_id) {
  145.    var tr = document.getElementById("category"+category_id);
  146.    if (!tr) {
  147.       return;
  148.    }
  149.    tr.parentNode.removeChild(tr);
  150.  
  151.    // must decrement category_id value of all subsequent rows
  152.    while (true) {
  153.       category_id++;
  154.       var new_category_id = category_id - 1;
  155.       tr = document.getElementById("category"+category_id);
  156.       if (!tr) {
  157.          break;
  158.       }
  159.       var children = tr.childNodes;
  160.       tr.setAttribute("id", "category"+new_category_id);
  161.  
  162.       // I tried avoiding 'innerHTML', but that didn't help
  163.  
  164.       //children[0].innerHTML = "";
  165.       children[0].removeChild(children[0].childNodes[0]);
  166.       children[0].appendChild(document.createTextNode("Category "+new_category_id+" Name:"));
  167.       children[1].childNodes[0].setAttribute("name", "English"+new_category_id);
  168.       children[1].childNodes[0].setAttribute("id", "English"+new_category_id);
  169.       children[2].childNodes[0].setAttribute("name", "Spanish"+new_category_id);
  170.       children[2].childNodes[0].setAttribute("id", "Spanish"+new_category_id);
  171.       children[3].childNodes[0].setAttribute("name", "Portuguese"+new_category_id);
  172.       children[3].childNodes[0].setAttribute("id", "Portuguese"+new_category_id);
  173.       children[4].childNodes[0].setAttribute("id", "del_category"+new_category_id);
  174.       children[4].childNodes[0].setAttribute("href", "javascript:dyn_table_del_category("+new_category_id+")");
  175.  
  176.       var a_del_link = document.createElement("a");
  177.       a_del_link.setAttribute("id", "del_category"+new_category_id);
  178.       a_del_link.setAttribute("href", "javascript:dyn_table_del_category("+new_category_id+")");
  179.       a_del_link.appendChild(document.createTextNode("Delete Category "+new_category_id));
  180.  
  181.       //children[4].childNodes[0].innerHTML = "";
  182.       children[4].removeChild(children[4].childNodes[0]);
  183.       children[4].appendChild(a_del_link);
  184.    }
  185. }
  186. </script>
  187. </head>
  188. <body>
  189. <form method="post">
  190. <div id="dyn_table" class="channel_fields">
  191.    <div class="box dark">
  192.       <div class="left">Languages:</div>
  193.       <div class="right">
  194.          <input type="checkbox" name="dyn_table[languages][]" id="cbEnglish" value="English" checked="checked" onclick="dyn_table_change_language('English')"/>English &nbsp;
  195.          <input type="checkbox" name="dyn_table[languages][]" id="cbSpanish" value="Spanish" checked="checked" onclick="dyn_table_change_language('Spanish')"/>Spanish &nbsp;
  196.          <input type="checkbox" name="dyn_table[languages][]" id="cbPortuguese" value="Portuguese" onclick="dyn_table_change_language('Portuguese')"/>Portuguese
  197.       </div>
  198.       <br clear="both"/><br/>
  199.    </div>
  200.    <div class="box dark">
  201.       <table border="0" cellspacing="0">
  202.       <!-- IE7 requires the tbody tag when appending/removing children with JS -->
  203.       <tbody id="dyn_table_categories">
  204.       <tr>
  205.          <td class="left">&nbsp;</td>
  206.          <td class="English">English</td>
  207.          <td class="Spanish">Spanish</td>
  208.          <td class="Portuguese" style="display:none">Portuguese</td>
  209.          <td>&nbsp;</td>
  210.       </tr>
  211.       <tr id="category1">
  212.          <td class="left">Category 1 Name:</td>
  213.          <td class="English"><input type="text" name="English1" id="English1"/></td>
  214.          <td class="Spanish"><input type="text" name="Spanish1" id="Spanish1"/></td>
  215.          <td class="Portuguese" style="display:none"><input type="text" name="Portuguese1" id="Portuguese1"/></td>
  216.          <td>&nbsp;</td>
  217.       </tr>
  218.       </tbody>
  219.       </table>
  220.       <div class="left"><a href="javascript:dyn_table_add_category()">Add New Category</a></div>
  221.    </div>
  222. </div>
  223. </form>
  224. </body>
  225. </html>
  226.  
Jun 24 '07 #1
Share this Question
Share on Google+
1 Reply


P: 2
Ah, I found the solution. All I had to do was use an empty string value for the 'display' CSS property instead of 'block' because display:block isn't valid CSS for tables and table elements:

Expand|Select|Wrap|Line Numbers
  1. cells[i].style.display = cb.checked ? "" : "none";
rather than

Expand|Select|Wrap|Line Numbers
  1. cells[i].style.display = cb.checked ? "block" : "none";
Jun 24 '07 #2

Post your reply

Sign in to post your reply or Sign up for a free account.