2012-08-23 11 views
6

Tengo el siguiente:Sólo hay una gota de elemento que se ve

Estoy tratando de configurarlo de manera que cuando se arrastre el artículo, sólo se cae al elemento div que se puede ver, y es no cubierto.

por lo que utiliza este JS:

$(".draggable").draggable({ 
    helper: "clone" 
}) 
$("#bottom, .draggable").droppable({ 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 
     $this.append($dragged.clone()); 
    }, 
    hoverClass: "dragHover" 
})​ 

Pero cae en el elemento ambos lugares a pesar de que sólo una de las zonas de arrastre es no visible!

¿Cómo lo arreglo para que esto no ocurra ?

violín: http://jsfiddle.net/maniator/Wp4LU/


Información complementaria para recrear la página sin el violín:

HTML:

<div id="top"> 
    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 

    <div class="draggable"> 
     Lorem ipsum dolor sit amet 
    </div> 
    </div> 

    <div id="bottom"></div> 

CSS:

.draggable { 
    border: 1px solid green; 
    background: white; 
    padding: 5px; 
} 

.dragHover{ 
    background: blue; 
} 

#top { 
    height: 500px; 
    overflow-y: scroll; 
} 
#bottom { 
    height: 150px; 
    overflow-y: scroll; 
    border: red solid 4px; 
} 

+0

Dado que no resolvió el problema en el servidor en vivo, aquí hay un [violín] (http://jsfiddle.net/ult_combo/Wp4LU/18/) usando la propiedad deshabilitada para imitar un 'event.stopImmediatePropagation' para otros widgets UI, con suerte se puede mejorar si no se encuentra una mejor manera. –

+0

@Neal ¿Crees que no podemos usar alguna propiedad de jquery como $ this.is (": visible")? No sé mucho sobre jquery pero puedes decir que es un intento de un novato – Moons

Respuesta

2

Pruebe la configuración con la función accept. The working demo.

$("#bottom, .draggable").droppable({ 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 
     $this.append($dragged.clone()); 
    }, 
    accept: function() { 
     var $this = $(this), divTop= $("#top"); 
     if ($this.is(".draggable")) { 
      return $this.offset().top < divTop.offset().top + divTop.height() ; 
     } 
     return true; 
    }, 
    hoverClass: "dragHover" 
})​;​ 
+0

Santa maravilla^_^esto parece estar funcionando :-). Tengo que probarlo un poco más :-D. Muchas gracias! – Neal

2

Si te tengo derecho - éste debe resolver su problema - http://jsfiddle.net/Wp4LU/60/ También se podría escribir la función aceptar por encargo - http://jqueryui.com/demos/droppable/#option-accept

Código:

var draggableList = $('#top'); 

$(".draggable").draggable({ 
    helper: "clone" 
}); 
$("#bottom, .draggable").droppable({ 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 

     if ($this.hasClass("draggable")) { 
      if ($this.position().top >= draggableList.height() || 
       $this.position().top + $this.outerHeight() >= 
       draggableList.height()) 
       return; 
     } 

     $this.append($dragged.clone()); 
    }, 
    hoverClass: "dragHover" 
})​;​ 
+0

Esto funciona muy bien en el violín ... pero no parece estar funcionando en mi código real (que se ve un poco diferente) ... – Neal

0

Según las fuentes (jquery.ui.droppable.js), la operación de soltar buscará cada droppable elegible y aplicará la función de soltar a cada uno que se cruza con ella:

drop: function(draggable, event) { 

    var dropped = false; 
    $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { 

     if(!this.options) return; 
     if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) 
      dropped = this._drop.call(this, event) || dropped; 

(Las versiones anteriores tenían la última condición "O" invertida, por lo que solo se aplicaría a una sola cuenta que se pueda quitar. Pruebe su violín usando jQuery 1.5.2/jQuery UI 1.8.9, y vea que solo cae en un elemento, aunque sea el "incorrecto" ...)

Y cada modo de tolerancia actualmente implementado en la función $.ui.intersect solamente tener en cuenta el (x, y) las coordenadas:

switch (toleranceMode) { 
    case 'fit': 
     return (l <= x1 && x2 <= r 
      && t <= y1 && y2 <= b); 
     break; 
    case 'intersect': 
     return (l < x1 + (draggable.helperProportions.width/2) // Right Half 
      && x2 - (draggable.helperProportions.width/2) < r // Left Half 
      && t < y1 + (draggable.helperProportions.height/2) // Bottom Half 
      && y2 - (draggable.helperProportions.height/2) < b); // Top Half 
     break; 
    ... 

por lo tanto, a menos que alguien añade un modo de tolerancia conscientes z-index, su única opción es trabajar en torno al tema de alguna manera. Yo sugeriría primera adición de todos los candidatos lanzables a un conjunto y, cuando es el momento de caer, seleccione sólo el que es "más cercano" a la pantalla:

$("#bottom, .draggable").droppable({ 
    over: function(event, ui) { 
     if (!ui.draggable.data("drop-candidates")) 
      ui.draggable.data("drop-candidates",[]); 
     ui.draggable.data("drop-candidates").push(this); 
    }, 
    out: function(event, ui) { 
     var that = this, 
      candidates = ui.draggable.data("drop-candidates") || []; 
     ui.draggable.data("drop-candidates", $.grep(candidates, function(e) { 
      return e != that; 
     }); 
    }, 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 
     var candidates = $.data("drop-candidates").sort(closestToScreen); 
     if (candidates[0] == this) 
      $this.append($dragged.clone()); 
    }, 
    hoverClass: "dragHover" 
})​ 

Ahora, la implementación del comparador closestToScreen es la parte difícil . El W3C CSS Specification describe cómo los motores de renderizado deberían ordenar los elementos para pintar, pero hasta ahora no pude encontrar una forma fácil de acceder a esta información. Yo también asked this question aquí en SO, tal vez alguien encontrará una buena manera.


P.S. Si la modificación de la fuente de jQuery UI es una opción, usted podría intentar implementar un modo de tolerancia conscientes índice z usando document.getElementFromPoint, como this answer a dicha pregunta sugirió:

var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, 
    y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; 
switch (toleranceMode) { 
    ... 
    case 'z-index-aware': 
     return document.elementFromPoint(x1,y1) == droppable; 
     break; 

(que aseguraría única el elemento de la derecha debajo de la esquina superior izquierda del arrastrable se consideraría "lo suficientemente bueno" como destino de caída, no es ideal, pero es mejor que lo que tenemos hasta ahora; una solución similar podría adaptarse para usar las coordenadas del puntero del mouse)

Y, no, no puede usar este método con la solución presentada anteriormente: en el momento en que ocurre la caída, el asistente de arrastre es el elemento más cercano a la pantalla ... (Edit: d'oh! No funcionaría si se implementa como un modo de tolerancia, por la misma razón ...)

0

Si sólo quiere pasar el elemento se puede ver que podría cambiar su selector:

$(".draggable:visible").draggable({ 
    helper: "clone" 
}); 
$("#bottom, .draggable:visible").droppable({ 
    drop: function(event, ui) { 
     var $this = $(this), 
      $dragged = $(ui.draggable); 
     $this.append($dragged.clone()); 
    }, 
    hoverClass: "dragHover" 
})​; 

O cuando se oculta un elemento cambia su clase pueda arrastrar por algo más.

+0

Esto no funcionará ... el evento está ** no ** delegado .... – Neal

+0

@Neal parece que no entendí el verdadero problema aquí. parece que recibiste tu respuesta de otra publicación. buena suerte – TecHunter

Cuestiones relacionadas