Переместить элемент списка в начало неупорядоченного списка с помощью jQuery - PullRequest
26 голосов
/ 26 октября 2009

Допустим, у меня есть следующий неупорядоченный список

<ul>
 <li><a>Hank</a></li>
 <li><a>Alice</a></li>
 <li><a>Tom</a></li>
 <li><a>Ashlee</a></li>
</ul>

Что я ищу, так это когда я нажимаю на Тома, он перемещается (анимированный и без перетаскивания) в верхнюю часть списка (индекс 0).

Я считал jquery сортируемым, но не могу найти способ активировать движущуюся часть программно.

Ответы [ 5 ]

52 голосов
/ 12 мая 2012

нашел это даже аккуратнее:

$('li').on('click', function() {
    $(this).parent().prepend(this);
});​

Живой пример

19 голосов
/ 27 октября 2009

Я нашел решение, которое, кажется, работает довольно хорошо. Это подтверждение концепции, поэтому вам, вероятно, придется немного ее изменить, чтобы она лучше подходила для вашего конкретного случая. Кроме того, я тестировал его только в Firefox, но не вижу причин, по которым это не будет работать во всех браузерах. Во всяком случае, вот оно:

<script type="text/javascript">
  $(document).ready(function() {
    $('li').click(function() {
      // the clicked LI
      var clicked = $(this);

      // all the LIs above the clicked one
      var previousAll = clicked.prevAll();

      // only proceed if it's not already on top (no previous siblings)
      if(previousAll.length > 0) {
        // top LI
        var top = $(previousAll[previousAll.length - 1]);

        // immediately previous LI
        var previous = $(previousAll[0]);

        // how far up do we need to move the clicked LI?
        var moveUp = clicked.attr('offsetTop') - top.attr('offsetTop');

        // how far down do we need to move the previous siblings?
        var moveDown = (clicked.offset().top + clicked.outerHeight()) - (previous.offset().top + previous.outerHeight());

        // let's move stuff
        clicked.css('position', 'relative');
        previousAll.css('position', 'relative');
        clicked.animate({'top': -moveUp});
        previousAll.animate({'top': moveDown}, {complete: function() {
          // rearrange the DOM and restore positioning when we're done moving
          clicked.parent().prepend(clicked);
          clicked.css({'position': 'static', 'top': 0});
          previousAll.css({'position': 'static', 'top': 0}); 
        }});
      }
    });
  });
</script>

<ul>
 <li><a>Hank</a></li>
 <li><a>Alice</a></li>
 <li><a>Tom</a></li>
 <li><a>Ashlee</a></li>
</ul>

Он вычисляет разницу в смещениях между нажатием LI и первым LI и перемещает нажатый вверх на верх, устанавливая его position в relative и анимируя свойство top. Точно так же он вычисляет, сколько места осталось после нажатия LI, и соответственно перемещает все предыдущие. Когда это сделано с анимацией, он перестраивает DOM в соответствии с новым порядком и восстанавливает стили позиционирования.

Надеюсь, это поможет!

10 голосов
/ 26 октября 2009

Предполагая, что:

<ul id="list">
 <li><a>Hank</a></li>
 <li><a>Alice</a></li>
 <li><a>Tom</a></li>
 <li><a>Ashlee</a></li>
</ul>

тогда:

$("#list a").click(function() {
  $(this).parent().before("#list a:first");
  return false;
});

Если вы хотите оживить, тогда это немного сложнее. Один вариант:

$("#list a").click(function() {
  $(this).parent().slideUp(500).before("#list a:first").slideDown(500);
  return false;
});

Другой вариант:

$("#list a").click(function() {
  var item = $(this).parent();
  var prev = item.prev();
  while (prev.length > 0) {
    item.before(prev);
    prev = item.prev();
  }
  return false;
});

но я сомневаюсь, что вы получите плавную анимацию таким образом.

2 голосов
/ 13 мая 2011

Я поиграл с скрипкой, которую не сделал сюрприз, и расширил код для замены двух произвольных наборов элементов (единственное ограничение - они должны следовать непосредственно друг за другом).

см. Здесь: http://jsfiddle.net/ZXYZ3/139/

1 голос
/ 27 ноября 2012

Я придумал это решение: http://jsfiddle.net/FabienDemangeat/TBYWw/

Идея состоит в том, чтобы выбрать индекс элемента Li, который будет перемещаться, и его назначение. Если значение назначения ниже индекса элемента li для перемещения, эффект будет обратным.

Некоторые детали не идеальны, но это может стать отправной точкой. Я вдохновил себя от фрагмента, предоставленного "Никакими Сюрпризами"

Основная функция swapLiElements заменяет два элемента li, а функция обратного вызова в качестве параметров позволяет легко выполнять более одного обмена ( см. Скрипту ).

function swapLiElements($northLi, $southLi, isPushingDown, duration, easing, callbackFunction) {

    var movement = $northLi.outerHeight();

    // Set position of the li elements to relative
    $northLi.css('position', 'relative');
    $southLi.css('position', 'relative');

    // Set the z-index of the moved item to 999 to it appears on top of the other elements
    if(isPushingDown)
        $northLi.css('z-index', '999');
    else        
        $southLi.css('z-index', '999');

    // Move down the first li
    $northLi.animate({'top': movement}, {
        duration: duration,
        queue: false,
        easing: easing,
        complete: function() {
            // Swap the li in the DOM
            if(isPushingDown)
                $northLi.insertAfter($southLi);
            else
                $southLi.insertBefore($northLi);

            resetLiCssPosition($northLi);
            resetLiCssPosition($southLi);

            callbackFunction();
        }
    });

    $southLi.animate({'top': -movement}, {
        duration: duration,
        queue: false,
        easing: easing,
    });

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...