¿Cómo usar HTML5 arrastrar y soltar en combinación con KnockoutJS?

Parece que no puedo vincularme a eventos de arrastrar y soltar html5.

A continuación, se muestra un ejemplo de una plantilla:

<script id="tabsTemplate" type="text/html">
    <div class="dropzone" for="tab"
        data-bind="event:{dragover: function(event){event.preventDefault();},
                          dragenter: function(event){event.target.addClass('dragover'); event.preventDefault();},
                          dragleave: function(event){event.target.removeClass('dragover'); event.preventDefault();}}
                          drop: function(event){console.log('blahblah!')}"></div>
    <h1 class="tab" draggable="true"
      data-bind="attr: {selected: $data.name === $item.selected()},
                 click: function(){$item.selected($data.name)},
                 event:{ dragstart: function(event){console.log('blah!!')},
                         dragend: function(event){document.getElementsByClassName('dragover')[0].removeClass('dragover')}}">
        ${name}

        <img src="icons/close-black.png" class="close button" role="button"
            data-bind="click: function(e){$item.close($data)}">
    </h1>
</script>

Lo que tengo debería funcionar como se esperaba ... y lo hace siempre que los haga normales en línea. Sin embargo, ¡las otras fijaciones no funcionan!

Recibo este mensaje de error:

Error de sintaxis no detectado: token inesperado '||' jquery-tmpl.js: 10

¿Que está pasando aqui? ¿Hay algo que esté haciendo mal?

preguntado el 28 de agosto de 11 a las 00:08

Si no ha implementado el dragstart event ¿cómo está determinando si está funcionando o no? Si no lo haces setData entonces no se producirá ningún arrastre. -

Todo lo que tienes que hacer es poner 'draggable: true' y puedes arrastrar. Mi controlador dragend no necesita conocer ningún dato y funciona bien cuando está en línea ... pero no cuando está en un enlace. -

La forma en que puedo decir es que la clase 'dragover' que se agrega en dragenter cambia el CSS considerablemente. Dragend debería eliminar la clase de la última zona de lanzamiento para activar el evento dragenter. En la encuadernación no lo hace ... en línea lo hace. -

He Acabo de revisarlo - Chrome funciona, Firefox requiere un dragstart. Por lo tanto, asumo que estás usando Chrome y este no es tu problema. Descargaré knockout.js y jugaré con él. -

3 Respuestas

OK, lo he resuelto. Parece que me perdí en la documentación donde decía que en knockout, por defecto hace que todos los eventos eviten default / return false. Así que todo lo que tenía que hacer era hacer que mi controlador dragstart volviera a ser verdadero, y ahora funciona. ¡¡Uf!!

Respondido 29 ago 11, 14:08

Para aquellos (como yo) que necesitan un SSCCE funcionando; la sugerencia de [cybermotron] de la solución sigue, también corrige un problema donde los manejadores esperan parámetros datos y evento.

http://jsfiddle.net/marrok/m63aJ/

HTML

<script type="application/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

<ul id="people" data-bind='template: { name: "personTmpl", foreach: people }'>
</ul>
<div class="trash" data-bind ="visible:dragging, event:{
       dragover: function(data, event){
          event.preventDefault();
       },
       drop: function(data, event){
          console.log('trash', $root.drag_start_index())
          $root.trash($root.drag_start_index())     
          event.preventDefault();
       }
}"> <span>DELETE</span> </div> 

<script id="personTmpl" type="text/html">
    <li class="draggable" draggable="true" data-bind="event:{
      dragstart:   function(data, event){ 
                    $(event.target).addClass('dragSource')
                    $root.drag_start_index($index());
                    return $(event.target).hasClass('draggable');},    

       dragend:   function(data, event){  
                   $root.drag_start_index(-1);
                   $(event.target).removeClass('dragSource')
                   return true;
       },    
       dragover:  function(data, event){event.preventDefault();},
       dragenter: function(data, event){
                $root.drag_target_index($index());
                var element = $(event.target)
                if(element.hasClass('draggable'))
                     element.toggleClass('dragover'); 
                event.preventDefault();
    },
       dragleave: function(data, event, $index){
                var element = $(event.target)
                if(element.hasClass('draggable'))
                     element.toggleClass('dragover');
                event.preventDefault();
    },
       drop: function(data, event){
                $(event.target).removeClass('dragover'); 
                console.log('swap', $root.drag_start_index(),  $root.drag_target_index() )
                $root.swap($root.drag_start_index(),  $root.drag_target_index())
               }
             }">

        <span data-bind='text: name'></span>
    </li>
</script>

Eliminatoria

var Person = function(name) {
    this.name = ko.observable(name);

};

var PeopleModel = function() {
    var self = this;

    self.drag_start_index = ko.observable();
    self.drag_target_index = ko.observable();
    self.dragging = ko.computed(function() {
        return self.drag_start_index() >= 0;
    });
    self.people = ko.observableArray([
        new Person("Oleh"), new Person("Nick C."), new Person("Don"), new Person("Ted"), new Person("Ben"), new Person("Joe"), new Person("Ali"), new Person("Ken"), new Person("Doug"), new Person("Ann"), new Person("Eve"), new Person("Hal")]);


    self.trash = function(index) {
        self.people.splice(index, 1)
    }
    self.swap = function(from, to) {
        if (to > self.people().length - 1 || to < 0) return;

        var fromObj = self.people()[from];
        var toObj = self.people()[to];
        self.people()[to] = fromObj;
        self.people()[from] = toObj;
        self.people.valueHasMutated()
    }
};
ko.applyBindings(new PeopleModel());​

respondido 28 nov., 12:22

¡Buen violín que llegaste allí, muy útil y conciso! - Arroz Allen

Es posible que tenga el mismo problema que se mencionó aquí, aunque se refiere a plantillas anidadas:

advertencia

Si está pasando templateOptions al enlace de plantilla desde una plantilla anidada (por lo tanto, especificando un enlace de plantilla desde dentro de una plantilla), preste especial atención a su sintaxis. Encontrará un problema si su enlace se ve así:

 <div data-bind="template: { name: 'items', data: newItems, templateOptions: { header: “New Items!”}}"></div> 

El complemento jQuery Templates se confunde con el}} al final de su enlace, ya que es parte de su sintaxis. Agregar un espacio entre los frenillos funcionará bien. Con suerte, esto evitará que alguien sienta una frustración innecesaria.

 <div data-bind="template: { name: 'items', data: newItems, templateOptions: { header: “New Items!”} }"></div>

Respondido 28 ago 11, 11:08

Wow ... no había pensado en jquery template confundido por mi uso desconsiderado de}} ... bueno, los arreglé y ahora ya no recibo el error ... y ahora, cuando comienzo a arrastrar, la consola dice "¡bla!", tal como lo pedí ... ¡sin embargo, el elemento no se arrastra ahora! Registra el evento dragstart, pero el elemento permanece quieto ... y su enlace parece estar roto. - cybermotron

enlace arreglado ahora :) Buen artículo, pero no es lo que estaba buscando para esto. - cybermotron

Me doy cuenta de que :) Sin embargo, no he tenido tiempo de mirarlo más de cerca. - Byte mayor

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.