2010-11-04 9 views
8

Esto es un problema un tanto oscuro, pero estoy usando jQuery Sortables y trato de obtener dos listas conectadas que funcionen bien juntas cuando una se posiciona como fixed. Todo funciona bien hasta que se desplaza un poco por la página para que las dos listas terminen una encima de la otra. Entonces las listas parecen confundirse en cuanto a cuál debería estar recibiendo el artículo que se está arrastrando, lo que significa que se produce un montón de nerviosismo ya que aparece/desaparece en cada lista.Tratando de superponer listas ordenables jQuery

Parece que el problema es que ambas listas manejan los eventos mouse/sort ya que el elemento arrastrado está técnicamente sobre ambas listas, pero lo que quiero es tener la lista superpuesta (es decir, position: fixed) tragar los eventos para que la lista principal subyacente no intente recibir el artículo.

Aquí está el ejemplo de código mínima:

<html> 
<head> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script> 
    <style type="text/css"> 
     ul { list-style-type: none; padding: 0; float: left; } 
     li { margin: 5px; padding: 5px; width: 500px; border: solid 1px #F00; background-color: #FFF; } 
     #overlayed { position: fixed; top: 0; background-color: #000; margin: 20px; padding: 10px; } 
     #overlayed li { width: 50px; float: left; } 
    </style> 
    <script type="text/javascript"> 
     $(function() { 
      $("ul").sortable({ connectWith: "ul", opacity: 0.6 }).disableSelection(); 
     }); 
    </script> 
</head> 
<body> 
<div id="overlayed"> 
    <ul> 
     <li>Item X</li> 
     <li>Item Y</li> 
     <li>Item Z</li> 
    </ul> 
</div> 
<br/><br/><br/><br/><br/> 
<ul> 
    <li>Item 01</li> 
    <li>Item 02</li> 
    <li>Item 03</li> 
    <li>Item 04</li> 
    <li>Item 05</li> 
    <li>Item 06</li> 
    <li>Item 07</li> 
    <li>Item 08</li> 
    <li>Item 09</li> 
    <li>Item 10</li> 
    <li>Item 11</li> 
    <li>Item 12</li> 
    <li>Item 13</li> 
    <li>Item 14</li> 
    <li>Item 15</li> 
    <li>Item 16</li> 
    <li>Item 17</li> 
    <li>Item 18</li> 
    <li>Item 19</li> 
    <li>Item 20</li> 
    <li>Item 21</li> 
    <li>Item 22</li> 
    <li>Item 23</li> 
    <li>Item 24</li> 
    <li>Item 25</li> 
    <li>Item 26</li> 
    <li>Item 27</li> 
    <li>Item 28</li> 
    <li>Item 29</li> 
    <li>Item 30</li> 
</ul> 
</body> 
</html> 

Así que la pregunta es, ¿cómo puedo solucionarlo?

+0

Sumérjase en el código de la biblioteca, descubra cómo funciona realmente la función que está utilizando, entonces debería ser capaz de resolver su problema. – aaaaaaaaaaaa

Respuesta

5

Terminé arreglando este problema ampliando la funcionalidad incorporada en sortable para crear un fixedSortable que detecta e ignora selectivamente al pasar el ratón sobre las listas cuando hay una superposición en su lugar. Para mis propósitos, acabo de codificar las reglas, ya que se adaptaban a mis necesidades/limitaciones de tiempo, pero debería poder hacerlo completamente genérico sin demasiado esfuerzo.

En primer lugar aquí está el código (explicación más abajo):

<html> 
<head> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.6/jquery-ui.min.js"></script> 
    <style type="text/css"> 
     ul { list-style-type: none; padding: 0; float: left; } 
     li { margin: 5px; padding: 5px; width: 500px; border: solid 1px #F00; background-color: #FFF; } 
     #overlayed { position: fixed; top: 0; background-color: #000; margin: 20px; padding: 10px; } 
     #overlayed li { width: 50px; float: left; } 
    </style> 
    <script type="text/javascript"> 
     (function ($, undefined) { 
      $.widget("ui.fixedSortable", $.ui.sortable, { 
       _init: function() { 
        this.element.data("sortable", this.element.data("fixedSortable")); 
        return $.ui.sortable.prototype._init.apply(this, arguments); 
       }, 
       _create:function() { 
        var result = $.ui.sortable.prototype._create.apply(this, arguments); 
        this.containerCache.sortable = this; 
        return result; 
       }, 
       _intersectsWithPointer: function (item) { 
//This line.... 
        if (item.instance.element.hasClass("main-list") && this.positionAbs.top + this.offset.click.top < $(window).scrollTop() + 87) { 
         return false; 
        } 
        return $.ui.sortable.prototype._intersectsWithPointer.apply(this, arguments); 
       }, 
       _intersectsWith: function(containerCache) { 
//Also this line.... 
        if (containerCache.sortable.element.hasClass("main-list") && this.positionAbs.top + this.offset.click.top < $(window).scrollTop() + 87) { 
         return false; 
        } 
        return $.ui.sortable.prototype._intersectsWith.apply(this, arguments); 
       } 
      }); 
     })(jQuery); 

     $(function() { 
      $("ul").fixedSortable({ connectWith: "ul", opacity: 0.6 }).disableSelection(); 
     }); 
    </script> 
</head> 
<body> 
<div id="overlayed"> 
    <ul> 
     <li>Item X</li> 
     <li>Item Y</li> 
     <li>Item Z</li> 
    </ul> 
</div> 
<br/><br/><br/><br/><br/> 
<ul class="main-list" > 
    <li>Item 01</li> 
    <li>Item 02</li> 
    <li>Item 03</li> 
    <li>Item 04</li> 
    <li>Item 05</li> 
    <li>Item 06</li> 
    <li>Item 07</li> 
    <li>Item 08</li> 
    <li>Item 09</li> 
    <li>Item 10</li> 
    <li>Item 11</li> 
    <li>Item 12</li> 
    <li>Item 13</li> 
    <li>Item 14</li> 
    <li>Item 15</li> 
    <li>Item 16</li> 
    <li>Item 17</li> 
    <li>Item 18</li> 
    <li>Item 19</li> 
    <li>Item 20</li> 
    <li>Item 21</li> 
    <li>Item 22</li> 
    <li>Item 23</li> 
    <li>Item 24</li> 
    <li>Item 25</li> 
    <li>Item 26</li> 
    <li>Item 27</li> 
    <li>Item 28</li> 
    <li>Item 29</li> 
    <li>Item 30</li> 
</ul> 
</body> 
</html> 

Si la adaptación de este mismo, tendrá que cambiar las dos líneas comentadas marcados anteriormente. Básicamente, las sentencias if deben evaluarse como verdaderas (y, por lo tanto, devolver falsas) si el elemento que se coloca sobre (item.instance.element y containerCache.sortable.element) es no la superposición y el evento (this) se produce dentro de los límites de la superposición. De esta manera, la lista principal nunca recibe eventos en la ubicación de la página donde se encuentra la superposición. Así que en este código la lista principal no recibe ningún evento si ocurre en los 87 píxeles superiores de la pantalla, ya que ahí es donde estaba mi superposición fija (que no es muy precisa en este ejemplo simplificado, pero con suerte todavía tiene sentido)

+3

no sé si esto es útil para cualquier persona, pero he dejado caer el código de Alconja en JSBin para que pueda ver que funciona. http://jsbin.com/iqemid/2 todo gracias a Alconja por este código ^^ – azzy81

2

Este es el error que creo que está encontrando, y la solución es mucho más simple:

http://bugs.jqueryui.com/ticket/7065

+1

Creo que es el mismo error, pero la solución sugerida no cubre todos los escenarios (incluido el que menciona el OP). Creo que la solución real requiere determinar el contexto de apilamiento de todos los contenedores desplegables bajo el cursor y seleccionar el contenedor superior en términos de orden z. –

+0

Ah, probablemente sea cierto. La corrección solo cubre las listas que se superponen debido al desbordamiento: oculto, no debido al orden z. Parece que primero tienes que ordenar los candidatos por orden z y luego recorrerlos hasta que obtengas un golpe. – Jason

0

me encontré con este problema en una página donde tengo una lista vertical por encima de una segunda lista . Aunque el desbordamiento está configurado como oculto, el desbordamiento invisible de la lista superior sigue bloqueando el evento de desbordamiento para la lista debajo de él (esto se puede confirmar configurando el desbordamiento en automático en la lista superior para ayudar a visualizar la superposición). Es un problema de índice z.

Mi solución fue colocar este código en caso de parada se puede ordenar:

//expliclty hide the overflow items 
$('.topList .item:gt(5)').hide(); 
$('.topeList .item:first').show(); 

Lo que estoy haciendo aquí está ocultando de manera explícita los elementos de la lista superior, dejando sólo la parte superior 5 visible, por lo que no hay DOM offset superposición entre la lista superior e inferior.

Cuestiones relacionadas