Browse Source

Swap Feature

This is a rough implementation of a swapping feature. Setting the new "swap" option to true will cause a dragged item to be swapped with the item you drop it on (instead of inserted next to it). The item being hovered over (and potentially swapped with) will be highlighted by adding the class specified in the new "swapHighlightClass" option (defaults to "sortable-swap-highlight"). When swapping is enabled, the "end" event's "to" property will be set to the item being dropped on and swapped with.

It's a bit hackish, but it works as a solution to issues #1211, #1082, #1072, #891, #869, and #469. Maybe it can at least serve as a starting off point to adding this feature to master eventually? Thanks!
pull/1274/head
Ken 7 years ago committed by GitHub
parent
commit
aa6e99ef9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 58
      Sortable.js

58
Sortable.js

@ -261,6 +261,7 @@
var defaults = { var defaults = {
group: null, group: null,
sort: true, sort: true,
swap: false,
disabled: false, disabled: false,
store: null, store: null,
handle: null, handle: null,
@ -271,6 +272,7 @@
ghostClass: 'sortable-ghost', ghostClass: 'sortable-ghost',
chosenClass: 'sortable-chosen', chosenClass: 'sortable-chosen',
dragClass: 'sortable-drag', dragClass: 'sortable-drag',
swapHighlightClass: 'sortable-swap-highlight',
ignore: 'a, img', ignore: 'a, img',
filter: null, filter: null,
preventOnFilter: true, preventOnFilter: true,
@ -860,12 +862,23 @@
_cloneHide(activeSortable, isOwner); _cloneHide(activeSortable, isOwner);
if (!dragEl.contains(el)) { if (!dragEl.contains(el)) {
if (this.options.swap)
{
var elements = document.getElementsByClassName(this.options.swapHighlightClass);
while(elements.length > 0){
_toggleClass(elements[0], this.options.swapHighlightClass, false);
}
_toggleClass(target, this.options.swapHighlightClass, true);
}
else
{
if (after && !nextSibling) { if (after && !nextSibling) {
el.appendChild(dragEl); el.appendChild(dragEl);
} else { } else {
target.parentNode.insertBefore(dragEl, after ? nextSibling : target); target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
} }
} }
}
parentEl = dragEl.parentNode; // actualization parentEl = dragEl.parentNode; // actualization
@ -969,6 +982,24 @@
// Drag stop event // Drag stop event
_dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex, null, evt); _dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex, null, evt);
if (this.options.swap)
{
var elements = document.getElementsByClassName(this.options.swapHighlightClass);
var dropEl = null;
while(elements.length > 0){
dropEl = elements[0];
_toggleClass(elements[0], this.options.swapHighlightClass, false);
}
if (dropEl)
{
_swapNodes(dragEl, dropEl);
newIndex = _index(dragEl, options.draggable);
_dispatchEvent(this, rootEl, 'end', dragEl, dropEl, rootEl, oldIndex, newIndex);
}
}
else
{
if (rootEl !== parentEl) { if (rootEl !== parentEl) {
newIndex = _index(dragEl, options.draggable); newIndex = _index(dragEl, options.draggable);
@ -1009,6 +1040,7 @@
this.save(); this.save();
} }
} }
}
} }
@ -1512,6 +1544,32 @@
return clearTimeout(id); return clearTimeout(id);
} }
function _swapNodes(n1, n2) {
var p1 = n1.parentNode;
var p2 = n2.parentNode;
var i1, i2;
if ( !p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1) ) return;
for (var i = 0; i < p1.children.length; i++) {
if (p1.children[i].isEqualNode(n1)) {
i1 = i;
}
}
for (var i = 0; i < p2.children.length; i++) {
if (p2.children[i].isEqualNode(n2)) {
i2 = i;
}
}
if ( p1.isEqualNode(p2) && i1 < i2 ) {
i2++;
}
p1.insertBefore(n2, p1.children[i1]);
p2.insertBefore(n1, p2.children[i2]);
}
// Fixed #973: // Fixed #973:
_on(document, 'touchmove', function (evt) { _on(document, 'touchmove', function (evt) {
if (Sortable.active) { if (Sortable.active) {

Loading…
Cancel
Save