help with DOM row/cell with innerHTML

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • necromonger

    help with DOM row/cell with innerHTML

    Hi,

    I've got this code that creates a new new row and cell. I then put some
    text into the cell with innerHTML - works beautifully with Firefox but
    fails with IE. I guess IE doesn't support this way of doing it, but is
    there another way of doing it with DOM?

    newr = document.create Element('tr');

    stbl.appendChil d(newr);
    newc = document.create Element('td');

    newr.appendChil d(newc);
    newr.cells[0].innerHTML = (nr+1)+". "+sa[ti][nr + 1]+"<br><hr>";
    (works in firefox but fails in IE 6+ too...)
  • RobG

    #2
    Re: help with DOM row/cell with innerHTML

    necromonger wrote:
    [color=blue]
    > Hi,
    >
    > I've got this code that creates a new new row and cell. I then put some
    > text into the cell with innerHTML - works beautifully with Firefox but
    > fails with IE. I guess IE doesn't support this way of doing it, but is
    > there another way of doing it with DOM?
    >
    > newr = document.create Element('tr');
    >
    > stbl.appendChil d(newr);
    > newc = document.create Element('td');
    >
    > newr.appendChil d(newc);
    > newr.cells[0].innerHTML = (nr+1)+". "+sa[ti][nr + 1]+"<br><hr>";
    > (works in firefox but fails in IE 6+ too...)[/color]

    I have noticed in the past that sometimes you can't access
    an element in IE until it is actually added to the document.
    Try writing your new row to the document (insert it in the
    table), then modify the innerHTML.

    Alternatively, create a text node and append your text to
    it, then append it to the cell. I'm not sure, but you
    should be able to create and append the HR the same way. I
    don't have time to play with this myself right now, just
    hoping to help out.

    Rob

    Comment

    • necromonger

      #3
      Re: help with DOM row/cell with innerHTML

      Thanks ROb. You've mentioned I should "insert" the row into the table,
      how do I do that? isnt appendChild doing it already (internally?)

      It's good you mentioend that, because I also noticed that even when I
      insert a new tr, when i check the table.rows.leng th, it remains the same
      as before.. any ideas will help.. am very new to this (in fact today is
      the 3rd day of my learning)

      thanks plenty!


      RobG wrote:[color=blue]
      > necromonger wrote:
      >[color=green]
      >> Hi,
      >>
      >> I've got this code that creates a new new row and cell. I then put
      >> some text into the cell with innerHTML - works beautifully with
      >> Firefox but
      >> fails with IE. I guess IE doesn't support this way of doing it, but is
      >> there another way of doing it with DOM?
      >>
      >> newr = document.create Element('tr');
      >>
      >> stbl.appendChil d(newr);
      >> newc = document.create Element('td');
      >>
      >> newr.appendChil d(newc);
      >> newr.cells[0].innerHTML = (nr+1)+". "+sa[ti][nr + 1]+"<br><hr>";
      >> (works in firefox but fails in IE 6+ too...)[/color]
      >
      >
      > I have noticed in the past that sometimes you can't access an element in
      > IE until it is actually added to the document. Try writing your new row
      > to the document (insert it in the table), then modify the innerHTML.
      >
      > Alternatively, create a text node and append your text to it, then
      > append it to the cell. I'm not sure, but you should be able to create
      > and append the HR the same way. I don't have time to play with this
      > myself right now, just hoping to help out.
      >
      > Rob[/color]

      Comment

      • RobG

        #4
        Re: help with DOM row/cell with innerHTML

        necromonger wrote:
        [color=blue]
        > Thanks ROb. You've mentioned I should "insert" the row into the table,
        > how do I do that? isnt appendChild doing it already (internally?)[/color]

        Yes, you already do it. I was trying to think of a more
        explicit way of doing it but can't think of one. I tried
        creating P and text nodes and adding them rather than using
        innnerHTML, changing the order, etc. but nothing seems to
        work.
        [color=blue]
        > It's good you mentioend that, because I also noticed that even when I
        > insert a new tr, when i check the table.rows.leng th, it remains the same
        > as before.. any ideas will help.. am very new to this (in fact today is
        > the 3rd day of my learning)[/color]

        I've added a "showDOM" function below. It shows that in IE
        the extra stuff is added but just doesn't get
        displayed(???)

        I've created a new function based on insertBefore and
        nextSibling, but you need an exsiting row to use it - see
        if it solves you problem.

        My guess is that addRow1 is not adding the TR in quite the
        right spot, though IE is normally very tollerant of stuff
        like that.

        Careful of wrapping...

        <html>
        <head>
        <title>Insert Row</title>

        <script type="text/javascript">
        function addRow1(stbl) {
        alert(stbl.rows .length + " : " + stbl.firstChild .nodeName);
        var newr = document.create Element('tr');
        var newc = document.create Element('td');
        var newT1 = document.create Element('p')
        var newT2 = document.create TextNode("A new para.");
        var newT3 = document.create Element('hr')

        newc.appendChil d(newT1);
        newc.appendChil d(newT2);
        newc.appendChil d(newT3);
        newr.appendChil d(newc);
        stbl.appendChil d(newr);

        // Test that DOM stuff works without the table
        var bodyRef = document.getEle mentsByTagName( "body").item(0) ;
        var newT4 = document.create Element('p')
        var newT5 = document.create TextNode("A new para.");
        bodyRef.appendC hild(newT4);
        bodyRef.appendC hild(newT5);

        }

        function addRow2(r) {
        var newr = document.create Element('tr');
        var newc = document.create Element('td');
        newc.innerHTML = "blah blah blah <br><hr>";

        newr.appendChil d(newc);
        var rParent = r.parentNode;
        rParent.insertB efore(newr,r.ne xtSibling);
        }

        function showDOM() {
        var msg = "";
        function listNodes(n) {
        msg += n.nodeName + "\n";
        for (var i=0; i<n.childNodes. length; i++) {
        listNodes(n.chi ldNodes[i]);
        }
        }

        listNodes(docum ent.getElementB yId("aTable"));
        alert(msg);
        }
        </script>

        </head>
        <body>
        <table id="aTable" border="1">
        <tr id="aRow"><td>H ere is aRow</td></tr>
        </table>
        <br>
        <form action="" name="aForm">
        <input type="button" value="add row 1" onclick="
        addRow1(documen t.getElementByI d('aTable'));
        ">
        <input type="button" value="add row 2" onclick="
        addRow2(documen t.getElementByI d('aRow'));
        ">
        <input type="button" value="Show DOM tree"
        onclick="showDO M();">
        </form>

        </body>
        </html>

        Comment

        • Richard Cornford

          #5
          Re: help with DOM row/cell with innerHTML

          necromonger wrote:[color=blue]
          > I've got this code that creates a new new row and cell. I
          > then put some text into the cell with innerHTML - works
          > beautifully with Firefox but fails with IE. I guess IE
          > doesn't support this way of doing it, but is there
          > another way of doing it with DOM?
          >
          > newr = document.create Element('tr');
          >
          > stbl.appendChil d(newr);
          > newc = document.create Element('td');
          >
          > newr.appendChil d(newc);
          > newr.cells[0].innerHTML = (nr+1)+". "+sa[ti][nr + 1]+"<br><hr>";[/color]

          Using the identifier name - stbl - implies that it is a TABLE element to
          which you are appending the row. In DOM (and HTML) terms that is
          structurally incorrect as TR elements may only be children of TBODY,
          THEAD and TFOOT elements. This often causes novices problems when
          building tables dynamically as in HTML TBODY elements may be implied. In
          the HTML DTDs the opening and closing TBODY tags are optional. They do
          not need to be explicitly included in HTML source code, but TBODY
          elements exist in corresponding DOMs as a result of the HTML parser
          encountering a TR outside of any of the elements that are allowed to
          contain it.

          Richard.


          Comment

          • RobG

            #6
            Re: help with DOM row/cell with innerHTML

            necromonger wrote:[color=blue]
            > Thanks ROb. You've mentioned I should "insert" the row into the table,
            > how do I do that? isnt appendChild doing it already (internally?)[/color]
            [snip]

            Read Richard's post below. I'd figured the bit about the TBODY from
            the tree display, but only on the bus home from work. So Richard gave
            me the heart to try again. So the add row function now has a findTbody
            function too - it gets the first TBODY after the TABLE reference that
            you pass. The reason you need this is because you can't guarantee that
            the first child of a table will be a tbody - in Safari and Firefox it's
            a text node.

            If you have a row ref, it's simpler to use the insertBefore/nextSibling
            method.

            Here's some code anyway, and have fun. I've added comments as
            appropriate, you may wish to trim them out.

            Oh, I added an index to the showDOM function to make it easier to tell
            children and siblings.

            <html>
            <head>
            <title>Insert Row</title>

            <script type="text/javascript">

            // Add a row to a table
            function addRow1(stbl) {

            // find the first tbody tag
            var tB = findTbody(stbl) ;

            // create the elements
            var newr = document.create Element('tr');
            var newc = document.create Element('td');

            // append the HTML to the td
            newc.innerHTML = "blah blah blah <br><hr>";

            // append the td to the tr
            newr.appendChil d(newc);

            // append the tr to the tbody
            tB.appendChild( newr);
            }

            // Pass a tableRef and returns the first tBody
            function findTbody(t) {
            function readTree(u) {
            for (var j=0; j<u.childNodes. length; j++) {
            if (u.childNodes[j].nodeName == 'TBODY') {

            // break out if we found a tbody
            return u.childNodes[j];
            }
            // otherwise keep looking
            readTree(u.chil dNodes[j]);
            }
            }
            var x = readTree(t);
            return x;
            }

            // shows the DOM with index
            // only good for IE as other DOM
            // viewers are better
            function showDOM() {
            var msg = "";
            function listNodes(n,x) {
            msg += x + ' ' + n.nodeName + "\n";
            for (var i=0; i<n.childNodes. length; i++) {
            listNodes(n.chi ldNodes[i],x + '.' + i);
            }
            }
            listNodes(docum ent.getElementB yId("aTable"),' 0');
            alert(msg);
            }

            // demonstrates adding a row after a row
            // using insertBefore/nextSibling method
            function addRow2(r) {
            var newr = document.create Element('tr');
            var newc = document.create Element('td');
            newc.innerHTML = "blah blah blah <br><hr>";

            newr.appendChil d(newc);
            var rParent = r.parentNode;
            rParent.insertB efore(newr,r.ne xtSibling);
            }

            </script>

            </head>
            <body>
            <table id="aTable" border="1">
            <tr id="aRow"><td>H ere is aRow</td></tr>
            </table>
            <br>
            <form action="" name="aForm">
            <input type="button" value="add row 1" onclick="
            addRow1(documen t.getElementByI d('aTable'));
            ">
            <input type="button" value="add row 2" onclick="
            addRow2(documen t.getElementByI d('aRow'));
            ">
            <input type="button" value="Show DOM tree"
            onclick="showDO M();">
            </form>

            </body>
            </html>

            Comment

            • VK

              #7
              Repeat of 09/29/04: Re: setting outerHTML - can this be done?

              The Table Object Model cannot be manipulated in such way.

              var myTable = getElementById( 'myTable');
              var myRow = myTable.insertR ow();
              if (myRow != null) {
              var myCell = myRow.insertCel l();
              myCell.innerHTM L = '<b>It works !!!!!!!!</b>';
              }
              else {
              window.alert('Y ou can not change a data-bound table. You have to change the
              data source itself');
              }


              More of useful reading:
              Find official documentation, practical know-how, and expert guidance for builders working and troubleshooting in Microsoft products.





              Comment

              • Fred Oz

                #8
                Re: Repeat of 09/29/04: Re: setting outerHTML - can this be done?

                VK wrote:[color=blue]
                > The Table Object Model cannot be manipulated in such way.[/color]
                [snip]

                Yes it can. The post you refer to tried to modify a TR using innerHTML.
                You can modify the contents of a cell (td) with innerHTML, which is
                what the OP was trying to do after creating the row and cell with DOM
                methods.

                Cheers, Fred.

                Comment

                • necromonger

                  #9
                  Re: help with DOM row/cell with innerHTML

                  Thanks RIchard, Rob,

                  Rob - nice of you to put in some code. Let me play around with that and
                  see if I get it working the way I want and I'll post an update.
                  Hmm...dint think a simple one would turn out this complicated! thanks to
                  IE >:/ :(


                  RobG wrote:[color=blue]
                  > necromonger wrote:
                  >[color=green]
                  >> Thanks ROb. You've mentioned I should "insert" the row into the table,
                  >> how do I do that? isnt appendChild doing it already (internally?)[/color]
                  >
                  > [snip]
                  >
                  > Read Richard's post below. I'd figured the bit about the TBODY from
                  > the tree display, but only on the bus home from work. So Richard gave
                  > me the heart to try again. So the add row function now has a findTbody
                  > function too - it gets the first TBODY after the TABLE reference that
                  > you pass. The reason you need this is because you can't guarantee that
                  > the first child of a table will be a tbody - in Safari and Firefox it's
                  > a text node.
                  >
                  > If you have a row ref, it's simpler to use the insertBefore/nextSibling
                  > method.
                  >
                  > Here's some code anyway, and have fun. I've added comments as
                  > appropriate, you may wish to trim them out.
                  >
                  > Oh, I added an index to the showDOM function to make it easier to tell
                  > children and siblings.
                  >
                  > <html>
                  > <head>
                  > <title>Insert Row</title>
                  >
                  > <script type="text/javascript">
                  >
                  > // Add a row to a table
                  > function addRow1(stbl) {
                  >
                  > // find the first tbody tag
                  > var tB = findTbody(stbl) ;
                  >
                  > // create the elements
                  > var newr = document.create Element('tr');
                  > var newc = document.create Element('td');
                  >
                  > // append the HTML to the td
                  > newc.innerHTML = "blah blah blah <br><hr>";
                  >
                  > // append the td to the tr
                  > newr.appendChil d(newc);
                  >
                  > // append the tr to the tbody
                  > tB.appendChild( newr);
                  > }
                  >
                  > // Pass a tableRef and returns the first tBody
                  > function findTbody(t) {
                  > function readTree(u) {
                  > for (var j=0; j<u.childNodes. length; j++) {
                  > if (u.childNodes[j].nodeName == 'TBODY') {
                  >
                  > // break out if we found a tbody
                  > return u.childNodes[j];
                  > }
                  > // otherwise keep looking
                  > readTree(u.chil dNodes[j]);
                  > }
                  > }
                  > var x = readTree(t);
                  > return x;
                  > }
                  >
                  > // shows the DOM with index
                  > // only good for IE as other DOM
                  > // viewers are better
                  > function showDOM() {
                  > var msg = "";
                  > function listNodes(n,x) {
                  > msg += x + ' ' + n.nodeName + "\n";
                  > for (var i=0; i<n.childNodes. length; i++) {
                  > listNodes(n.chi ldNodes[i],x + '.' + i);
                  > }
                  > }
                  > listNodes(docum ent.getElementB yId("aTable"),' 0');
                  > alert(msg);
                  > }
                  >
                  > // demonstrates adding a row after a row
                  > // using insertBefore/nextSibling method
                  > function addRow2(r) {
                  > var newr = document.create Element('tr');
                  > var newc = document.create Element('td');
                  > newc.innerHTML = "blah blah blah <br><hr>";
                  >
                  > newr.appendChil d(newc);
                  > var rParent = r.parentNode;
                  > rParent.insertB efore(newr,r.ne xtSibling);
                  > }
                  >
                  > </script>
                  >
                  > </head>
                  > <body>
                  > <table id="aTable" border="1">
                  > <tr id="aRow"><td>H ere is aRow</td></tr>
                  > </table>
                  > <br>
                  > <form action="" name="aForm">
                  > <input type="button" value="add row 1" onclick="
                  > addRow1(documen t.getElementByI d('aTable'));
                  > ">
                  > <input type="button" value="add row 2" onclick="
                  > addRow2(documen t.getElementByI d('aRow'));
                  > ">
                  > <input type="button" value="Show DOM tree"
                  > onclick="showDO M();">
                  > </form>
                  >
                  > </body>
                  > </html>[/color]

                  Comment

                  • necromonger

                    #10
                    Re: help with DOM row/cell with innerHTML

                    But richard, this thing works fine in Firefox.(of course, I'll correct
                    it structurally later on). What I see doesnt work in IE is that it
                    throws an error for

                    tbl.rows[0].cells[0].innerHTML (not supported error)

                    and if i do newc.innerHTML = "blah blah" and then do appendchild - it
                    throws no error but shows no table either :( firefox works in both
                    cases. I'm at my wits end to make it work for IE but retaining my DOm
                    code as much as possible.

                    Richard Cornford wrote:[color=blue]
                    > necromonger wrote:
                    >[color=green]
                    >>I've got this code that creates a new new row and cell. I
                    >>then put some text into the cell with innerHTML - works
                    >>beautifully with Firefox but fails with IE. I guess IE
                    >>doesn't support this way of doing it, but is there
                    >>another way of doing it with DOM?
                    >>
                    >> newr = document.create Element('tr');
                    >>
                    >> stbl.appendChil d(newr);
                    >> newc = document.create Element('td');
                    >>
                    >> newr.appendChil d(newc);
                    >> newr.cells[0].innerHTML = (nr+1)+". "+sa[ti][nr + 1]+"<br><hr>";[/color]
                    >
                    >
                    > Using the identifier name - stbl - implies that it is a TABLE element to
                    > which you are appending the row. In DOM (and HTML) terms that is
                    > structurally incorrect as TR elements may only be children of TBODY,
                    > THEAD and TFOOT elements. This often causes novices problems when
                    > building tables dynamically as in HTML TBODY elements may be implied. In
                    > the HTML DTDs the opening and closing TBODY tags are optional. They do
                    > not need to be explicitly included in HTML source code, but TBODY
                    > elements exist in corresponding DOMs as a result of the HTML parser
                    > encountering a TR outside of any of the elements that are allowed to
                    > contain it.
                    >
                    > Richard.
                    >
                    >[/color]

                    Comment

                    • Richard Cornford

                      #11
                      Re: help with DOM row/cell with innerHTML

                      RobG wrote:
                      <snip>[color=blue]
                      > .... So the add row function now has a findTbody function
                      > too - it gets the first TBODY after the TABLE reference
                      > that you pass. ...[/color]
                      <snip>

                      You may be interested to here that the W3C HTML DOM specification
                      defines a - tbodies - property of TABLE elements that is a collection
                      containing all of the TBODYs in a table. It isn't quite universally
                      supported even on otherwise quite complete W3C DOM browsers but it would
                      always be my first port of call, possibly with -
                      table.getElemen tsByTagName('TB ODY') - my second.

                      Richard.


                      Comment

                      • Richard Cornford

                        #12
                        Re: help with DOM row/cell with innerHTML


                        necromonger wrote:[color=blue]
                        > But richard, this thing works fine in Firefox.(of course,
                        > I'll correct it structurally later on). ...[/color]

                        I will bet that if you examine the constructed DOM you will find that
                        Firefox has added the intervening TBODY element for you, if not then you
                        got lucky (it happens), but there is still not reason to expect it to
                        work in other browsers (indeed the W3C Core DOM spec says an exception
                        should be thrown when an attempt is made to construct an invalid tree,
                        though I can see why people are reluctant to implement that in HTML web
                        browsers).

                        Oh, and please don't top post to comp.lang.javas cript.

                        Richard.



                        Comment

                        • RobG

                          #13
                          Re: help with DOM row/cell with innerHTML

                          necromonger wrote:[color=blue]
                          > Thanks RIchard, Rob,
                          >
                          > Rob - nice of you to put in some code. Let me play around with that and
                          > see if I get it working the way I want and I'll post an update.
                          > Hmm...dint think a simple one would turn out this complicated! thanks to
                          > IE >:/ :(
                          >[/color]
                          [snip]

                          So I guess you have a couple of options here:

                          You can use Richard's table.getElemen tsByTagName, it
                          returns a collection so you likely need to pick where you
                          want to insert your row (after the last one?). It will
                          probably do the job just fine 999 out of 1,000 and you are
                          in control of whether it works or not (i.e. it breaks
                          depending on the HTML you compose, not how the browser
                          reads it).

                          One caveat: if you intend to put in an empty
                          table (e.g. <table></table>) then add rows, some browsers
                          do not put in a tbody (e.g. Safari) even though they do put
                          in a tbody if there are rows there in the HTML. So you
                          can't add rows using JD. If this is your intent, make sure
                          you put a tbody in the HTML.

                          You can use the tree climbing method to find the first
                          tbody, but it's got pretty much the same issues as the
                          getElements... method and is likely overly complex - it
                          worked but I like getElements... better - it's simple.

                          Another method is to put in a row, then use style to hide
                          it, like:

                          <tr style="display: none;">...td's as required...</tr>

                          Now you have an apparently empty table and an
                          explicit place to add rows and can use the
                          insertBefore/nextSibling method. No more tbody issues.

                          It can even save you a lot of work if you have lots of
                          cells, so you can use cloneNode to clone an entire row,
                          then insert your HTML into cells as required rather than
                          using DOM methods to create all the elements - remember to
                          change the display property of your clone to '' or it'll
                          inherit the originals 'none'.

                          Gosh, spoilt for choice - Rob.


                          PS I keep forgetting that you can use things like:

                          var theTDs = tableRef.getEle mentsByTagName( 'td');

                          It even works getting the LIs in an OL or UL.

                          Comment

                          • VK

                            #14
                            Re: Repeat of 09/29/04: Re: setting outerHTML - can this be done?

                            > > The Table Object Model cannot be manipulated in such way.
                            [color=blue]
                            > Yes it can.[/color]

                            No, it can not :-)

                            I mean it is sometimes possible on some browsers, but it should not be used.
                            It's like use an assembler for direct memory patch instead of using proper
                            object's methods. May work, may not, may blow up in your face.

                            Using TOD as I suggested gives you the proper references to the rows and
                            cells, so you can apply innerHTML method to the proper object in the proper
                            way:
                            ....
                            var myCell = myRow.insertCel l();
                            myCell.innerHTM L = '<b>It works !!!!!!!!</b>';
                            ....




                            Comment

                            • Fred Oz

                              #15
                              Re: Repeat of 09/29/04: Re: setting outerHTML - can this be done?

                              VK wrote:
                              [snip][color=blue]
                              > var myCell = myRow.insertCel l();
                              > myCell.innerHTM L = '<b>It works !!!!!!!!</b>';
                              > ...[/color]

                              The OP had:

                              newr = document.create Element('tr');
                              stbl.appendChil d(newr); // here's the error
                              newc = document.create Element('td');
                              newr.appendChil d(newc);
                              newr.cells[0].innerHTML = (nr+1)+". "+sa[ti][nr + 1]+"<br><hr>";

                              I fail to see the difference - but I've been wrong before... You both
                              used DOM methods to create a row and a cell, then append the cell to the
                              row. You both then use innnerHTML to write the content of the cell.

                              The order in which the OP did things was a bit strange though...

                              The OP's problem was appending the row to the table node, not the
                              tablebody. Firefox shrugged and just put the row in the right place, IE
                              barfed 'cos it wanted a tbody - I would have bet money on the exact
                              opposite happening, but wonders never cease.

                              Cheers, Fred.

                              Comment

                              Working...