2010-11-04 5 views
8

Il s'agit d'un problème un peu obscur, mais j'utilise jQuery Sortables et j'essaie de faire fonctionner correctement deux listes connectées lorsque l'une est positionnée comme fixed. Tout fonctionne bien jusqu'à ce que vous faites défiler la page un peu de sorte que les deux listes se retrouvent l'une sur l'autre. Ensuite, les listes semblent être confus quant à savoir lequel devrait recevoir l'objet qui est traîné, ce qui signifie que vous obtenez un tas de scintillement qui se passe comme il apparaît/disparaît dans chaque liste. Il semble que le problème est que les deux listes gèrent les événements mouse/sort puisque l'élément qui est déplacé est techniquement sur les deux listes, mais ce que je veux, c'est que la liste superposée (ie la position: fixed) avale les événements de sorte que la liste principale sous-jacente n'essaie pas de recevoir l'élément.Traitement des listes triantes jQuery chevauchantes

Voici l'exemple de code minimal:

<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> 

La question est, comment puis-je résoudre ce problème?

+0

Plongez dans le code de la bibliothèque, découvrez comment la fonction que vous utilisez fonctionne réellement, alors vous devriez être capable de résoudre votre problème. – aaaaaaaaaaaa

Répondre

5

J'ai fini par résoudre ce problème en étendant la fonctionnalité intégrée sortable pour créer un fixedSortable qui détecte et ignore sélectivement le survol des listes lorsqu'il y a une superposition en place. Pour mes besoins, j'ai juste codé les règles, car cela convenait à mes besoins/contraintes de temps, mais vous devriez être capable de le rendre complètement générique sans trop d'efforts.

est d'abord ici le code (explication ci-dessous):

<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 adapter vous-même, vous aurez besoin de changer les deux lignes marquées ci-dessus commentées. Fondamentalement, les instructions if doivent évaluer true (et donc false) si l'élément survolé (item.instance.element et containerCache.sortable.element) est et non la superposition et l'événement (this) se produisent dans les limites de la superposition. De cette façon, la liste principale ne reçoit jamais d'événements à l'emplacement de la page où se trouve la superposition. Donc, dans ce code, la liste principale ne reçoit aucun événement s'ils apparaissent dans les 87 premiers pixels de l'écran, puisque c'est là que se trouvait ma superposition fixe (ce qui n'est pas tout à fait exact dans cet exemple, mais j'espère).

+3

ne sais pas si cela est utile à tout le monde mais j'ai déposé le code d'Alconja dans JSBin afin que vous puissiez le voir fonctionner. http://jsbin.com/iqemid/2 tout merci à Alconja pour ce code ^^ – azzy81

2

C'est le bug je pense que vous rencontrez, et le correctif est beaucoup plus simple:

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

+1

Je pense que c'est le même bug, mais le correctif suggéré ne couvre pas tous les scénarios (y compris celui mentionné par l'OP). Je pense que le vrai correctif nécessite de déterminer le contexte d'empilement de tous les conteneurs droppables sous le curseur et de sélectionner le conteneur le plus haut en termes d'ordre z. –

+0

Ah, probablement vrai. Le correctif ne couvre que les listes qui se chevauchent en raison d'un débordement: caché, non dû à l'ordre z. Il semble que vous ayez besoin de trier les candidats par ordre z d'abord, puis de les traverser jusqu'à ce que vous obteniez un coup. – Jason

0

je suis tombé sur ce problème sur une page où j'ai une liste verticale au-dessus d'une seconde liste . Même si overflow est défini sur hidden, le débordement invisible de la liste supérieure bloque toujours l'événement move over de la liste en dessous (cela peut être confirmé en définissant overflow sur auto dans la liste supérieure pour aider à visualiser le chevauchement). C'est un problème de z-index.

Mon solution était de placer ce code en cas d'arrêt sortable:

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

Ce que je fais ici se cache explicitement les éléments de la liste haut, ne laissant que les 5 visibles de sorte qu'il n'y a pas de DOM décalage chevauchement entre la liste supérieure et inférieure.