Michael Eugene Yuen Michael Eugene Yuen - 2 months ago 10
jQuery Question

Click function only works once (because selectors were removed and added back again)

I managed to fire the

$('.edit').click(function(){}
and
$('.button').click(function(e){}




$('.edit').click(function(){
// uid = userid
var uid = '123';
var self = $(this);
// closest in the parent elements
// use .find with caution unless you sure you have only one .input
// contenteditable makes element editable. use with caution as it accepts html tags, javascript
// .addClass for styling
var input = self.closest('tr').find('.input');
input.attr('contenteditable','true').addClass('editable');
self.closest('td').html('<span class="button">Save</span>');
$('.button').click(function(e){
e.preventDefault();
var field = $(this).closest('tr').data('field');
// get text instead of html from editable tr
var value = $(this).closest('tr').find('.input.editable').text();
if (value.length > 0) {
var dataString = 'edit_info=' + uid + '&field=' + field + '&value=' + value;
alert(dataString);
// $.ajax({
// type: "POST",
// url: "ajax.php",
// data: dataString,
// success: function(data){
// if (data == 'success') {
input.attr('contenteditable','false').removeClass('editable');
$(this).closest('td').html('<span class="edit">Edit Info</span>');
// }
// }
// });
return false;
};
});
return false;
});

table tr td {
padding: 12px 15px;
border-bottom: 1px solid #d6d6d6;
box-sizing: border-box;
}

.edit {
color: blue;
cursor: pointer;
}

.editable {
background-color: #FFF;
border: 1px solid #d6d6d6;
}

.button {
background-color: blue;
color: #FFF;
border-radius: 8px;
line-height: 18px;
padding: 5px 8px;
text-align: center;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr data-field="name">
<td>Name</td>
<td class="input">John Doe</td>
<td><span class="edit">Edit Info</span></td>
</tr>
<tr data-field="email">
<td>Email</td>
<td class="input">johndoe@email.com</td>
<td><span class="edit">Edit Info</span></td>
</tr>
</table>





But it only works once. Can anyone explain why?

Here is my fiddle: https://jsfiddle.net/michaelyuen/s7d06ra8/6/

Answer

The problem is because you're removing the .edit element from the DOM and creating a new one. When you remove the original its click handler goes with it and the new copy has no click handler assigned.

The best way to fix this would be to use delegated event handlers, like this:

$(document).on('click', '.edit', function(e) {
  e.preventDefault();
  var $self = $(this);
  var $input = $self.closest('tr').find('.input');

  $input.attr('contenteditable', 'true').addClass('editable');
  $self.closest('td').html('<span class="button">Save</span>');
});

$(document).on('click', '.button', function(e) {
  e.preventDefault();
  var uid = '123';
  var $self = $(this);
  var field = $self.closest('tr').data('field');
  var value = $self.closest('tr').find('.input.editable').text();
  var $input = $self.closest('tr').find('.input');

  if (value.length > 0) {
    var data = {
      edit_info: uid,
      field: field,
      value: value
    }
    console.log(data);

    //	$.ajax({
    //	    type: "POST",
    //      url: "ajax.php",
    //      data: data,
    //      success: function(data){
    //      	if (data == 'success') {
                    $input.attr('contenteditable', 'false').removeClass('editable');
                    $self.closest('td').html('<span class="edit">Edit Info</span>');
    //		    }
    //    	}
    //  });
  };
});
table tr td {
  padding: 12px 15px;
  border-bottom: 1px solid #d6d6d6;
  box-sizing: border-box;
}
.edit {
  color: blue;
  cursor: pointer;
}
.editable {
  background-color: #FFF;
  border: 1px solid #d6d6d6;
}
.button {
  background-color: blue;
  color: #FFF;
  border-radius: 8px;
  line-height: 18px;
  padding: 5px 8px;
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <tr data-field="name">
    <td>Name</td>
    <td class="input">John Doe</td>
    <td><span class="edit">Edit Info</span>
    </td>
  </tr>
  <tr data-field="email">
    <td>Email</td>
    <td class="input">johndoe@email.com</td>
    <td><span class="edit">Edit Info</span>
    </td>
  </tr>
</table>

Also note that I amended your AJAX request to send information in an object, instead of hacking together a querystring. This has the benefit of both being easier to maintain, and also means that jQuery will encode any special characters for you.

Comments