简体   繁体   中英

Unable to attach event listeners to dynamically created elements in IE8

OVERVIEW:

When I click a button i want to

  • insert a new row at the end of a table
  • copy the cells and contents from the first row of the table
  • give unique ids to the elements within the cells
  • assign a focus event listener to all inputs in the page.

PROBLEM:

The event handlers are not firing on the correct elements in IE8. For example if I focus on the last input in the table, the first input gets highlighted.

CLARIFICATION:

  • This works in IE10, Chrome.
  • Does not work in IE8 which is my target browser.
  • I know of ways to get around this.My aim is NOT to find a workaround but to understand what my mistake is, in the given code.
  • The example code is just a quick simplified version of the problem. I am not asking for code optimization thats not relevant to the question.
  • Change event does not work too.

CODE:

HTML:

<table width="200" border="1" id="myTable">
    <tr>
        <td>
            <input type='text' id='row0col0' name='row0col0'>
        </td>
    </tr>
</table>
<button id="addRow">Add Row</button>

JS:

function addFocusListener() {
     $("input").unbind();
     $("input").each(function () {
         var $this = $(this);
         $this.focus(function () {
             var newThis = $(this);
             newThis.css('background-color', 'red');
         });    
     });
 }

 function addRowWithIncrementedIDs() {
     var table = document.getElementById("myTable");
     var newRow = table.insertRow(-1);
     var row = table.rows[0];
     var rowNum = newRow.rowIndex;
     for (var d = 0; d < row.cells.length; d++) {
         var oldCell = row.cells[d];
         newCell = oldCell.cloneNode(true);
         newRow.appendChild(newCell);

         for (var c = 0; c < newCell.childNodes.length; c++) {
             var currElement = newCell.childNodes[c];
             var id = "row" + rowNum + "col" + d;
             $(currElement).attr('name', id);
             $(currElement).attr('id', id);
         }
     }
 }    
 $(document).ready(function () {

     $("#addRow").click(function () {
         addRowWithIncrementedIDs();
         addFocusListener();
     });
 });

OTHER APPROACHES THAT WORK:

  1. changing from jQuery binding to regular JS binding. Ie from

     $this.focus(function () {....}); 

    to
    this.onfocus =function () {....};

  2. Attaching the event handler as they are rendered.

FIDDLE:

http://jsfiddle.net/sajjansarkar/GJvvu/

RELATED LINKS IN SO:

jQuery event listener doesn't work in IE 7/8

EDIT

Sorry, I just noticed your comment that you want to understand the error in your code. I can quickly tell you one error, and that is mixing jQuery and native DOM methods. If you have dedicated yourself to using a very powerful library, then use all of it's features, not just the ones you understand.

The below code uses event delegation (to fix your focusing problem) and jQuery methods to more simply add a row to the table than with native methods.

If you're going to use jQuery, then you might as well use it all the way:

var t = $('#myTable');

$(document)
    .on('focus','#myTable input',function() { 
        $(this).css('background','red') 
    })
    .on('click','#addRow',function() {
        //create a new row
        var 
            newIndex,
            r = t.find('tr').eq(0).clone();

        //append it to the table
        r.appendTo(t);

        //update newIndex - use it for later
        newIndex = r.index();

        //update the name/id of each of the inputs in the new row
        r.find('input').each(function() {
            var 
                el = $(this),
                id = 'row'+newIndex+'col'+el.closest('td').index();

                el.attr('id',id).attr('name',name);
        });

    });

http://jsfiddle.net/GJvvu/1/

You don't need to loop through your inputs and bind a focus handler to each of them, jQuery automatically collects all DOM elements that match the selector and performs it's focus API function on each of them:

Change this:

function addFocusListener() {
     $("input").unbind();
     $("input").each(function () {
         var $this = $(this);
         $this.focus(function () {
             var newThis = $(this);
             newThis.css('background-color', 'red');
         });    
     });
 }

To this

function addFocusListener() {
 $('input')
   .unbind()
   .focus(function(){
     $(this).css('background-color','red');
   });
}
$("#addRow").live("click", function(){
 addRowWithIncrementedIDs();
 addFocusListener();
 });

Try out above code... this should work..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM