James
James

Reputation: 2860

jQuery onClick only runs once on table cell

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:

  1. A user cliks on the table cell, which works fine and the span is replaced by an input box.
  2. The user then clicks off of the input box which turns the input box into a span with no issues.
  3. The problem is here, if the user tries to click back onto that same table cell to edit it again the jQuery doesn't run.

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

Answers (2)

Luis Carvalho
Luis Carvalho

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

Arun P Johny
Arun P Johny

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

Related Questions