2009-08-23 9 views
2

J'ai une liste de draggables connectés à une liste de sortables. Le glisser/déposer fonctionne bien, tout comme le tri. La chose est que, avant que la liste ne soit triée, j'ai besoin de créer un enregistrement dans la base de données (en utilisant des rails). Donc j'utilise $ .post qui fonctionne bien, mais j'ai besoin de changer l'identifiant de l'élément inséré. Je fais cela en changeant l'id de l'élément inséré en utilisant le callback $ .post. Fonctionne bien mais cela arrive APRÈS le tri. Et si vous vous demandez pourquoi je n'ai pas utilisé le rappel d'arrêt draggable c'est parce que c'est la même chose. Voici le code abrégé (supprimé stuff db non pertinente):JQuery draggable callback appelé after sortable de

$("#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); 
}}); 

Le conteneur triable est simple:

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

Il me semble que tous les callbacks sont appelés après le genre. Est-ce vrai? Comment contourner cela si vous avez besoin de mettre à jour le DOM avant le tri? MISE À JOUR: Au cas où ils manqueraient dans les commentaires, voici l'image et les exemples de fichiers illustrant le problème.

Image: http://dl.getdropbox.com/u/1826667/sortable.png Exemples de fichiers: http://dl.getdropbox.com/u/1826667/jquery_callback_order.zip

Il semble donc que les callbacks finissent toujours à la fin de tout autre événement quel que soit l'endroit où ils sont appelés (@ rappel .post avant la mise à jour triables est encore appelé dernier , etc). Je ne pense pas que ce soit un échec dans JQuery (bien que je trouve ça bizarre); J'essaie de faire un certain nombre de messages (qui sont nécessaires car ils sont co-dépendants, créer un enregistrement puis trier) dans un seul coup ce qui n'est peut-être pas la façon de le faire. Je vais essayer de le contourner dans le backend (j'ai quelque chose qui marche presque) donc je considérerai cela comme fermé. Merci à tous ceux qui ont aidé avec le problème. SO règles.

MEGAIMPORTANTUPDATE: Cela fonctionne! Shawn l'a eu (voir la réponse) et je suis encore un peu étourdi. Ça fait quelques jours sur cette chose. Merci encore à tout le monde et surtout à Shawn. Tu gères.

+0

J'ai des difficultés à voir le problème. Est-ce que vous voulez changer, par exemple, # workcenter_43 à # operation_64 avant que l'ordre des sortables ne soit changé? –

+0

C'est vrai. Mais le rappel pour changer l'identifiant est appelé après le changement triable. –

+0

Je ne pense pas qu'il y ait un moyen de faire exactement cela; peut-être que nous pouvons trouver une solution de contournement. Pourquoi est-ce que vous devez appeler cela avant le genre? –

Répondre

2

Aha! Je l'ai. Cette image était juste ce dont j'avais besoin. Voici ce qu'il faut faire:

$("#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(); 
    } 
}}); 
+0

Saints-singes! C'est brillant! Mettez-le dedans et fonctionne parfaitement. C'est toujours bizarre de le voir (j'ai des alertes montrant la commande) mais ça fonctionne PARFAITEMENT! Merci beaucoup. Tu es un génie. –

+1

Il y avait en fait un problème plus important que l'ordre des rappels; c'est la partie "asynchrone" d'AJAX. Ces appels de serveur n'ont aucune garantie sur le moment où ils reviennent; vous en commencez un et votre code continue. Si vous avez quelque chose qui doit arriver après une réponse du serveur (par exemple, votre tri), alors il doit être appelé à partir du rappel. –

0

Avant l'événement de mise à jour, l'événement de démarrage est appelé, vous pouvez l'utiliser.

+0

Ouais, j'ai regardé ça (à peu près tous les rappels en fait). Mais je ne peux pas créer l'enregistrement si l'utilisateur ne dépose pas l'élément sur le triable.:) j'ai fait jouer avec l'idée de le créer et quel que soit le supprimer si inutilisés mais tout semblait tellement mal. –

+0

Avez-vous essayé de l'attacher à l'événement stop() du draggable à la place? –

+0

Ouais, c'est en fait le premier rappel que j'ai utilisé (parce que cela avait plus de sens). Mais cela est également appelé après le tri, donc j'ai commencé à essayer d'injecter les fonctions dans le rappel triable pour forcer l'ordre des rappels. Toujours essayer ... –