Link to home
Start Free TrialLog in
Avatar of pwtucker
pwtuckerFlag for United States of America

asked on

Set onclick event with javascript when duplicating table row

Hi Experts,
I need some more help.  I have a table with 4 columns and when the user clicks on a button it duplicates the first row.  However, I need to change the onclick event of the new row to be onclick="selectTime(this,field[nextrownumber])".  The problem is that when the new field is created it increases the number at the end of each field, so the copied onclick event is not working correctly.   How can I create this onclick event ("selectTime(this,txtStartTime1)") so that txtStartTime1 becomes txtStartTime[newrownumber]?

Here is the code I am using to create the new row.  The function selectTime is in a referenced js file if that makes a difference.


    <script language="JavaScript" src="js/timepicker.js"></script>

<script language="JavaScript">

function AddRow()
    {                  
            var dColor = '#E5E5E5';  
            var eColor = '#FFFFFF';                      
            var idImg=["deleteStart","StartImg","StopImg"];
            var idText=["chkSelectStartTime","txtStartTime", "txtStopTime", "txtStartStopComments"];            
            var tbl = document.getElementById('StartStop');  
            var ctr = tbl.rows.length;
            if(tbl.rows.length == 7)
            {
                alert("Not allowed to enter more start/stop times to this time sheet.  Please submit this timesheet and create another for more records.");
                return false;
            }
            var tbd = tbl.getElementsByTagName('tbody')[0];
            var r = tbl.getElementsByTagName('tr');
            var c = r[1].cloneNode(true)
           
            var sel = c.getElementsByTagName('img');
            for(var i = 0;i<sel.length;i++)
            {                          
              sel[i].name = idImg[i] + ctr;
              sel[i].id = idImg[i] + ctr;
              if(sel[i].name == 'chkSelectStartTime' + ctr)
                {
                    sel[i].disabled = false;
                    sel[i].alt = "Click icon to delete row.";
                    sel[i].style.backgroundColor = eColor;
                    sel[i].style.cursor = 'hand';                    
                }                                                        
            }

            var sel = c.getElementsByTagName('input');
            for(var i = 0;i<sel.length;i++)
            {                  
                  sel[i].disabled = false;
                  sel[i].name = idText[i] + ctr;
                  sel[i].id = idText[i] + ctr;
                  sel[i].value = "";                                    
            }

            tbd.insertBefore(c,tbl.rows[tbl.rows.length - 1]);
    }

</script>
</head>

    <body>
    <form id="TimeSheet">  

<input id="btnAdd" name="btnAdd;" onclick="AddRow()"
            style="width: 75px; height: 22" type="button" value="Add Row">      
        <table id="StartStop" cellpadding="0" cellspacing="0" style="border-right: LightSteelBlue  thin solid;
            border-top: LightSteelBlue  thin solid; border-left: LightSteelBlue  thin             solid;
            border-bottom: LightSteelBlue  thin solid; border-collapse: collapse;">
            <tr>
                <th style="width: 13px; height: 15px; border-bottom: LightSteelBlue                      thin solid;
                    border-right: LightSteelBlue  thin solid; background-color: AntiqueWhite">
                </th>
                <th style="width: 95px; height: 19px; border-bottom: LightSteelBlue  thin                solid;
                    border-right: LightSteelBlue  thin solid; background-color: AntiqueWhite">
                    Start Time</th>
                <th style="width: 95px; height: 19px; border-bottom: LightSteelBlue  thin                solid;
                    border-right: LightSteelBlue  thin solid; background-color: AntiqueWhite">
                    Stop Time</th>
                <th style="width: 250px; height: 15px; border-bottom: LightSteelBlue                      thin solid;
                    border-right: LightSteelBlue thin solid; background-color: AntiqueWhite">
                    Comments</th>
            </tr>
           
            <tr>
                <td align="center" style="width: 13px; height: 15px; border-bottom: LightSteelBlue thin solid;
                    border-right: LightSteelBlue thin solid">
                    <input id="chkSelectStartTime1" name="chkSelectStartTime1" onclick="this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode);"
                        style="width: 13px; height: 15px; border: 0" type="checkbox" /></td>
                <td style="width: 129px; height: 19px; border-bottom: LightSteelBlue  thin                solid;
                    border-right: LightSteelBlue  thin solid">
                    <input id="txtStartTime1" maxlength="8" name="txtStartTime1"
                        readonly="readonly" size="8" style="width: 95px; height: 19px; border: 0;" type="text"
                        value="" />
                    <img name="StartImg1" alt="Pick a Start Time" border="0" height="19px" onclick="selectTime(this,txtStartTime1)"
                        src="images/timepicker.gif" style="cursor: hand" width="30">
                </td>
                <td style="width: 129px; height: 19px; border-bottom: LightSteelBlue  thin                solid;
                    border-right: LightSteelBlue  thin solid">
                    <input id="txtStopTime1" maxlength="8" name="txtStopTime1"
                        readonly="readonly" size="8" style="width: 95px; height: 19px; border: 0;" type="text"
                        value="" />
                    <img name="StopImg1" alt="Pick a Stop Time" border="0" height="19px" onclick="selectTime(this,txtStopTime1)"
                        src="images/timepicker.gif" style="cursor: hand" width="30">
                </td>  
                <td style="width: 250px; height: 15px; border-bottom: LightSteelBlue                      thin solid;
                    border-right: LightSteelBlue  thin solid">
                    <input maxlength="195px" name="txtStartStopComments1" style="width: 250px; height: 19px; border: 0"
                        type="text" />
                </td>            
            </tr>
            <tr style="visibility:hidden"><td></td></tr>
        </table>
Avatar of HonorGod
HonorGod
Flag of United States of America image

The way to do this is to have the onclick routine travel up the DOM to locate the <tr>,
then find which row this is in the table.

Another way would be to have the row number be an attribute of the current row, so that when the routine locates the <tr> element, it can simply extract the row number (attribute) from this element.

one moment please... (coding)
Avatar of pwtucker

ASKER

My add new row function has the current row.  I just don't know how to tell the new field what the onclick event should be.  I have found several examples, but can't get them to work.
example found:
button.onclick=function(){selectTime(parameters);}

not sure how to enclose the parameters.
Not entirely sure what you are after.  I have assumed the following:

- newrownumber is a variable in scope which contains the new row number
- txtStartTime# is meant to be a string (not like in your example "selectTime(this,txtStartTime1)", where it is a variable).



button.onclick= new Function("selectTime(this,'txtStartTime" +  newrownumber + "'");
Here my way:

<script language="JavaScript">

function AddRow()
    {                  
            var dColor = '#E5E5E5';  
            var eColor = '#FFFFFF';                      
            var idImg=["deleteStart","StartImg","StopImg"];
            var idText=["chkSelectStartTime","txtStartTime", "txtStopTime", "txtStartStopComments"];            
            var tbl = document.getElementById('StartStop');  
            var ctr = tbl.rows.length;
            if(tbl.rows.length == 7)
            {
                alert("Not allowed to enter more start/stop times to this time sheet.  Please submit this timesheet and create another for more records.");
                return false;
            }
            var tbd = tbl.getElementsByTagName('tbody')[0];
            var r = tbl.getElementsByTagName('tr');
            var c = r[1].cloneNode(true)
           
            var sel = c.getElementsByTagName('img');
            for(var i = 0;i<sel.length;i++)
            {                          
              sel[i].name = idImg[i] + ctr;
              sel[i].id = idImg[i] + ctr;
              if(sel[i].name == 'chkSelectStartTime' + ctr)
                {
                    sel[i].disabled = false;
                    sel[i].alt = "Click icon to delete row.";
                    sel[i].style.backgroundColor = eColor;
                    sel[i].style.cursor = 'hand';                    
                }                                                        
            }

            var sel = c.getElementsByTagName('input');
            for(var i = 0;i<sel.length;i++)
            {                  
                  sel[i].disabled = false;
                  sel[i].name = idText[i] + ctr;
                  sel[i].id = idText[i] + ctr;
                  sel[i].value = "";                                    
            }

            tbd.insertBefore(c,tbl.rows[tbl.rows.length - 1]);
    }

function removeRow(theFld){
  var tr = theFld.parentNode;
  while(tr && tr.nodeName!="TR"){
    tr = tr.parentNode;
  }
  if(tr){
    rows = tr.parentNode.rows;
    if(rows.length>1){
      tr.parentNode.removeChild(tr);
    } else {
      alert("Last row.");
    }
  }
}

function popCal(theImg){
  var td = theImg.parentNode;
  while(td && td.nodeName!="TD"){
    td = td.parentNode;
  }
  if(td){
    var inpField = td.getElementsByTagName("input")[0];
    selectTime(theImg, inpField);
  }
}

function selectTime(theImg, theFld){
  alert(theFld.name)
}
</script>
</head>

    <body>
    <form id="TimeSheet">  

<input id="btnAdd" name="btnAdd;" onclick="AddRow()"
            style="width: 75px; height: 22" type="button" value="Add Row">      
        <table id="StartStop" cellpadding="0" cellspacing="0" style="border-right: LightSteelBlue  thin solid;
            border-top: LightSteelBlue  thin solid; border-left: LightSteelBlue  thin             solid;
            border-bottom: LightSteelBlue  thin solid; border-collapse: collapse;">
            <tr>
                <th style="width: 13px; height: 15px; border-bottom: LightSteelBlue                      thin solid;
                    border-right: LightSteelBlue  thin solid; background-color: AntiqueWhite">
                </th>
                <th style="width: 95px; height: 19px; border-bottom: LightSteelBlue  thin                solid;
                    border-right: LightSteelBlue  thin solid; background-color: AntiqueWhite">
                    Start Time</th>
                <th style="width: 95px; height: 19px; border-bottom: LightSteelBlue  thin                solid;
                    border-right: LightSteelBlue  thin solid; background-color: AntiqueWhite">
                    Stop Time</th>
                <th style="width: 250px; height: 15px; border-bottom: LightSteelBlue                      thin solid;
                    border-right: LightSteelBlue thin solid; background-color: AntiqueWhite">
                    Comments</th>
            </tr>
           
            <tr>
                <td align="center" style="width: 13px; height: 15px; border-bottom: LightSteelBlue thin solid;
                    border-right: LightSteelBlue thin solid">
                    <input id="chkSelectStartTime1" name="chkSelectStartTime1" onclick="removeRow(this);"
                        style="width: 13px; height: 15px; border: 0" type="checkbox" /></td>
                <td style="width: 129px; height: 19px; border-bottom: LightSteelBlue  thin                solid;
                    border-right: LightSteelBlue  thin solid">
                    <input id="txtStartTime1" maxlength="8" name="txtStartTime1"
                        readonly="readonly" size="8" style="width: 95px; height: 19px; border: 0;" type="text"
                        value="" />
                    <img name="StartImg1" alt="Pick a Start Time" border="0" height="19px" onclick="popCal(this)"
                        src="images/timepicker.gif" style="cursor: hand" width="30">
                </td>
                <td style="width: 129px; height: 19px; border-bottom: LightSteelBlue  thin                solid;
                    border-right: LightSteelBlue  thin solid">
                    <input id="txtStopTime1" maxlength="8" name="txtStopTime1"
                        readonly="readonly" size="8" style="width: 95px; height: 19px; border: 0;" type="text"
                        value="" />
                    <img name="StopImg1" alt="Pick a Stop Time" border="0" height="19px" onclick="popCal(this)"
                        src="images/timepicker.gif" style="cursor: hand" width="30">
                </td>  
                <td style="width: 250px; height: 15px; border-bottom: LightSteelBlue                      thin solid;
                    border-right: LightSteelBlue  thin solid">
                    <input maxlength="195px" name="txtStartStopComments1" style="width: 250px; height: 19px; border: 0"
                        type="text" />
                </td>            
            </tr>
            <tr style="visibility:hidden"><td></td></tr>
        </table>


Sorry, I did not cound the header row and the invisible last row.
Check this:


function removeRow(theFld){
  var tr = theFld.parentNode;
  while(tr && tr.nodeName!="TR"){
    tr = tr.parentNode;
  }
  if(tr){
    rows = tr.parentNode.rows;
    if(rows.length>3){
      tr.parentNode.removeChild(tr);
    } else {
      alert("Last row.");
    }
  }
}

Let me give this a try.  
In my example "this" is the field which has the onclick event and "txtStartTime1" is a text field on the form/table.

Row 1 = chkbox1     txtStart1     txtStop1     txtCommetns1
(there is an image associated with txtStart1 and txtStop1 that has an onclick event associated with it selectTime(this,txtStart1)

Row created by addRow function:
Row 2 = chkBox2     txtStart2     txtStop2     txtComments2
(Now I want the onclick event for the image to be selectTime(this,txtStart2)

Does this make sense?
Zvonko - Not sure I follow what you are doing.  It looks like you are deleting a row.  My goal is to change the onclick event of a field created in my addRow().
ASKER CERTIFIED SOLUTION
Avatar of Zvonko
Zvonko
Flag of North Macedonia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Oh, and first added row has fields with suffix: 3
Zvonko - I just tried what you said about deleting and adding again.  I was okay as long as I always deleted the last row, but when I deleted one in the middle it caused duplicates.  I will be opening another question about renumbering rows.  Thanks for looking out for me :)

Still not understanding how to change the onclick event when the row is created.  What I would like to do (if possible) is when the new img field is created change the onclick event.  Like below...

for(var i = 0;i<sel.length;i++)
            {                          
              sel[i].name = idImg[i] + ctr;
              sel[i].id = idImg[i] + ctr;
              if(sel[i].name == 'chkSelectStartTime' + ctr)
                {
                    sel[i].disabled = false;
                    sel[i].alt = "Click icon to delete row.";
                    sel[i].style.backgroundColor = eColor;
                    sel[i].style.cursor = 'hand';  
                    sel[i].onclick = new Function(selectTime(this, txtStartTime[i]);
                }                                                        
            }
Sorry, please disregard the if statement above.  

for(var i = 0;i<sel.length;i++)
            {                          
              sel[i].name = idImg[i] + ctr;
              sel[i].id = idImg[i] + ctr;
              sel[i].disabled = false;
              sel[i].alt = "Click icon to delete row.";
              sel[i].style.backgroundColor = eColor;
              sel[i].style.cursor = 'hand';  
               sel[i].onclick = new Function(selectTime(this, txtStartTime[i]);
             }                                                        
       

One thing I'm not clear about in your code is what the selectTime function looks like.  What type of arguments does it take?

Is it:  selectTime(DOM NODE, STRING);
or is it: selectTime(DOM NODE, DOM NODE);
OK, lets get back to this question: how to change the onClick handler?
My answer: Add a generalized onClick handler that uses "this" reference and let that generalized onClick wrapper handler call your calender function with the neighbour input field. Then you need not to care about field name.  That is what my function popCal() does.
By the way, your old onClick handler would work ONLY in IE. This is not defined in FF: txtStartTime1



@basicinstinct: your last question is answered with the last sentence of my previous comment.
ok, in the code where you clone the row, add some code to locate, and modify parm #2 of the onclick to match the value of the associated input element id field.

Each column has:
- And input element with an id value
- An image element with an onclick value

After you clone the row:

  var c   = r[ 1 ].cloneNode( true );

- Locate the input element within this cloned row using:

  var td = c.getElementById( 'txtStartTime1' );

- modify the id attribute to be 'txStartTime' + (current row #)

  var rowNum = tbl.rows.length - 1;
  td.setAttribute( 'id', 'txtStartTime' + rowNum );

- Do the same for the StopTime  

  td = c.getElementById( 'txtStopTime1' );
  td.setAttribute( 'id', 'txtStopTime' + rowNum );

Before you add the new cloned row to the table.
wow, it's really interesting to see what kind of flurry of activity can occur while one is off thinking about, and trying different things... :-)
HG, you described the code that pwtucker already posted in its initial question. The replacing of ids is already done by the original code.
Thanks Zvonko.  Sorry for not quiet understanding your code, but it works perfect.  Be on the look out for the deleting and renumbering my columns.

Thanks everyone..