mirror of
https://github.com/claradex/nativegallery.git
synced 2024-11-15 03:31:10 +03:00
193 lines
5.2 KiB
JavaScript
193 lines
5.2 KiB
JavaScript
|
/**
|
|||
|
* tablesort plugin for jQuery
|
|||
|
* Written by Alexander Konov
|
|||
|
* Based on TableDnD ideas (https://github.com/isocra/TableDnD)
|
|||
|
*/
|
|||
|
|
|||
|
(function($)
|
|||
|
{
|
|||
|
$.fn.tablesort = function(options)
|
|||
|
{
|
|||
|
function recountRows(tbl)
|
|||
|
{
|
|||
|
var opts = tbl.data('opts');
|
|||
|
var rows = $(opts.rowSelector, tbl);
|
|||
|
var rowsCount = rows.length;
|
|||
|
var handle = (opts.dragHandle ? $(opts.dragHandle, tbl) : tbl);
|
|||
|
|
|||
|
tbl.data('rowsCount', rowsCount);
|
|||
|
handle[rowsCount > 1 ? 'addClass' : 'removeClass']('tablesort-active');
|
|||
|
|
|||
|
return rows;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
$(this).each(function()
|
|||
|
{
|
|||
|
var table = $(this);
|
|||
|
|
|||
|
// Метод recountRows нужно вызывать извне при добавлении или удалении строк в таблице
|
|||
|
// Это требуется для автоотключения сортировки, если в таблице только одна строка
|
|||
|
if (typeof options == 'string' && options == 'recountRows')
|
|||
|
{
|
|||
|
recountRows(table);
|
|||
|
return table;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
var eventStart = 'touchstart.tablesort mousedown.tablesort';
|
|||
|
var eventMove = 'touchmove.tablesort mousemove.tablesort';
|
|||
|
var eventEnd = 'touchend.tablesort mouseup.tablesort';
|
|||
|
|
|||
|
var dragObject = null;
|
|||
|
var mouseOffset = null;
|
|||
|
var oldY = 0;
|
|||
|
|
|||
|
var defaults = {
|
|||
|
rowSelector: 'tr', // Можно указать tbody, если надо перемещать блоки, состоящие из нескольких строк
|
|||
|
dragHandle: null, // Селектор "ручки" для переноса (по умолчанию можно перемещать, потянув за любое место строки, кроме <a> и <input>)
|
|||
|
sensitivity: 10, // Sensitivity setting will throttle the trigger rate for movement detection
|
|||
|
onChange: null // Функция onChange
|
|||
|
};
|
|||
|
|
|||
|
if (options == undefined) options = {};
|
|||
|
var opts = $.extend({}, defaults, options);
|
|||
|
|
|||
|
table.data('opts', opts);
|
|||
|
|
|||
|
|
|||
|
if (opts.dragHandle)
|
|||
|
table.on(eventStart, opts.dragHandle, function(e) { startDrag($(this).closest(opts.rowSelector), e); });
|
|||
|
else table.on(eventStart, opts.rowSelector, function(e) { startDrag($(this), e); });
|
|||
|
|
|||
|
recountRows(table);
|
|||
|
|
|||
|
|
|||
|
function startDrag(dragObj, e)
|
|||
|
{
|
|||
|
if (table.data('rowsCount') <= 1) return; // Некуда перетаскивать - всего одна строка в таблице
|
|||
|
|
|||
|
var target = $(e.target);
|
|||
|
if (target.closest('a').length != 0 || target.is('input') || target.is('select') || target.is('textarea')) return; // Неподходящие для перетаскивания элементы с собственным поведением
|
|||
|
|
|||
|
e.preventDefault();
|
|||
|
|
|||
|
dragObject = dragObj;
|
|||
|
mouseOffset = getMouseY(e) - $(e.target).offset().top;
|
|||
|
|
|||
|
$(document).on(eventMove, mouseMove).on(eventEnd, mouseUp);
|
|||
|
|
|||
|
$('html').add(opts.dragHandle ? $(opts.dragHandle, table) : table).addClass('tablesort-dragging');
|
|||
|
toggleObjectClass(dragObject);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function toggleObjectClass(obj)
|
|||
|
{
|
|||
|
var s = obj.attr('class');
|
|||
|
if (!s) return;
|
|||
|
|
|||
|
var i, cls, arr = s.split(' ');
|
|||
|
|
|||
|
for (i = 0; i < arr.length; i++)
|
|||
|
{
|
|||
|
if (/s[0-9]{1,2}/.test(arr[i]))
|
|||
|
{
|
|||
|
cls = parseInt(arr[i].substr(1));
|
|||
|
arr[i] = 's' + (cls >= 10 && cls <= 19 || cls >= 30 && cls <= 39 ? cls-10 : cls+10);
|
|||
|
}
|
|||
|
|
|||
|
obj.attr('class', arr.join(' '));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function getMouseY(e)
|
|||
|
{
|
|||
|
if (e.originalEvent.changedTouches) return e.originalEvent.changedTouches[0].clientY + $(document).scrollTop();
|
|||
|
if (e.pageY) return e.pageY;
|
|||
|
return e.clientY + $(document).scrollTop();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function checkPageScroll(e)
|
|||
|
{
|
|||
|
var y = (e.originalEvent.changedTouches) ? e.originalEvent.changedTouches[0].clientY : e.clientY;
|
|||
|
var h = $(window).innerHeight();
|
|||
|
|
|||
|
if (y < 25) window.scrollBy(0, -10); else
|
|||
|
if (y > h - 25) window.scrollBy(0, 10);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function rowMoving(dir, currentRow)
|
|||
|
{
|
|||
|
if (!dir || !currentRow) return;
|
|||
|
currentRow[dir > 0 ? 'after' : 'before'](dragObject);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function mouseMove(e)
|
|||
|
{
|
|||
|
if (!dragObject) return false;
|
|||
|
e.preventDefault();
|
|||
|
|
|||
|
checkPageScroll(e);
|
|||
|
|
|||
|
var mouseY = getMouseY(e);
|
|||
|
rowMoving(findDragDirection(mouseY), findDropTargetRow(dragObject, mouseY));
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function findDragDirection(y)
|
|||
|
{
|
|||
|
var yMin = oldY - opts.sensitivity;
|
|||
|
var yMax = oldY + opts.sensitivity;
|
|||
|
|
|||
|
var dir = y >= yMin && y <= yMax ? 0 : y > oldY ? 1 : -1;
|
|||
|
if (dir) oldY = y;
|
|||
|
|
|||
|
return dir;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function findDropTargetRow(draggedRow, y)
|
|||
|
{
|
|||
|
var row, rowY;
|
|||
|
var rows = recountRows(table);
|
|||
|
var rowsCount = table.data('rowsCount');
|
|||
|
|
|||
|
for (var i = 0; i < rowsCount; i++)
|
|||
|
{
|
|||
|
row = rows.eq(i);
|
|||
|
rowY = row.offset().top;
|
|||
|
|
|||
|
if (y >= rowY && y <= rowY + row.outerHeight()) return draggedRow.is(row) ? null : row;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
function mouseUp(e)
|
|||
|
{
|
|||
|
if (!dragObject) return null;
|
|||
|
e.preventDefault();
|
|||
|
|
|||
|
$(document).off(eventMove + ' ' + eventEnd);
|
|||
|
|
|||
|
toggleObjectClass(dragObject);
|
|||
|
dragObject = null;
|
|||
|
|
|||
|
$('html').add('.tablesort-dragging').removeClass('tablesort-dragging');
|
|||
|
|
|||
|
if (opts.onChange) opts.onChange.call(table);
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
return table;
|
|||
|
});
|
|||
|
}
|
|||
|
})(jQuery);
|