John Doe John Doe - 1 year ago 55
Javascript Question

Coffeescript to manipulate DOM with jQuery

I want to add a row in a table based on an an existing row.
I am trying to do it with coffeescript -- but it just doesn't work.

I think I am misunderstanding the way the insertion works in the nested div fields . .because I can move the elements around if they don't have any lower level components ..

So if you can see what I am doing wrong -- please advise and I would also appreciate if you can throw a line on how to change the ID of the added element ..

Here is the coffeescript and the html

$(".add_row").click ->
jQuery ->
alert "Done"

<div id="row1">
<tr> <td> r1c1 </td> <td> r1c2</td> </tr>
<div id="row2">
<tr> <td> r2c1</td> <td> r2c2 </td> </tr>
<div id="row3">
<tr> <td> r3c1 </td> <td> r3c2</td> </tr>
<td>-</td> <td> <button class="add_row"> Add Another Row </button> </td>

Answer Source

Your HTML is not valid so the browser will probably rewrite it and throw everything off for you.

From the fine specification:

Permitted contents
An optional caption element, followed by zero or more colgroup elements, followed by an optional thead element, followed by

one tfoot element, followed by zero or more tbody elements, or one or more tr elements


zero or more tbody elements, or one or more tr elements followed by an optional tfoot element

In particular, <table><div> is not valid. When your jQuery gets to work with the <table>, #row1 won't be inside the table at all and it might not contain what you're expecting it to.

Valid HTML is important so fix the HTML:

  <tr id="row1">
    <td> r1c1 </td>
    <td> r1c2 </td>
  <tr id="row2">
    <td> r2c1 </td>
    <td> r2c2 </td>
  <tr id="row3">
    <td> r3c1 </td>
    <td> r3c2 </td>
    <td> <button class="add_row"> Add Another Row </button> </td>

Then you'll want to fix up your CoffeeScripts. First the indentation, that needs to be consistent and correct since indentation defines the structure of your CoffeeScript. Also, the inner jQuery -> call is unnecessary, that's used to queue up a function to call when the document is ready to work with but you just want to run a bit of code right now when the button is clicked. Furthermore, you don't want to use appendTo as that will:

Insert every element in the set of matched elements to the end of the target.

where you want to put the cloned row after #row3, not inside it. You'd be better off using after and starting with #row3 like this:

$(".add_row").click ->

This will still leave you with some problems, in particular:

  1. You'll have duplicate #row1 elements.
  2. Hitting the button again will keep adding new rows after #row3 rather than right above the button row.

I'll leave fixing those as an exercise for the reader.

For example: