views:

1158

answers:

2

I am using a javascript var to control the running of an ajax call. The call is triggered from a click event (on "#week_tag" div)and only needs to be run once per page load. The same click event also toggles the display of the sliding pane ("#week_summary") where the data from the ajax call is shown.

In the example below, I'm trying to use a variable and an if statement to prohibit the ajax call from being called when the user clicks the "#week_tag" div a second time to close the sliding pane. The var status is set to "before" when the page is loaded, and set to "after" once the ajax call is made. If the var status is equal to "before", the call is run, else the "#week_summary" is just toggled. It isn't working because I don't know how to give the var "status" a second value of "after". Any ideas?

$(document).ready(function(){
    var status = "before";
    alert("before:"+status);

    $('#week_tag').click(function(){
        if(status =="before"){
            alert("afterclick:"+status);
            var form_date_set = $("input[name='date_set']").val();

            $.post("/tortus/index.php/daylog/build_summary",
                {date_set:form_date_set}, 
                function(html){
         $("#week_summary").html(html);

            var status = "after";
            });
        }

        $('#week_summary').toggle('blind');

        alert("after:"+status);

        });

     });
+2  A: 

That's because you are declaring a new variable inside the callback function, giving it local scope. If you remove the var from the callback function, it should work as expected.

 $.post("/tortus/index.php/daylog/build_summary",
            {date_set:form_date_set}, 
            function(html){
               $("#week_summary").html(html);

               status = "after";
               alert("status: " + status);
        });

EDIT: And of course, as stated in the comment below, since the call is asynch, you will need to alert the status on the callback as well. Or create a new onclick event on some random element, that will simply display the status:

$(document).ready({
   var status = "before"
   ...
   //your previous onclick event here
   ...
   $("#newElm").click(function() {
      alert("status: " + status);
   });
});
peirix
That won't solve it, I believe. The problem is that 'status' will keep whatever value it was bound to when the closure was created, even when it gets changed outside of the closure.
KaptajnKold
also the ajax call is asynch therefore the alert will always be before
redsquare
@KaptajnKold: Since the variable is created outside the ajax function closure, it will be available for all functions inside the document.ready function.
peirix
Yes, I misstated the problem. The problem is this: Changing thevalue of the variable inside the closure won't affect it's value outside. They are effectively different variables who happen to have the same value to begin with.
KaptajnKold
Oops. Turns out I'm wrong. I would have expected this function function() {var b = 2; c = function() { b = 3; }; c(); return b; } to return 2, but in fact it returns 3.
KaptajnKold
And that's because c() is a function inside the same closure as b is instansiated, which means c() has access to the same b variable.
peirix
+1  A: 

If you want your click handler to run only once, use the .one method to bind your handler. This guarantees it will only be called once, as your handler unbound automatically as the event takes place, just before running your code. See the .one documentation on docs.jquery.com.

Example usage:

$('#week_tag').one('click', function() {
    // This code will only be run once, after #week_tag got clicked on.  
});

Using this method you don't need to track the state at all, jQuery takes care of this for you.

Martijn Pieters