Uncaught exception when calling rowIndex.

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • meaneyedcat@hotmail.com

    Uncaught exception when calling rowIndex.

    When I call addField(), my table appears to be populated correctly
    with a new row in the table with all the required fields. However,
    when I call delete row on any new rows that have been created, I get
    the following error:

    Error: uncaught exception: [Exception... "Component returned failure
    code: 0x80004002 (NS_NOINTERFACE )
    [nsIDOMHTMLTable RowElement.rowI ndex]" nsresult: "0x80004002
    (NS_NOINTERFACE )" location: "JS frame ::
    http://localhost:3000/form/edit_fields/1 :: removeField :: line 65"
    data: no]

    The error appears to happen when the last line of removeField() gets
    called...specif ically rowToDelete.row Index throws the exception.

    I should mention that I am running this code on Firefox 1.0, however,
    when I run it on IE6, it doesn't work either, but I don't know what
    the error is (I just don't know how to get a trace of the JavaScript
    errors).

    thanks for your help!
    Aaron.

    <script type="text/javascript">
    var newArray = new Array();
    var exArray = new Array();

    var delArr = new Array();

    var tbCount=<%= @form.inputs.co unt %>;

    function addField() {
    newArray[tbCount]=document.creat eElement('INPUT ');
    table = document.getEle mentById('field Table');

    row = document.create Element('tr');
    row.id = 'n_' + (tbCount + 1);
    fieldCell = document.create Element('td');
    fieldCell.appen dChild(document .createTextNode ('Field ' +
    (tbCount + 1) + ':'));

    nameCell = document.create Element('td');
    nameInput = document.create Element('input' );
    nameInput.id = 'nname' + (tbCount + 1);
    nameInput.name = 'nname[' + (tbCount + 1) + ']';
    nameInput.type = 'text';
    nameInput.size = '30';
    nameCell.append Child(nameInput );

    descCell = document.create Element('td');
    descInput = document.create Element('input' );
    descInput.id = 'newdesc' + (tbCount + 1);
    descInput.name = 'newdesc[' + (tbCount + 1) + ']';
    descInput.type = 'text';
    descInput.size = '30';
    descCell.append Child(descInput );

    delCell = document.create Element('td');
    delLink = document.create Element('a');
    delLink.href = "#";
    delLink.setAttr ibute('onClick' , "removeField(n_ " + (tbCount+1) +
    "); return false");
    delLink.appendC hild(document.c reateTextNode(' Delete'));
    delCell.appendC hild(delLink);

    table.appendChi ld(row);
    row.appendChild (fieldCell);
    row.appendChild (nameCell);
    row.appendChild (descCell);
    row.appendChild (delCell);
    tbCount++;
    }

    function removeField(row ToDelete) {
    array = rowToDelete.id. split('_');
    rowType = array[0];
    rowId = array[1];

    switch (rowType) {
    case 'e':
    break;
    case 'n':
    break;
    }
    table = document.getEle mentById('field Table');
    table.deleteRow (rowToDelete.ro wIndex);
    }
    </script>

  • Martin Honnen

    #2
    Re: Uncaught exception when calling rowIndex.



    meaneyedcat@hot mail.com wrote:

    [color=blue]
    > when I call delete row on any new rows that have been created, I get
    > the following error:
    >
    > Error: uncaught exception: [Exception... "Component returned failure
    > code: 0x80004002 (NS_NOINTERFACE )
    > [nsIDOMHTMLTable RowElement.rowI ndex]" nsresult: "0x80004002
    > (NS_NOINTERFACE )" location: "JS frame ::
    > http://localhost:3000/form/edit_fields/1 :: removeField :: line 65"
    > data: no]
    >
    > The error appears to happen when the last line of removeField() gets
    > called...specif ically rowToDelete.row Index throws the exception.[/color]
    [color=blue]
    > function removeField(row ToDelete) {
    > array = rowToDelete.id. split('_');
    > rowType = array[0];
    > rowId = array[1];
    >
    > switch (rowType) {
    > case 'e':
    > break;
    > case 'n':
    > break;
    > }
    > table = document.getEle mentById('field Table');
    > table.deleteRow (rowToDelete.ro wIndex);
    > }[/color]

    We need to see where you call the function, exactly what you pass in as
    an argument, make sure it is really a row element object.

    --

    Martin Honnen

    Comment

    • Michael Winter

      #3
      Re: Uncaught exception when calling rowIndex.

      meaneyedcat@hot mail.com wrote:
      [color=blue]
      > [W]hen I call delete row on any new rows that have been created, I
      > get the following error:[/color]

      Could you create a minimal example and provide a URL? It's much easier
      to diagnose a problem when it can be seen in action.

      [snip]
      [color=blue]
      > function addField() {
      > newArray[tbCount]=document.creat eElement('INPUT ');
      > table = document.getEle mentById('field Table');
      >
      > row = document.create Element('tr');
      > row.id = 'n_' + (tbCount + 1);
      > fieldCell = document.create Element('td');
      > fieldCell.appen dChild(document .createTextNode ('Field '
      > + (tbCount + 1) + ':'));[/color]

      I would seriously consider learning to apply the var keyword within
      functions. It is not a good idea to dump loads of variables into the
      global object.

      [snip]
      [color=blue]
      > delLink.setAttr ibute('onClick' , "removeField(n_ " + (tbCount+1)
      > + "); return false");[/color]

      Isn't the argument to removeField supposed to be a string? You should
      change that second argument to

      'removeField("n _' + (tbCount + 1) + '"); return false;'

      That said, this isn't a reliable way to create event listeners (though
      it will certainly work in Mozilla). If you plan on using this code in
      a wider environment, take the traditional approach:

      delLink.onclick = function() {
      removeField('n_ ' + (tbCount + 1));
      return false;
      };

      [snip]

      Mike

      --
      Michael Winter
      Replace ".invalid" with ".uk" to reply by e-mail.

      Comment

      • meaneyedcat@hotmail.com

        #4
        Re: Uncaught exception when calling rowIndex.

        I don't have a webserver in which I can deploy my code, but I can give
        you the full page source if that will help.

        When I add a row to a table through JavaScript, is the internal
        representation of the table and rows still accessable as if the rows
        where there when the page was rendered initially? I noticed that when I
        add a row using table.insertRow (table.rows.len gth) and then
        alert(table.row s.length), the number is always the same. So, if I had 3
        rows rendered initially, the alert would display three. When I append a
        couple more rows using the code below, the row count would still be
        three. That leads me to believe that A) The rows are appended in some
        other structure, or B) I have no clue what I am doing! I am willing to
        accept B over A at this point. =-)

        As for the parameter to the move method being wrapped in quotes. If I
        do that, it actually returns a string, but when I leave the quotes out,
        it returns the HTMLTableRowEle ment, which works nice because I should
        be able to get the rowIndex from it (but I am not, I am getting this
        exception!).

        Anyway, thanks for your help and quick replies! Below is the full
        source for the page.
        Thanks again!
        AR.

        <html>
        <head>
        <title></title>

        <script type="text/javascript">
        var newArray = new Array();
        var exArray = new Array();
        var delArr = new Array();

        var tbCount=<%= @form.inputs.co unt %>;

        function addField() {
        table = document.getEle mentById('field Table');

        row = table.insertRow (table.rows.len gth);
        row.id = 'n_' + (tbCount + 1);
        fieldCell = document.create Element('td');
        fieldCell.appen dChild(document .createTextNode ('Field ' + (tbCount +
        1) + ':'));

        nameCell = document.create Element('td');
        nameInput = document.create Element('input' );
        nameInput.id = 'nname' + (tbCount + 1);
        nameInput.name = 'nname[' + (tbCount + 1) + ']';
        nameInput.type = 'text';
        nameInput.size = '30';
        nameCell.append Child(nameInput );

        descCell = document.create Element('td');
        descInput = document.create Element('input' );
        descInput.id = 'newdesc' + (tbCount + 1);
        descInput.name = 'newdesc[' + (tbCount + 1) + ']';
        descInput.type = 'text';
        descInput.size = '30';
        descCell.append Child(descInput );

        delCell = document.create Element('td');
        delLink = document.create Element('a');
        delLink.href = "#";
        delLink.setAttr ibute('onClick' , "removeField(n_ " + (tbCount+1) + ");
        return false");
        delLink.appendC hild(document.c reateTextNode(' Delete'));
        delCell.appendC hild(delLink);

        table.appendChi ld(row);
        row.appendChild (fieldCell);
        row.appendChild (nameCell);
        row.appendChild (descCell);
        row.appendChild (delCell);
        tbCount++;
        }

        function removeField(row ToDelete) {
        array = rowToDelete.id. split('_');
        rowType = array[0];
        rowId = array[1];

        switch (rowType) {
        case 'e':
        break;
        case 'n':
        break;
        }
        alert(rowToDele te.rowIndex);
        table = document.getEle mentById('field Table');
        table.deleteRow (rowToDelete.ro wIndex);
        }
        </script>

        </head>
        <body>


        <%= start_form_tag( {:action => "save_field s", :id => @form.id}, "id"
        => "fieldForm" ) %>

        <table id="fieldTable" >
        <% i = 0
        @form.inputs.ea ch do |field|
        i = i + 1
        %>
        <tr id="e_<%= i %>">
        <td>
        Field <%= i %>:
        </td>
        <td>
        <%= text_field "name", field.id, "value" => field.name %>
        </td>
        <td>
        <%= text_field "descriptio n", field.id, "value" => field.descripti on
        %>
        </td>
        <td>
        <a href="#" onClick="remove Field(<%= 'e_' + i.to_s %>); return
        false;">Delete</a>
        <!-- %= link_to("Delete ", :action => "delete_fie ld", :id => field.id
        ) % -->
        </td>
        </tr>
        <% end %>
        </table>
        <input type="submit" value="Save"/>
        <%= hidden_field "field_coun t", "count", "value" => @form.inputs.co unt
        %>
        <%= end_form_tag %>
        <a href="#" onClick="addFie ld(); return false;">Add Field</a>

        </body>
        </html>

        Comment

        • Michael Winter

          #5
          Re: Uncaught exception when calling rowIndex.

          meaneyedcat@hot mail.com wrote:
          [color=blue]
          > I don't have a webserver in which I can deploy my code, but I can
          > give you the full page source if that will help.[/color]

          In it's current form, no. Please show the *output* of the server-side
          code (preferably with only a minimal set of input data).
          [color=blue]
          > I noticed that when I add a row using
          > table.insertRow (table.rows.len gth)[/color]

          You can use

          table.insertRow (-1);

          to append a row.
          [color=blue]
          > and then alert(table.row s.length), the number is always the same.[/color]

          In which browser? Both IE6 and Firefox 1.0 update the row count. I'd
          expect Opera to as well.
          [color=blue]
          > As for the parameter to the move method being wrapped in quotes. If
          > I do that, it actually returns a string, but when I leave the
          > quotes out, it returns the HTMLTableRowEle ment [...][/color]

          My apologies. I should have double-checked. However, you shouldn't
          rely on that behaviour. Obtaining a reference to an element through
          its id attribute value alone is not well supported (and in my opinion,
          a horrible feature to implement).

          On the subject of sending a reference though, this can easily be
          achieved with a slight modification to the code I posted:

          function addField() {
          /* ... */

          var row = table.insertRow (-1);

          /* ... */

          delLink.onclick = function() {
          removeField(row );
          return false;
          };

          /* ... */
          }

          For that to work the variable, row, *must* be local (as above).

          [snip]

          Mike

          --
          Michael Winter
          Replace ".invalid" with ".uk" to reply by e-mail.

          Comment

          • meaneyedcat@hotmail.com

            #6
            Re: Uncaught exception when calling rowIndex.

            Thanks Michael, you have given me some things to think about. Listed
            below is the output of the rendered HTML page.

            Thanks again!
            AR.

            <html>
            <head>
            <title></title>

            <script type="text/javascript">
            var newArray = new Array();
            var exArray = new Array();
            var delArr = new Array();

            var tbCount=1;

            function addField() {
            table = document.getEle mentById('field Table');

            row = table.insertRow (table.rows.len gth);
            row.id = 'n_' + (tbCount + 1);
            fieldCell = document.create Element('td');
            fieldCell.appen dChild(document .createTextNode ('Field ' + (tbCount +
            1) + ':'));

            nameCell = document.create Element('td');
            nameInput = document.create Element('input' );
            nameInput.id = 'nname' + (tbCount + 1);
            nameInput.name = 'nname[' + (tbCount + 1) + ']';
            nameInput.type = 'text';
            nameInput.size = '30';
            nameCell.append Child(nameInput );

            descCell = document.create Element('td');
            descInput = document.create Element('input' );
            descInput.id = 'newdesc' + (tbCount + 1);
            descInput.name = 'newdesc[' + (tbCount + 1) + ']';
            descInput.type = 'text';
            descInput.size = '30';
            descCell.append Child(descInput );

            delCell = document.create Element('td');
            delLink = document.create Element('a');
            delLink.href = "#";
            delLink.setAttr ibute('onClick' , "removeField(n_ " + (tbCount+1) + ");
            return false");
            delLink.appendC hild(document.c reateTextNode(' Delete'));
            delCell.appendC hild(delLink);

            table.appendChi ld(row);
            row.appendChild (fieldCell);
            row.appendChild (nameCell);
            row.appendChild (descCell);
            row.appendChild (delCell);
            tbCount++;
            }

            function removeField(row ToDelete) {
            array = rowToDelete.id. split('_');
            rowType = array[0];
            rowId = array[1];

            swit:h (rowType) {
            case 'e':
            break;
            case 'n':
            break;
            }
            alert(rowToDele te.rowIndex);
            table = document.getEle mentById('field Table');
            table.deleteRow (rowToDelete.ro wIndex);
            }
            </script>

            </head>
            <body>


            <form action="/form/save_fields/1" id="fieldForm" method="post">

            <table id="fieldTable" >

            <tr id="e_1">

            <td>
            Field 1:
            </td>
            <td>
            <input id="name_1" name="name[1]" size="30" type="text" value="ID"
            />
            </td>
            <td>
            <input id="description _1" name="descripti on[1]" size="30"
            type="text" value="Serial Number" />
            </td>

            <td>
            <a href="#" onClick="remove Field(e_1); return false;">Delete</a>
            <!-- %= link_to("Delete ", :action => "delete_fie ld", :id => field.id
            ) % -->
            </td>
            </tr>

            </table>
            <input type="submit" value="Save"/>
            <input id="field_count _count" name="field_cou nt[count]" type="hidden"
            value="1" />
            </form>
            <a href="#" onClick="addFie ld(); return false;">Add Field</a>

            </body>
            </html>

            Comment

            • meaneyedcat@hotmail.com

              #7
              Re: Uncaught exception when calling rowIndex.

              OK, I figured out why the table.rows.leng th wasn't updating. If you
              look at my code, I first do a

              row = table.insertRow (XXXX);

              then later in the code, I manually add that row to the table
              again....some funky stuff must have been happening behind the scenes.

              AR.

              Comment

              • Martin Honnen

                #8
                Re: Uncaught exception when calling rowIndex.



                meaneyedcat@hot mail.com wrote:
                [color=blue]
                > function addField() {
                > table = document.getEle mentById('field Table');[/color]

                It was already suggested to make sure your function uses local variables
                e.g.
                var table = ...[color=blue]
                > row = table.insertRow (table.rows.len gth);[/color]
                var row = ...
                and so on. That also means you can use
                [color=blue]
                > delLink.setAttr ibute('onClick' , "removeField(n_ " + (tbCount+1) + ");
                > return false");[/color]

                delLink.onclick = function (evt) {
                removeField(row );
                return false;
                };
                here instead of what you have, setAttribute is unfortunately implemented
                in different ways in different browsers.

                [color=blue]
                > table.appendChi ld(row);[/color]

                Don't do that if you have called insertRow above to create the row.
                Indeed even if you used createElement to create a row don't call
                appendChild on the table itself, instead make sure you insert into a tbody.

                [color=blue]
                > function removeField(row ToDelete) {[/color]
                [color=blue]
                > table = document.getEle mentById('field Table');
                > table.deleteRow (rowToDelete.ro wIndex);[/color]

                You could simply do
                rowToDelete.par entNode.removeC hild(rowToDelet e);
                for those two lines.

                [color=blue]
                > <table id="fieldTable" >
                >
                > <tr id="e_1">
                >
                > <td>
                > Field 1:
                > </td>
                > <td>
                > <input id="name_1" name="name[1]" size="30" type="text" value="ID"
                > />
                > </td>
                > <td>
                > <input id="description _1" name="descripti on[1]" size="30"
                > type="text" value="Serial Number" />
                > </td>
                >
                > <td>
                > <a href="#" onClick="remove Field(e_1);[/color]

                Don't rely on elements being accessible by variables of the name of the
                id attribute, that works in IE and some other browsers (unfortunately
                even in Firefox 1.0 in quirks mode) but for cross-browser support you
                should use document.getEle mentById e.g.
                <a onclick="var row;
                if (document.getEl ementById && (row =
                document.getEle mentById('e_1') )) {
                removeField(row );
                }
                return false;"

                --

                Martin Honnen

                Comment

                Working...