css, html, php, javascript, jQuery, ajax … – решения, примеры, рецепты
5 Мар
Плагин для javascript- библиотеки jQuery, о котором пойдет речь в этой статье, позволит пользователю «вручную» сортировать строки таблицы с помощью технологии drag-and-drop.
Для начала посмотрите небольшой пример, а потом будем разбирать, как это работает.
Вы можете скачать исходный код примера, и при наличии библиотеки jQuery воспроизвести это пример на своем сайте.
Для начала нам потребуется подключить к странице два файла – библиотеку jQuery и файл jquery.tablednd.js. Сделаем это в разделе HEAD.
<script type="text/javascript" src="js/jquery-1.2.1.js"></script> <script type="text/javascript" src="js/jquery.tablednd.js"></script>
Что касается стилевого оформления таблицы – здесь Вы вольны творить как угодно. В HTML-коде также ничего особенного – совершенно обычная таблица. Замечу только, что все строки таблицы (элементы tr) должны иметь атрибут id, т.е. содержать идентификатор. Ну и конечно мы должны будем иметь возможность обратиться к конкретной таблице, поэтому атрибут id должна иметь и сама таблица.
В принципе мы могли бы обращаться к таблице и по имени класса, но лучше все-таки использовать именно id – спокойнее как-то.
В самом простом варианте сделать строки перемещаемыми в таблице можно вот так:
<script type="text/javascript">
$(document).ready(function() {
$("#table-1").tableDnD();
});
</script>
Т.е. по сути одной строкой! Все остальное – «обертка», которая отслеживаем момент готовности объектной модели документа (DOM). Но это не было бы так интересно, если бы мы не имели возможности использовать какие-либо дополнительные параметры. К счастью такая возможность есть. Я приведу список доступных опций, поясняя некоторые из них строками кода.
onDragClass – определяет имя класса, который добавляется во время перемещения строки и будет удален после того, как строка будет drop, сброшена. Вот как это выглядит в коде:
$("#table-1").tableDnD({
onDragClass: "dragRow"
});
Для назначения стилей при перемещении строки возможно также использование опции onDragStyle, но onDragClass представляется более гибким для применения, поскольку при использовании onDragStyle, назначенные стили могут быть унаследованы например ячейками строки или другим содержимым, что не всегда приемлемо.
onDropStyle – составляет как бы пару для onDragStyle и содержит конечно же имя класса, который будет применен в момент операции drop.
onDragStart – содержит функцию, которая будет вызвана в момент начала перемещения строки. Функция принимает два параметра – таблицу и строку, которую пользователь начал перемещать.
onDragStart: function(table, row) {
$("#messageArea").html("Перемещаем строку " + row.id);
}
onDrop – содержит функцию, которая будет вызвана в момент, когда строка «сброшена». Функция принимает два параметра – таблицу и строку, которую пользователь «сбросил». Новый порядок расположения строк можно получить, используя table.tBodies[0].rows.
Именно в onDrop я добавил пару строк кода, что бы «сброшенная» строка немного «моргнула» (правда не могу разобраться, почему-то «моргает»она только в FireFox – странно…) – все это Вы сможете увидеть в исходном коде.
В качестве содержимого ячеек вполне могут быть использованы элементы input или select. Правда здесь необходимо отметить, что присутствуют некоторые проблемы с использованием radio и checkbox в IE6. При перемещении строки эти элементы не сохраняют значение, если оно было определено.
Что еще? Ну разве можно сказать, что какие-то строки в таблице можно сделать неперемещаемыми. Для этого элементу tr необходимо добавить атрибут noDrag со значением true.
Вот теперь наверное совсем все.
Отзывов (41) на «jQuery – перемещение строк в таблице»
хм… а как предотвратить процесс перетаскивания в момент связи с сервером при необходимости. Допустим мне необходимо поменять порядок следования строк в базе…
Немного вопрос непонятен… Перетаскивание строк происходит на стороне клиента. Пусть юзер таскает их как угодно. До какого-то момента… А потом, например с помощью Ajax-запроса, данные уходят на сервер. Выполняйте синхронный запрос и все действия на стороне клиента будут блокированы до окончания запроса…
Вот такой же пример надо, только между двумя таблицами
Добрый день!
А как можно забрать данные о новом порядке, чтобы закрепить его в базе данных? Очень бы пригодилось…
Посмотрите внимательно исходный код. В опции onDrop мы перебираем в цикле все rows и имеем возможность получить id строки – rows[i].id
Дальше можно с помощью $.ajax() например, отправить эти данные серверу….
Как именно это можно проделать – см. соответствующие статьи.
Спасибо за научение! Поторопился с вопросом…
Стану пробовать.
А если закосячит, можно я снова приду?
Можно… Заходите, всегда рад.
есть небольшой глюк (актуально для версии 0.5 может и дальше)
если при верстке использовать теги то при перетастивании на заголовок вылетает ошибка элемент не найден – не смертельно но ie кумарит
в функции mousemove в строке 202 нужно добавить в проверку «currentRow.parentNode.tagName == ‘TBODY’»
что-бы получилось так «} else if (! movingDown && jQuery.tableDnD.dragObject != currentRow && currentRow.parentNode.tagName == ‘TBODY’) {«
кусок поста не прошол цунзуру
ошибка если использовать теги «THEAD», «TFOOT»
Возможно ли добавить атрибут noDrag = true при при вставке новой строки в таблицу.
строка вставляется обычным способом
selftable.insertRow(numrow), где numrow – номер вставляемой строки.
Благодарен за ваш нужный труд.
Собственно я сам догадался… После вставки строки, как описано выше, устанавливаем для нее атрибут noDrag = true, так: newrow.setAttribute(«noDrag», «true»);
После этого новая строка не сможет быть перемещена!
Всем удачи!
Главное, вовремя не ответить! Хорошо, что Вы сами догадались – просто не всегда есть возможность оперативно отвечать на вопросы. Все-таки блог – это хобби, а не работа.
Добрый день,
возник вопрос – как ограничить перетаскивание ячеек ?
хочется сделать чтоб ячейку 5 напрмиер можно было таскать только в пределах между 3 и 7.. и чтоб ячейку 1 вообще невозможно было заменить =)
Если честно – на практике не сталкивался, так что посоветовать что-то не могу. Наверное можно какую-то логику продумать. Во время перемещения отслеживать какие-то параметры, при выходе за пределы которых запрещать дальнейшее перемещение. Только надо придумать какие именно параметры.
есть параметр onAllowDrop который содержит функцию, которой передаются перетаскиваемая строка и строка над которой она находится. Возвращаем true если можно бросать и false если нельзя
у вас несколько хороших примеров работы с таблицами.
а можно примерчик того, как по щелчку стрелок на клавиатуре выделяются строки в соответствующую сторону? (особенно если таблица не помещается на странице и поэтому у нее есть сбоку скрол)
Ну, примерно вот так:
$(document).ready(function(){ // toggle для того, чтобы по клику выделять строку $('tr').toggle( function() { // по первому клику на строке // удаляем класс с подсветкой для всех строк $('tr.hightlight').removeClass('hightlight'); // добавляем подсветку кликнутой строки $(this).addClass('hightlight'); }, function() { // по второму клику на строке // удаляем класс с подсветкой $(this).removeClass('hightlight'); } ); // отслеживаем keyup $(document).keyup(function(event){ if(event.keyCode == 38) { // стрелка вверх // для подсвеченной строки удаляем подсветку, // переходим на предыдущую строку // добавляем ей класс с подсветкой $('tr.hightlight').removeClass('hightlight') .prev('tr') .addClass('hightlight'); } if(event.keyCode == 40) { // стрелка вниз // для подсвеченной строки удаляем подсветку, // переходим на следующую строку // добавляем ей класс с подсветкой $('tr.hightlight').removeClass('hightlight') .next('tr') .addClass('hightlight'); } }); });вопрос по предыдущему коду.
а как сделать так, чтобы этот код срабатывал только для таблицы с определенным id?
я пыталась везде добавить #grid_table_header до tr, но так не работает.
Если таблица имеет id например #table, то в селекторе, вместо просто tr надо указывать:
$(‘#table tr’).toggle(……..
В остальных местах аналогично. Тут синтаксис практически тот же, что и в обычном CSS.
СПАСИБО ОГРОМНОЕ!!!!!! заработало как нужно.
а еще один вопросик можно?
на событие стрелок также реагирует сама web-страница (т.е. срабатывает боковой скрол), а от этого можно как-нибудь избавиться?
Здесь уже немного шаманить надо, я подскажу в каком направлении. Можно сделать что-то вроде этого:
$(window).scroll(function () { $(this).scrollTop(0); });т.е. как только возникает событие scroll(), отрабатывает функция, которое тащит окно обратно вверх. Минус тут в том, что когда дойдем до нижнего края окна, наша подсветка уйдет еще дальше вниз и ее просто не будет видно.
Значит надо дорабатывать еще – получать размеры окна, отслеживать их, и при достижении нижней границы мудрить что-то еще….
Как перехватить какую строку перенесли понятно, а вот как определить строки которые были перемещены. т.е.если мы последнюю строку сделали первой, то нумерация всех строк летит… не могу допетрить
Записываю порядок строк для всех записей. Громоздко, но пока не могу подругому..
$(document).ready(function(){
$(«#catTable»).tableDnD({
onDragClass: «dragRow»,
onDrop: function(table, row)
{
var str = »;
var numRows = table.tBodies[0].rows.length-2;
temp = new Array(numRows);
for(var i=0; i < numRows; i++)
{
str += table.tBodies[0].rows[i+2].id + ‘=’ + (i+1) + ‘,’;
}
updateOrder(str);
}
});
});
А что непонятного? Каждая строка имеет свой id и он при перемещении не изменяется. Остается только по окончанию перемещения очередной строки собрать все id – и готов новый порядок сортировки.
Собственно в примере это есть…
Собственно так и делаю, только приходится обновлять поле в базе всех записей, и тех которые изменились и тех которые не изменились. Т.е. лишние запросы к базе…
У меня таблицы в районе 15-35 строк…
И если переместить строку на одну позицию вверх, то надо-то обновить только 2 записи в базе, а не 35…
Насколько помню, это можно сделать всего одним запросом…
UPDATE `tbl` SET `order`=’1′ WHERE `id`=’1′
UPDATE `tbl` SET `order`=’2′ WHERE `id`=’6′
UPDATE `tbl` SET `order`=’3′ WHERE `id`=’4′
UPDATE `tbl` SET `order`=’4′ WHERE `id`=’2′
Как это выполнить одним запросом?
А кто-нибудь пробовал делать сортировку с многоуровневой структурой? ну т.е. так чтоб уровень целиком с подуровнями таскался?
To kukuikar:
Вы же и спрашивали тут? И Вам ответили:
…. Можно написать запрос UPDATE обновляющий несколько записей в таблице или нескольких таблицах
можно встраивать подзапросы например в выражениях для определения WHERE ….
Объединить действительно нельзя, а написать запрос по аналогии с INSERT – можно.
Вы посмотрите мануал даже на тему многострочного INSERT’a и поэкспериментируйте с UPDATE.
Должно получиться.
А возможно ли сделать так чтобы данный плагин обрабатывал строки которые будут созданы через jquery методом добавления элементов DOM
alex, после добавления новых строк еще раз:
$(«#table»).tableDnD();
А я делаю так:
$(«#editcontent»).tableDnD({
onDrop: function(table, row) {
var curID = 0;
for (var i=0;i<table.tBodies[0].rows.length;i++)
{
curID = parseInt(table.tBodies[0].rows[i].id.split(«_»)[1]);
$.post(«ajax.php»,{id: curID, order: i+1});
}
}
});
Спасибо. Подскажите пожалуйста, как решить одну проблему с этим плагином? Суть в том, что у таблицы есть строка заголовков (thead-th). Он та не перещается (noDrag). Но получается переместить строки перед ней. Как можно этого избежать?
Знаете, даже не нашел свежей версии этого плагина… Просто он очень старый (и теперь не развивается??? наверное…) и я бы советовал обратить внимание на более современные плагины.
Хотя может я не прав? И Вы знаете, где найти свежую версию плагина, хотя бы под версию 1.3.2?
Спасибо за статью! Такой вопрос: а если у меня есть шапка в таблице как сделать что бы выше нее не перетаскивались строки? Как я начитал в каментах с помощью «onAllowDrop», не подскажете как именно?
To chiffa:
Плагин этот уж больно старый…. Еле-еле нашел его страницу: http://www.isocra.com/2008/02/table-drag-and-drop-jquery-plugin/ – не увидел onAllowDrop…
Почему бы Вам не обратить внимание на какие-то современные решения? Например на Sortable из UI jQuery….
Спасибо за ответ! Все оказалось намного проще: class=»nodrop nodrag»
Еще раз спасибо!
Всё-таки, как сделать, чтобы строки не перескакивали через шапку? Что-куда прописать?
Спасибо, статья очень выручила.
Было бы здорово, если напишешь обзор и на NestedSortables, полезная штука, правда с таблицами не работает.
Есть небольшой вопросик…
с ячейках таблицы у меня лежат input type=»text»
так вот, при перетаскивании строк, эти импуты выпадают с DOM и когда нажимаю на кнопку Submit то в POST они не передаются.
Не подскажете что можно сделать?
Пожалуйста, все технические вопросы – на форум jQuery. Здесь комментирование закрыто.