tags:

views:

597

answers:

2

I have a list of draggables connected to a list of sortables. The drag/drop works fine as does the sorting. The thing is that before the list gets sorted, I need to create a record in the DB (using rails). So I use $.post which works fine, but I need to change the the id of the inserted element. I do this by changing the id of the inserted element using the $.post callback. Works fine but it happens AFTER the sort. And if you're wondering why I didn't use the draggable stop callback it's because is does the same thing. Here's the abbreviated code (removed irrelevant db stuff):

    $("#operations_container").sortable({items:'.process_small', axis:'y', update: function(ev,ui) {
 if (ui.item.attr('id').match("workcenter"))
 {
  $.post('/operations', 'fancyrailspoststuffignore', function(data) {
     $("#operations_container > #workcenter_" + workcenterid).attr("id", "operation_" + data.operation.id);
     }, "json");
 } 
 $.post('/jobs/sort/<%= @job.id %>', 'morefancyschamncyrailsjunk);
}});

The sortable container is simple:

<div id="operations_container" class="in_grid">
</div>

So it appears to me that all callbacks are called after the sort. Is this true? How do you get around this if you need to update the DOM before the sort?

UPDATE: In case they get missed in the comments, here are the image and sample files illustrating the problem.

Image : http://dl.getdropbox.com/u/1826667/sortable.png Sample files: http://dl.getdropbox.com/u/1826667/jquery%5Fcallback%5Forder.zip

So it appears that the callbacks always end up at the end of any other events regardless of where they are called (@.post callback before sortable update is still called last, etc). I don't think it's a failing in JQuery (although I do find it odd); I AM trying to do a number of posts (which are required since they are co-dependent;create a record then sort) in the one go which is perhaps not the way to do it. I'll try and work around it in the backend (I have something almost working) so I'll consider this closed. Thanks to everyone who helped with the problem. SO rules.

MEGAIMPORTANTUPDATE: It's working! Shawn got it (see answer) and I'm still a bit giddy. It's been a few days on this thing. Thanks again to everyone and especially Shawn. You rock.

A: 

Before update event, the start event is called, you can use it.

Thinker
Yeah, I looked at that (pretty much every callback actually). But I can't create the record if the user doesn't drop the element on the sortable. :)I did toy with the idea of creating it regardless and then deleting it if unused but that just seemed soooo wrong.
Sven Schott
Did you try attaching it to the stop() event of the draggable instead?
Shawn J. Goff
Yeah, that's actually the first callback I used (cause it made more sense). But that gets called after the sort as well so I started to try and inject the functions into the sortable callback to force the order of the callbacks. Still trying...
Sven Schott
I've put together a sample HTML page to illustrate the issue. I think my app is clouding the problem. http://dl.getdropbox.com/u/1826667/jquery_callback_order.zip
Sven Schott
If it's only an issue of the order you call those functions, then http://jsbin.com/ufibo/edit would work fine. However, I seems that something in your app is required to do something before the sort. I don't think we can do that unless we have the user add the item then sort it after. So I'm wondering why the app needs to do something before the sort to see if we can work around that part.
Shawn J. Goff
Damn. I eventually came to the same conclusion. I tried to do the creation on the fly in rails but I lose the sort order because of the serialization. Well, I'll just have to find another way. Thanks for all the help anyway. I appreciate it.
Sven Schott
+2  A: 

Aha! Got it. That picture was just what I needed. Here's what to do:

$("#operations_container").sortable({items:'.process_small', axis:'y', update: function(ev,ui) {
    var sortDbTable = function(){
        $.post('/jobs/sort/<%= @job.id %>', 'morefancyschamncyrailsjunk);
    }
    if (ui.item.attr('id').match("workcenter"))
    {
            $.post('/operations', 'fancyrailspoststuffignore', function(data) {
                                    $("#operations_container > #workcenter_" + workcenterid).attr("id", "operation_" + data.operation.id); //is there any reason you're not using the ui.item.attr("id",...) here?
                                    sortDbTable(); //this will make sure id is changed before DB sort
                                    }, "json");
    } else { //else not absolutely needed, but will make sure it's not unnecessarily sorted again
        sortDbTable();
    }
}});
Shawn J. Goff
Holy monkeys! That's brilliant! Put it in and works perfectly. It's still weird to see it (I have alerts showing the order) but it works PERFECTLY! Thank you so much. You're a genius.
Sven Schott
There was actually a bigger issue than just the order of the callbacks; it's the "asynchronous" part of AJAX. Those server calls have no guarantee about when they return; you start one and your code continues. If you have something that must happen after a response from the server (for instance, your sort), then it must be called from the callback.
Shawn J. Goff