2012-01-26 16 views
7

Normalmente no hago este tipo de pregunta/respuesta, pero pensé que lo haría, ya que he visto esta pregunta más de 20 veces, y ni una sola respuesta en realidad funciona. En resumen, el problema es que si tiene contenido desplazable (overflow: auto; en cualquier parte dentro de un elemento jQuery arrastrable, cuando hace clic y arrastra la barra deslizadora, el contenedor arrastrable principal arrastra consigo. Así que dediqué un tiempo a encontrar una soluciónDeshabilitar el arrastre de jQuery al desplazar el contenido del elemento arrastrable

He aquí un ejemplo de algo de hTML que presentan este problema:

<div class="draggable" style="width:100px;height:100px;"> 
    <div id="content" style="width:80px;height:80px;overflow:auto;"> 
    Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula ut id elit. 
    </div> 
</div> 

La forma típica de inicializar un elemento que se pueda arrastrar, es algo como esto:

$(".draggable").draggable() 

Respuesta

4

La solución es unir al evento de desplazamiento en los elementos de su inicialización, y cualquiera de los elementos de los niños. Luego, cuando cualquiera de los niños invoque un comando de desplazamiento, encuentre todos los elementos primarios que se puedan arrastrar de ese elemento y establezca un elemento de datos desplazado en ese elemento.

En la versión actual de jQuery UI (1.8.16), el evento de inicio siempre comienza cuando se desplaza sobre la barra de desplazamiento y se avanza por el árbol, por lo que esta solución funciona bastante bien en mis pruebas.

$(".draggable").draggable({ 
    start: function() { 
     // if we're scrolling, don't start and cancel drag 
     if ($(this).data("scrolled")) { 
      $(this).data("scrolled", false).trigger("mouseup"); 
      return false; 
     } 
    } 
}).find("*").andSelf().scroll(function() {    
    // bind to the scroll event on current elements, and all children. 
    // we have to bind to all of them, because scroll doesn't propagate. 

    //set a scrolled data variable for any parents that are draggable, so they don't drag on scroll. 
    $(this).parents(".ui-draggable").data("scrolled", true); 

}); 

Para su visualización/escarceos placeres, he incluido una jsfiddle de la cuestión así.

+0

Desafortunadamente, esta respuesta solo funciona si realmente ocurre algún desplazamiento como resultado de un clic en la barra de desplazamiento. Si tuviera que presionar en la barra de desplazamiento sin desplazarse, el código jQuery UI/Draggable todavía comenzará su arrastre.(Intenté esto en el jsfiddle publicado con Chrome 23 Beta, simplemente haga clic en la barra de desplazamiento sin desplazarse) – eleotlecram

+0

Esto requiere escuchar el evento de desplazamiento de "*" (todo) y agregar que el desplazamiento es verdadero para los datos. La otra respuesta es más autónoma y mejor para legibilidad más adelante. – mgwidmann

6

Sugiero una solución basada en una combinación de [1] y la solución proporcionada por PriorityMark. Esta solución funciona de manera más confiable y creo que es un poco más eficiente también.

$(".draggable").draggable({ 
    start: function(event) { 
     var content = $(this).children('.content'); 

     // if we're scrolling, don't start and cancel drag 
     if (event.originalEvent.pageX-content.offset().left > content.innerWidth()) 
     { 
      console.log('should-cancel'); 
      $(this).trigger("mouseup"); 
      return false; 
     } 
    } 
}); 

Para que esto funcione, me ajusté un poco el ejemplo DOM (pero esto no debería ser un problema tan grande):

<div class="draggable" style="width:100px;height:100px;overflow:auto;"> 
    <div class="content" style="width:80px;height:80px;"> 
    Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nullam id dolor id nibh ultricies vehicula ut id elit. 
    </div> 
</div>​ 

Tenga en cuenta que aquí el arrastrable div tiene el desbordamiento, no el contenido div. Para la solución, realmente no importa, pero no quería tener que agregar un nivel Div adicional, ya que no es estrictamente necesario aclarar el punto.

Aquí está el jsfiddle.

[1] - listen for mouse events … except a div's overflow:scroll scrollbar?

+0

gracias funcionó increíble! ¡Rock! – msqar

+1

ohhh funciona para desplazarse verticalmente pero cuando intenta desplazarse horizontalmente se pone micrófonos. ¿Cómo puedo arreglar esto? :( – msqar

+1

esta solución hace que el desplazamiento funcione pero hace que el elemento arrastrable no se pueda fragmentar. Lo intenté en FF21.0 en mac OSX – PowerAktar

1

que estaba buscando este problema y encontró una solución más pequeña que funciona perfectamente para mí y quiero compartirlo. Mi solución es detener la propagación del evento "mousedown" en el elemento secundario/contenido. Sin mousedown significa que no hay arrastre;)

$(".draggable").draggable(); 
$("#content").mousedown(function(event) { 
    event.stopPropagation(); 
}); 
0

Esta es una solución bastante pero tiene un fallo. Una vez configurado para desplazarse, se necesita un segundo arrastre para arrastrar el elemento.

Cuestiones relacionadas