0

I'm creating a dynamic todo list. The list is downloaded from a local database and displayed in a table. At each todo there's a submit-button which you can press and the todo is supposed to register in the database as "done". In my code this is done through a variable called status in which a value of 1 is done, and a value of 0 is undone.

My problem is that you can press any button and all works well; new status is sent to a PHP script, which in turn modifies the status value in the database. Then the webpage automatically updates the display table. But if you try once more, on any of the other buttons, it doesn't work. You'll have to reload the webpage for any of the other buttons to work.

Here's my Jquery/AJAX code:

        $(document).ready( function() {
            $('#todo_display_table input[type="submit"]').click(function(evt) {
               evt.preventDefault();

               var todo_id = $(this).val();
               //document.write(todo_id);//debug
               $.when(changeTodoStatusTo(1, todo_id)).then(updateTodoDisplay);
            });
        });

        function updateTodoDisplay() {
            $.post("./daily_todo_display.php", null, replaceTbodyHTML);
        }

        function replaceTbodyHTML(data) {
            $('#todo_display_table tbody').html(data);
        }

        function changeTodoStatusTo(newStatus, todo_id) {
            //Send til phpscript som lagrer ny status i databasen
            var parameters = {
                todo_id: todo_id,
                newStatus: newStatus
            };

            return $.post("./daily_todo_change_todo_status.php", parameters); //, printDebugInfo);
        }

I can post my PHP-scripts as well, but I have tested these separately and they seem to work. Again, all of the functionality on my page works fine, but they seem to stop working after you clicked one time.

I have checked the database and the status value only update itself the on first try(first click of any of the buttons), which would indicate that the problem lies in either the click() function or in the changeTodoStatusTo() function. Thnx for any help, and don't hesitate to ask for more information =)

Einar
  • 185
  • 1
  • 2
  • 13

6 Answers6

3

You shouldn't use the live function of jQuery:

As of jQuery 1.7, the .live() method is deprecated. Use .on() to attach event handlers. Users of older versions of jQuery should use .delegate() in preference to .live().

This method provides a means to attach delegated event handlers to the document element of a page, which simplifies the use of event handlers when content is dynamically added to a page. See the discussion of direct versus delegated events in the .on() method for more information.

jQuery live documentation

As the documentation states, use .on() instead. It works the same way as .live() :)

Community
  • 1
  • 1
Andreas Stokholm
  • 1,677
  • 1
  • 12
  • 17
1

Are you recreating the submit buttons when you update??? It is hard to tell without seeing all of your code. Have you tried changing this:

$('#todo_display_table input[type="submit"]').click(function(evt) {

to this:

$('#todo_display_table input[type="submit"]').live('click', function(evt) {

see this if applicable: http://api.jquery.com/live/

bygrace
  • 5,868
  • 1
  • 31
  • 58
  • Just to explain the change a bit more, when you bind a click event like this $(...).click() then it applies to all items currently on the page. Any new items that match that selector that are added to the page will not have the click event bound on them. If you do this $(...).live('click') then the listener will automatically be bound to any new items that match that selector. In this instance, if you are recreating the submit buttons via ajax then you need to use "live". – bygrace May 21 '12 at 18:10
  • It worked! Really helpful answer with a good explanation, thnx ;) – Einar May 21 '12 at 18:42
  • 1
    @Einar Please have a look at the documentation for the live function. You should not use it anymore. – Andreas Stokholm May 21 '12 at 18:45
  • True, I should start using "on". Live has always worked so I haven't bother to change. I found this to be a good explanation. Its a bit clearer/concise than the jquery documentation: http://stackoverflow.com/questions/8065305/whats-the-difference-between-on-and-live-or-bind – bygrace May 21 '12 at 18:50
  • Using on() now ;) But a little disapointed that the selector doesn't go $(here) with the on() function. But thx, to both of you, it works smoothly now =) – Einar May 21 '12 at 18:57
0

I'm guessing you're losing the click event code when you update the html() of the #todo_display_table. Try live() instead

$('#todo_display_table input[type="submit"]').live('click', function(evt) {
Aaron W.
  • 9,254
  • 2
  • 34
  • 45
0

This is a classic case of browser caching. I experienced the same effect awhile back. One way out would be to invoke all your posts as such:

$.post("./daily_todo_change_todo_status.php?id=" + (count++), parameters);

Within your php script, just ignore the id component. By doing it this way, the browser will generate a new string each time and it won't think that it was calling on the older cached page.

Hope it helped :) Cheers!

Vern
  • 2,393
  • 1
  • 15
  • 18
0

It sounds like you're facing some issues with the browser caching the response of your POST requests. This is a common problem with some browsers. You should know that browsers cache content based on the URI, not the actual file. In other words, the query string is included. One workaround to avoid caching the requests is to use a slightly different URI each time:

$.post("./daily_todo_change_todo_status.php?t="+new Date().getTime(), null, callbackFn);

By inserting the current timestamp, you're guaranteed to always make a fresh request to the server, instead of the browser just pulling cached data in lieu of a request.

In addition, in your second POST request, you are attempting to return data. This function is designed to return the response and process it inside a callback function, asynchronously, so that you don't block execution on the page.

However, I see you have a comment there that it's for debugging information, so hopefully this is something you'd remove in production.

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
0

From the code I can see, your event handling seems to be just fine. However, you are most likely losing the events when replaceTbodyHTML is called. You could just try running the code from the onload again when you update. For example,

function addListeners() {
    $('#todo_display_table input[type="submit"]').click(function(evt) {
        evt.preventDefault();

        var todo_id = $(this).val();
        //document.write(todo_id);//debug
        $.when(changeTodoStatusTo(1, todo_id)).then(updateTodoDisplay);
    });
}

$(document).ready(addListeners);

And then at the end of replaceTbodyHTML add addListeners();

dpk2442
  • 701
  • 3
  • 8