Существует масса решений для сортировки списков, например tableDTD, tableSorter, jQuery.sortable и прочих, которые имеют широкий функционал, но при этом — большой код.
Моё решение использует jQuery, имеет компактный код (42 строки без комментариев) и предусматривает перемешивание элементов (относительно позиционированных) в пределах родительского контейнера.
Весь ход мыслей прокомментирован в JavaScript.
Моё решение использует jQuery, имеет компактный код (42 строки без комментариев) и предусматривает перемешивание элементов (относительно позиционированных) в пределах родительского контейнера.
Весь ход мыслей прокомментирован в JavaScript.
Посмотреть в действии на jsFiddle (некомментированный код).
HTML-разметка
<!DOCTYPE html> <html><head> <meta charset='utf-8'> <link type='text/css' rel='stylesheet' href='style.css'> <script type='text/javascript' src='http://code.jquery.com/jquery-2.0.3.min.js'></script> <script type='text/javascript' src='actions.js'></script> </head><body> <div class="container"> <div class="drop">1</div> <div class="drop">2</div> <div class="drop">3</div> <div class="drop">4</div> <div class="drop">5</div> </div> <input class="focus-out"> </body></html>
style.css
.container {width:200px;} .drop {position:relative; top:0px; height:16px; cursor:default; z-index:1;} .focus-out {position:absolute; width:2px; height:2px; left:-10px; top:-10px; background:none;}
actions.js
$(document).ready(function(){ // нажали на любом элементе списка $('.drop').mousedown(function(e){ var drop = $(this); // верхняя граница контейнера var posParentTop = drop.parent().position().top; // нижняя граница контейнера var posParentBottom = posParentTop + drop.parent().height(); // координаты исходного положения элемента var posOld = drop.position().top; // коррекция относительно позиции курсора при нажатии var posOldCorrection = e.pageY - posOld; // поднимаем нажатый элемент по z-оси drop.css({'z-index':2, 'background-color':'#eeeeee'}); // перетягиваем элемент var mouseMove = function(e){ // получаем новые динамические координаты элемента var posNew = e.pageY - posOldCorrection; // если элемент перетянут выше верхней границы контейнера if (posNew < posParentTop){ // устанавливаем позицию элемента, равную позиции родителя drop.offset({'top': posParentTop}); // отменяем выделение, переместив фокус в спрятанный (но не скрытый через css) input $('.focus-out').focus(); // если элемент перетянут ниже нижней границы контейнера } else if ((posNew + drop.height()) > posParentBottom){ // устанавливаем позицию элемента, равную позиции родителя + высоте родителя - высоте элемента drop.offset({'top': posParentBottom - drop.height()}); // отменяем выделение $('.focus-out').focus(); // если элемент в пределах контейнера } else { // устанавливаем новую высоту (элемент перемещается за курсором) drop.offset({'top': posNew}); // если элемент перемещен вверх на собственную высоту if (posOld - posNew > drop.height() - 2){ // меняем элемент с предыдущим в DOM drop.insertBefore(drop.prev()); // обнуляем позицию drop.css({'top':0}); // снова получаем координаты исходного и текущего положения posOld = drop.position().top; posNew = e.pageY - posOldCorrection; posOldCorrection = e.pageY - posOld; // если элемент перемещен вниз на собственную высоту } else if (posNew - posOld > drop.height() - 2){ // меняем элемент со следующим в DOM drop.insertAfter(drop.next()); drop.css({'top':0}); posOld = drop.position().top; posNew = e.pageY - posOldCorrection; posOldCorrection = e.pageY - posOld; } // отменяем выделение $('.focus-out').focus(); } }; // отпускаем клавишу мыши var mouseUp = function(){ // завершаем выполнение функции $(document).off('mousemove', mouseMove).off('mouseup', mouseUp); // плавно возвращаем наш элемент на ближайшее освободившееся место drop.animate({'top':0}, 100); // возвращаем z-позицию на уровень остальных элементов setTimeout(function(){ drop.css({'z-index':1, 'background-color':'transparent'}); }, 100); }; // подключаем выполнение функций перемещения и отпускания клавиши мыши // и завершаем выполнение функции, если нажата правая клавиша мыши $(document).on('mousemove', mouseMove).on('mouseup', mouseUp).on('contextmenu', mouseUp); }); });
Нерешённый вопрос: снимать выделение без использования спрятанного input (это простой путь, но совсем не феншуй). Кто что думает по поводу user-select?
ссылка на оригинал статьи http://habrahabr.ru/post/193004/
Добавить комментарий