2012-10-07 18 views
9

Estoy trabajando en un small jQuery plugin que imita el comportamiento jQuery UI arrastrable/droppable con eventos nativos de arrastrar y soltar HTML5.HTML5 Arrastrar y soltar eventos y compatibilidad con el navegador setDragImage

Una característica que me gustaría agregar es la capacidad de especificar el nodo que servirá como el proxy de arrastre.

Hice un poco de investigación, y according to MDN, para hacer esto requiere el uso de setDragImage(), pasando una imagen o un elemento.
¿Cuál es el soporte para setDragImage en diferentes navegadores?

Me he dado cuenta de que hay un complemento llamado jquery.event.drag que lleva un problema diferente del esperado.
¿Esta característica me obligaría a realizar algún tipo de solución como la del plugin anterior, o debería ser posible de fábrica en la mayoría o todos los navegadores que usan setDragImage?

EDITAR

Después de jugar un poco con esta funcionalidad, parecería que esta función es bastante limitada.

Además de contar con ningún apoyo en un buen número de navegadores, usando un elemento DOM arbitrario como el ayudante exige que sea en el árbol DOM y visible, y lo que tiene el propio elemento en el cuerpo, y una copia de como el controlador. Esto es principalmente no deseado para este tipo de complemento.

Además, el procesamiento también es problemático incluso cuando se cumplen los términos adecuados. Al intentar crear un helper desde <span>TEST</span>, el helper solo mostró un rectángulo blanco con las dimensiones del span.

Son estos problemas que se esperaban de acuerdo con las especificaciones? ¿Podrían ser corregidos en el código o requerirían una solución alternativa?

Respuesta

10

setDragImage es IMO una característica vital para cualquier caso de uso no trivial de arrastrar y soltar. por ejemplo, considere una lista de selección múltiple donde un arrastre debe incluir todos los elementos seleccionados y no solo la fila en la que se realizó el gesto de arrastre. es extraño que lo que desea establecer debe ser visible en el DOM, pero lo que es peor es que este método no está implementado en IE a partir de la versión 11.

Sin embargo, con un poco de esfuerzo pude hacer que funcione de manera razonablemente satisfactoria. El nodo de imagen de arrastre personalizado se puede eliminar del DOM en una función de tiempo de espera 0. así que agrégalo al DOM en dragstart y luego úsalo en la imagen de arrastre y luego quítalo. Esto funciona perfectamente en FF, pero en Chrome el nodo de la imagen de arrastre parpadeará antes de que se agote el tiempo de espera. Una forma de evitar esto es colocarlo de manera tal que la imagen de arrastre generada por el navegador aparezca exactamente en el mismo lugar, esto no es tan malo como suena ya que puede controlar la posición de la imagen de arrastre personalizada relativa al cursor.

Estaba jugando con esto recientemente y también pude hacerlo funcionar en IE. el truco es conseguir que IE arrastre el nodo de imagen de arrastre personalizado y no el nodo en el que se inició el dragstart. puedes hacer esto con el método específico IE DragDrop().

Lo último a tener en cuenta es que en Windows hay un límite de 300px en el ancho del nodo de imagen de arrastre personalizado, esto aplica a todos los juegos de arrastre, no solo al nodo personalizado en realidad. por lo que el navegador aplica un fuerte gradiente radial si la imagen de arrastre es demasiado grande.

http://jsfiddle.net/stevendwood/akScu/21/

$(function() { 

(function($) { 
    var isIE = (typeof document.createElement("span").dragDrop === "function"); 
    $.fn.customDragImage = function(options) { 

     var offsetX = options.offsetX || 0, 
      offsetY = options.offsetY || 0; 

     var createDragImage = function($node, x, y) { 
      var $img = $(options.createDragImage($node)); 
      $img.css({ 
       "top": Math.max(0, y-offsetY)+"px", 
       "left": Math.max(0, x-offsetX)+"px", 
       "position": "absolute", 
       "pointerEvents": "none" 
      }).appendTo(document.body); 

      setTimeout(function() { 
       $img.remove(); 
      }); 

      return $img[0]; 
     }; 

     if (isIE) { 
      $(this).on("mousedown", function(e) { 
       var originalEvent = e.originalEvent, 
        node = createDragImage($(this), originalEvent.pageX, originalEvent.pageY); 

       node.dragDrop(); 
      }); 
     } 

     $(this).on("dragstart", function(e) { 

      var originalEvent = e.originalEvent, 
       dt = originalEvent.dataTransfer; 

      if (typeof dt.setDragImage === "function") { 
       node = createDragImage($(this), originalEvent.pageX, originalEvent.pageY); 
       dt.setDragImage(node, offsetX, offsetY); 
      } 
     }); 

     return this; 
    }; 
}) (jQuery); 



$("[draggable='true']").customDragImage({ 
    offsetX: 50, 
    offsetY: 50, 
    createDragImage: function($node) { 
     return $node.clone().html("I'm a custom DOM node/drag image").css("backgroundColor", "orange"); 
    } 
}).on("dragstart", function(e) { 
    e.originalEvent.dataTransfer.setData("Text", "Foo"); 
}); 

}); 
+1

fantástica prueba de concepto y una solución brillante! – GeReV

+1

Esta solución alternativa sigue siendo válida para IE Edge, que tampoco implementa setDragImage. –

Cuestiones relacionadas