SitePoint Sponsor

User Tag List

Results 1 to 9 of 9

Hybrid View

  1. #1
    SitePoint Member
    Join Date
    Jun 2012
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Callback isnt being called...I can't figure out why...Please help spot the bug.

    The book I am learning jQuery from is the sitepoint book called, "jQuery:Novice to Ninja Second Edition". The source code for the "1-up" Notification example script which begins on page 302 of the book is the code that isn't performing the callback. Here is the code:

    Code:
    $(document).ready(function(){
      $('<span>Adding</span>')
        .addClass('adding')
        .insertAfter('.wishlist');
        
      $('.wishlist')
        .click(function(e) {
          doOneUp(this, function() {
            $(this).prev().text('Added');
          });
          e.preventDefault();
        })
    });
    
    function doOneUp(which, callback) {
      $(which)
        .next()
        .show()
        .animate({
          top: "-=50px",
          opacity: "toggle"
        }, 1000,
        function() {
          $(this)
            .css({top: ""})
            .hide('slow', callback) // hey sitepoint users, this is the callback that isn't being called back
            .remove();
        });
    }
    The amount of chaining and anonymous method usage in this example of the book seems over the top. For someone learning jQuery its probably not the best code to learn from. Trying to debug 1 long line of code versus multiple smaller pieces of code seems very difficult. But all that aside I have tried debugging this code in Chrome's debugger/inspector and have been unsuccessful. Can someone spot the bug?

  2. #2
    Under Construction silver trophybronze trophy AussieJohn's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    776
    Mentioned
    11 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ig-88 View Post
    The book I am learning jQuery from is the sitepoint book called, "jQuery:Novice to Ninja Second Edition". The source code for the "1-up" Notification example script which begins on page 302 of the book is the code that isn't performing the callback. Can someone spot the bug?
    It looks like the problem exists around the .remove() on the line after the callback is supposed to be called.

    I made a JS Fiddle with a solution http://jsfiddle.net/GeekyJohn/KV53F/

    The code below also highlights the problem.

    I moved the .remove() call to the callback, so it will remove the "adding" span from there.

    Code JavaScript:
    $(document).ready(function(){
      $('<span>Adding</span>')
        .addClass('adding')
        .insertAfter('.wishlist');
     
      $('.wishlist')
        .click(function(e) {
          doOneUp(this, function() {
            $(this).prev().text('Added').end().remove(); //call the remove over here.
          });
          e.preventDefault();
        })
    });
     
    function doOneUp(which, callback) {
      $(which)
        .next()
        .show()
        .animate({
          top: "-=50px",
          opacity: "toggle"
        }, 1000,
        function() {
          $(this)
            .css({top: ""})
            .hide('slow', callback);
            //.remove(); //problem is around the .remove() being called before the callback can execute
        });
    }&#8203;
    var details = {
    . . web: "afterlight.com.au",
    . . photos: "jvdl.id.au",
    . . psa: "usethelatestversion.com"
    }

  3. #3
    SitePoint Member
    Join Date
    Jun 2012
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey,

    Thanks for your help on this one. I'll give it a shot soon. Do you happen to know why the code doesn't work properly..if so, could you explain it to me what the author did wrong? Im pretty new to JavaScript and jQuery. Is the callback attached to the element that is removed from the document when .remove() is executed...in essence, removing the callback as well? I am just guessing.

    I thought that all callbacks went into a global jQuery queue so that they were not technically part of any element that exists in the document. But again I am just guessing.

  4. #4
    Under Construction silver trophybronze trophy AussieJohn's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    776
    Mentioned
    11 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ig-88 View Post
    Hey,

    Thanks for your help on this one. I'll give it a shot soon. Do you happen to know why the code doesn't work properly..if so, could you explain it to me what the author did wrong? Im pretty new to JavaScript and jQuery. Is the callback attached to the element that is removed from the document when .remove() is executed...in essence, removing the callback as well? I am just guessing.
    That's the gist of it. Without going in to too much detail, actions are performed on an element that is being removed before the script reaches those actions. The order of which things would happen in the callback of the .animate() is:



    1. .css({top: ""}) // set the top position
    2. .hide('slow', callback); //start hiding the element
    3. .remove(); // remove the element
    4. // "hide" finishes (the element has been removed from the DOM though, so the effect never gets to finish)
    5. // the callback for hide is called (but the element has been removed already, )



    The reason this happens is because jQuery doesn't wait for things like animations in the chain to finish before moving on the next item in the chain. It's asynchronous, meaning it simply begins the execution of an item that requires a queue (like animations) and then moves on down the chain. That's why the .remove() is best served being in the callback that finally gets executed.
    Last edited by AussieJohn; Jun 27, 2012 at 22:44. Reason: clarification
    var details = {
    . . web: "afterlight.com.au",
    . . photos: "jvdl.id.au",
    . . psa: "usethelatestversion.com"
    }

  5. #5
    SitePoint Member
    Join Date
    Jun 2012
    Posts
    19
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by AussieJohn View Post
    The reason this happens is because jQuery doesn't wait for things like animations in the chain to finish before moving on the next item in the chain. It's asynchronous, meaning it simply begins the execution of an item that requires a queue (like animations) and then moves on down the chain. That's why the .remove() is best served being in the callback that finally gets executed.
    I have been playing with this bit of a code a couple of hours now and I have discovered that while the jQuery .remove() method gets executed instantly, the .hide() method does not. Therefore, in my opinion the author has made this example overly complex by setting up callbacks that are unnecessary. Just for learning purposes I placed .remove() method in the callback of the .hide() method to test the functionality of the example. It appears it works just as well as any other and seems to make just a bit more sense than having to pass a callback argument to two different methods(passing the buck, or kicking the can down the road). Why put off until tomorrow what you can do today.

    My interpretation makes the anonymous method that's passed in as the 'callback' argument to doOneUp() unnecessary at least for this small example.

    Code:
    function doOneUp(triggerElement, /* no longer need this parameter -> */ callback) {
    				$(triggerElement).next().show(1000)
    					.animate(
    						{
    							opacity: 0,
    							top: "-=50px"
    						},
    						3000
    					).hide('slow',
    						function() {
    							$(this).remove();
    							triggerElement.textContent = 'Added';
    							console.log('Executing callback for .hide();');
    						}
    					);
    			}
    While overly complex examples can probably help you become a better programmer in the long run, they are quite a pain in the beginning.

  6. #6
    Under Construction silver trophybronze trophy AussieJohn's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    776
    Mentioned
    11 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ig-88 View Post
    I have been playing with this bit of a code a couple of hours now and I have discovered that while the jQuery .remove() method gets executed instantly, the .hide() method does not.
    Almost correct . The .hide() method gets executed before the .remove() executes, but the big difference is that .hide() causes an animation. The animation gets put in to the effects queue and won't finish before .remove() is called, because this all happens so quickly it gives the appearance that .hide() is skipped or executed too late. (Because the animation never finishes, so the callback won't be called either.)

    (It's worth noting that even though the original example doesn't have a duration on the .hide(), I could not get the original code to work with or without the duration in .hide())
    var details = {
    . . web: "afterlight.com.au",
    . . photos: "jvdl.id.au",
    . . psa: "usethelatestversion.com"
    }


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •