2012-05-04 10 views
7

que tienen una plantilla estándar en un archivo HTML como:cómo desencadenar JQuery .draggable() en elementos creados por plantillas?

<template name="cards"> 
    {{#each all_cards}} 
    {{> card_item}} 
    {{/each}} 
</template> 
<template name="card_item"> 
    <div class="card" style="left:{{position.x}}px; top:{{position.y}}px"> 
    {{title}} 
    </div> 
</template> 

Quiero tener las tarjetas (CSS selector de .card) se convierten en arrastrable con jQuery. Ahora, dado que Meteor actualiza automágicamente el DOM utilizando la plantilla, ¿cuándo y cómo sé dónde llamar a .draggable() en qué?

EDIT: Esto es lo que va mi solución que hace que los movimientos pendientes en otro cliente visibles con una animación oscilante (utilizando CSS3):

Template.card_item.events = { 
'mouseover .card': function (e) { 
    var $target = $(e.target); 
    var $cardContainer = $target.hasClass('card') ? $target : $target.parents('.card');  
    $cardContainer.draggable({containment: "parent", distance: 3}); 
}, 
'dragstart .card': function (e) { 
    Session.set("dragging_id", e.target.id); 
    $(e.target).addClass("drag"); 
    pos = $(e.target).position(); 
    Events.insert({type: "dragstart", id:e.target.id, left: pos.left, top: pos.top});  
}, 
'dragstop .card': function (e) { 
    pos = $(e.target).position(); 
    Events.insert({type: "dragstop", id:e.target.id, left: pos.left, top: pos.top});   
    Cards.update(e.target.id, {$set: {left:pos.left, top:pos.top}}); 
    Session.set("dragging_id", null); 
} 
} 

Events.find().observe({ 
added: function(event) { 
    if (event.type == "dragstart" && !Session.equals("dragging_id", event.id)) { 
     $("#"+event.id).draggable({disabled: true}); 
     $("#"+event.id).addClass("wobble");    
    } 
    if (event.type == "dragstop" && !Session.equals("dragging_id", event.id)) { 
     $("#"+event.id).animate({left: event.left, top: event.top}, 250);   
     Events.remove({id:this.id}); 
     $("#"+event.id).draggable({disabled: false}); 
    } 
} 
}); 
+1

Use 'Meteor.defer', no está en la documentación, pero esta pregunta lo explica. Lo estoy usando para hacer una lista ordenable en este momento y funciona bien. http://stackoverflow.com/questions/10109788/callback-after-the-dom-was-updated-in-meteor-js – lashleigh

+0

¡Gracias, lo comprobaré! - ¡Genial, esto funciona por montones! –

+0

Saludos, eres bienvenido. Además, aprendí que meteor.defer es solo un contenedor para setTimeout, escribe 'Meteor.defer' en la consola sin argumentos para ver a qué me refiero. – lashleigh

Respuesta

6

EDIT: Este enfoque no parece funcionar en el último versiones de Meteor, por ejemplo v0.5.0. Ver mi comment a continuación.

¡Parece que estamos trabajando en cosas similares! Tengo a working proof of concept for a simple Magic: The Gathering app. Así es como he arrastrando implementado en la actualidad

En una sección <head> en uno de los archivos HTML, incluye la secuencia de comandos de jQuery UI:

<script src="jquery-ui-1.8.20.custom.min.js"></script> 

Luego, en un archivo js, ​​hacen elementos de seguro se convierten en arrastrable pasar el ratón (nota: esto es sub-óptimo en pantallas táctiles, ya que requiere dos toques para arrastrar ... estoy buscando una solución mejor pantalla táctil):

Template.card_item.events['mouseover .card, touchstart .card'] = function (e) { 
    var $target = $(e.target); 
    if (!$target.data('isDraggable')) { 
     $target.data('isDraggable', true).draggable(); 
    } 
}; 

Y, por último, manejar el drag and dragstop events:

var prevDraggedTime = 0 

Template.card_item.events['drag .card'] = function (e) { 
    // get the cardId from e 
    var now = new Date().getTime(); 
    var position; 

    if (now - prevDraggedTime > 250) { 
     position = $(e.target).position(); 
     Cards.update(cardId, {$set: {x: position.top, y: position.left}}); 
     prevDraggedTime = now; 
    } 
} 

Template.card_item.events['dragstop .card'] = function (e) { 
    // get the cardId from e 
    var position = $(e.target).position(); 
    Cards.update(cardId, {$set: {x: position.top, y: position.left}}); 
} 
+0

No creo que actualizar en 'arrastre' sea una buena idea. Eso podría ser cientos de actualizaciones incluso para un pequeño arrastre. Simplemente actualice en dragend y use una transformación css3 para mover las cosas sin problemas a otros clientes. – lashleigh

+0

Sí, esto fue solo para demostrar el concepto. En mi código actual, estoy actualizando la posición en 'dragstop', y luego una vez cada 250ms en' drag'. – Emmett

+0

Genial, eso tiene mucho más sentido. Sin embargo, creo que valdría la pena decirlo en tu respuesta. – lashleigh

Cuestiones relacionadas