JavaScript - Traversing the HTML DOM using childNodes causes errors in Non IE browsers

前端 未结 1 719
北海茫月
北海茫月 2021-01-14 20:40

I have the following table being rendered in my browser. It\'s generated from the server side.

相关标签:
1条回答
  • 2021-01-14 20:47

    It's because you're using childNodes and whitespaces in the DOM are considered to be text nodes by Firefox et. al but not IE

    See this answer for an explanation

    My suggestions

    1.Set up some wrapper functions that ignore any nodeType other than 1 (ELEMENT_NODE) to do DOM traversing. Something like

    function child(elem, index) {
        // if index is not supplied, default is 1 
        // you might be more comfortable making this 0-based
        // in which case change i initial assignment value to 0 too
        index = index || 1; 
        // get first child element node of elem
        elem = (elem.firstChild && elem.firstChild.nodeType != 1) ?
                   next(elem.firstChild) :
                   elem.firstChild; 
        // use the index to move to nth-child element node             
        for(var i=1; i < index;i++) {
            (function() {     
                return elem = next(elem);         
            })();        
        }
        return elem;
    }
    
    function next(elem) {
        do {
            elem = elem.nextSibling;
        } while (elem && elem.nodeType != 1);
    return elem;                
    }
    

    and use like so - Working Demo - (Code at the bottom of the answer for reference)

    <table id="myTable">
        <thead>
            ...
        </thead>
        <tbody>
            ...
        </tbody>
    </table>
    
    <script type="text/javascript">
        child(document.getElementById('myTable'), 2); // will get the tbody
    </script>
    

    2.Use getElementbyId(), getElementsByTagName() or getElementsByName() instead of relying on position in the DOM

    3.Use a JavaScript library that abstracts away browser differences (jQuery comes highly recommended)

    The Demo Code

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
    <script type="text/javascript">
        window.onload = function() {    
           document.getElementById('getCellContents').onclick = getCellContents;    
        }
    
        function child(elem, index) {
            index = index || 1; 
            elem = (elem.firstChild && elem.firstChild.nodeType != 1) ?
                       next(elem.firstChild) :
                       elem.firstChild;            
            for(var i=1; i < index;i++) {
                (function() {    
                    return elem = next(elem);         
                })();        
            }
            return elem;
        }
    
        function next(elem) {
            do {
                elem = elem.nextSibling;
            } while (elem && elem.nodeType != 1);
        return elem;                
        }
    
        function getCellContents() {
            var row = parseInt(document.getElementById('row').value, 10);
            var column = parseInt(document.getElementById('column').value, 10);
            var result;
            var color;
            var table = document.getElementById('table');
            var cells = table.getElementsByTagName('td');
            for (var i= 0; i < cells.length; i++) {
                (function() {
                    cells[i].bgColor = '#ffffff';
                })();
            }
    
            if (row && column) {
                var tbody = child(table , 2);
                var selectedRow = (row <= tbody.getElementsByTagName("tr").length)? child(tbody, row): null;
                var selectedCell = (selectedRow && column <= selectedRow.getElementsByTagName("td").length)? child(selectedRow, column): null;  
    
                if (selectedRow && selectedCell) {
                    selectedCell.bgColor = '#00ff00';
                    result = selectedCell.innerHTML;
                    color = '#b7b7b7';
                }
                else {
                    result = 'Cell does not exist';
                    color = '#ff0000';
                }                                           
            }
            else {
                result = 'You must provide numeric arguments for Row and Column Number';
                color = '#ff0000';
            }       
            var results = document.getElementById('results');
            results.innerHTML = result;
            results.style.color = color;
        }
    
    
    </script>
    <title>DOM Traversal</title>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <style type="text/css">
    body {
        font-family: Verdana, Helvetica, Arial;
        font-size: 0.8em;
    }
    h2 {
        text-align:center;
    }
    table { 
        border: 1px solid #000;
        border-collapse: collapse;
    }   
    th, td { 
        border: 1px solid #000; 
        padding: 2px; 
    }
    fieldset {
        border: 0;
    }
    label {
        display: block;
        width: 120px;
        text-align: right;
        float: left;
        padding-right: 10px;
        margin: 5px 0;
    }
    input {
        margin: 5px 0;
    }
    
    input.text {
        padding: 0 0 0 3px;
        width: 172px;
    }
    
    input.button {
        margin: 15px 0 0 130px;
    }
    span {
        font-weight: bold;
        color: #b7b7b7;
    }
    </style>
    </head>
    <body>
    
    <h2>Example to demonstrate use of JavaScript DOM traversing wrapper functions</h2>
    <div style="margin: 0 auto; width: 600px;">
    <fieldset>
        <label for="row">Row Number:</label><input id="row" class="text" type="text" /><br/>
        <label for="column">Column Number:</label><input id="column" class="text" type="text" /><br/>
        <input id="getCellContents" type="button" class="button" value="Get Cell Contents" />
    </fieldset> 
    
    <p>Results: <span id="results"></span></p>
    
      <table id="table">
      <thead>
        <tr>
                <th>Column 1</th>
                <th>Column 2</th>   
            <th>Column 3</th>
            <th>Column 4</th>
            <th>Column 5</th>   
        </tr>   
      </thead>
      <tbody>
          <tr>
            <td>Banana</td>
            <td>Apple</td>
            <td>Orange</td>
            <td>Pineapple</td>
            <td>Cranberry</td>
          </tr>
          <tr>
            <td>Monkey</td>
            <td>Giraffe</td>
            <td>Elephant</td>
            <td>Tiger</td>
            <td>Snake</td>
          </tr>
          <tr>
            <td>C#</td>
            <td>Java</td>
            <td>Python</td>
            <td>Ruby</td>
            <td>Haskell</td>
          </tr>
          <tr>
            <td>France</td>
            <td>Spain</td>
            <td>Italy</td>
            <td>Germany</td>
            <td>Netherlands</td>
          </tr>
      </tbody>
      </table>
    <p style="font-weight:bold;">The Code:
    <pre><code>
    &lt;script type="text/javascript"&gt;
    window.onload = function() {    
       document.getElementById('getCellContents').onclick = getCellContents;    
    }
    
    function child(elem, index) {
        index = index || 1; 
        elem = (elem.firstChild && elem.firstChild.nodeType != 1) ?
                   next(elem.firstChild) :
                   elem.firstChild;                
        for(var i=1; i < index;i++) {
            (function() {   
                if(elem)  
                return elem = next(elem);         
            })();        
        }
        return elem;
    }
    
    function next(elem) {
        do {
            elem = elem.nextSibling;
        } while (elem && elem.nodeType != 1);
    return elem;                
    }
    
    function getCellContents() {
        var row = parseInt(document.getElementById('row').value, 10);
        var column = parseInt(document.getElementById('column').value, 10);
        var result;
        var color;
        var table = document.getElementById('table');
        var cells = table.getElementsByTagName('td');
        for (var i= 0; i < cells.length; i++) {
            (function() {
                cells[i].bgColor = '#ffffff';
            })();
        }
    
        if (row && column) {
            var tbody = child(table , 2);
            var selectedRow = (row <= tbody.getElementsByTagName("tr").length)? 
                                child(tbody, row): null;
            var selectedCell = (selectedRow && column <= selectedRow.getElementsByTagName("td").length)? 
                                    child(selectedRow, column): null;   
    
            if (selectedRow && selectedCell) {
                selectedCell.bgColor = '#00ff00';
                result = selectedCell.innerHTML;
                color = '#b7b7b7';
            }
            else {
                result = 'Cell does not exist';
                color = '#ff0000';
            }                                           
        }
        else {
            result = 'You must provide numeric arguments for Row and Column Number';
            color = '#ff0000';
        }       
        var results = document.getElementById('results');
        results.innerHTML = result;
        results.style.color = color;
    }
    &lt;/script&gt;
    </code>
    </pre>
    </p>
      </div>
    </body>
    </html>
    
    0 讨论(0)
提交回复
热议问题