Reputation: 2860
I have a list of rows in a table which I am attempting to make editable when a user clicks on a cell in the table. My plan is to then make AJAX requests to update this data.
Here is an example of my HTML:
<tr>
<td>3</td>
<td class="textFieldCell"><span class="textField" data-question-id="3">Is the instructor aware of their self development and self improvement areas they are working toward as part of their planned delivery and self peer or tutor assessment?</span></td>
<td class="sortOrderFieldCell"><span class="sortOrderField" data-question-id="3">3</span></td>
<td><a href="#" class="deleteQuestion" data-questionid="3">Delete Question</a></td>
</tr>
So the idea here is when a user clicks on the span in the table, it is replaced by an input box where a user can change the data and then the AJAX call is made on the blur. I am perfectly happy with writing the AJAX call but I am having an issue where the box table cell only allows the jQuery to change it to an input field once. Here is a step-bystep description of the issue:
Here is my jQuery:
jQuery('.sortOrderField').click(function() {
var input = jQuery('<input />', {'type': 'text', 'class': 'sortOrderField', 'name': 'aname', 'value': jQuery(this).html()});
jQuery(this).parent().append(input);
jQuery(this).remove();
input.focus();
jQuery('.sortOrderFieldCell input').blur(function() {
var html = "<span class='sortOrderField' data-question-id='3'>" + jQuery(this).val() + "</span>";
jQuery(this).parent().append(html);
jQuery(this).remove();
});
});
Does anybody have any ideas as to why this jQuery only runs once on a table cell?
Upvotes: 0
Views: 2007
Reputation: 101
You are attaching your event to all items in the page that currently have the class sortOrderField.
However, when you do jQuery(this).remove();
you remove the element from the page, and the trigger goes with it.
In order to have the trigger remain, you should attach it to the parent element, using the selector argument. Here is an example:
jquery('table.editableTable').on( 'click', '.sortOrderField', function() {
var input = jQuery('<input />', {'type': 'text', 'class': 'sortOrderField', 'name': 'aname', 'value': jQuery(this).html()});
jQuery(this).parent().append(input);
jQuery(this).remove();
input.focus();
});
jQuery('table.editableTable').on('blur', '.sortOrderFieldCell input', function() {
var html = "<span class='sortOrderField' data-question-id='3'>" + jQuery(this).val() + "</span>";
jQuery(this).parent().append(html);
jQuery(this).remove();
});
This example assumes that your rows are in a table with the class editableTable. This code also assumes that you aren't adding new tables dinamically to the page.
For performance reasons I would recomend that you put these events on the closest parent possible of the elements where the trigger will fire, in order to minimize the work on the bubbling up of events and element searches, but of course this depends on how big is the page and how pressed for performance you are.
Check the jquery .on() documentation for more information.
Upvotes: 0
Reputation: 388416
You need to use event delegation here
jQuery(document).on('click', '.sortOrderField', function() {
var input = jQuery('<input />', {'type': 'text', 'class': 'sortOrderField', 'name': 'aname', 'value': jQuery(this).html()});
jQuery(this).parent().append(input);
jQuery(this).remove();
input.focus();
});
jQuery(document).on('blur', '.sortOrderFieldCell input', function() {
var html = "<span class='sortOrderField' data-question-id='3'>" + jQuery(this).val() + "</span>";
jQuery(this).parent().append(html);
jQuery(this).remove();
});
Demo: Fiddle
Upvotes: 1