From 60bf786a3a765b7a9f9ed81d65c8472e550edcff Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Wed, 17 Jul 2013 10:20:24 +0000 Subject: [PATCH] Ox.List: add support for moving a (potentially discontinuous) selection of multiple items --- source/Ox.UI/js/List/List.js | 102 ++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 38 deletions(-) diff --git a/source/Ox.UI/js/List/List.js b/source/Ox.UI/js/List/List.js index f5458568..db066148 100644 --- a/source/Ox.UI/js/List/List.js +++ b/source/Ox.UI/js/List/List.js @@ -649,7 +649,6 @@ Ox.List = function(options, self) { } function getPositionById(id) { - // fixme: is this really needed? var pos = -1; Ox.forEach(self.$items, function($item, i) { if ($item.options('data')[self.options.unique] == id) { @@ -934,62 +933,89 @@ Ox.List = function(options, self) { } function movestart(data) { - self.drag = { - pos: findItemPosition(data) - }; - Ox.extend(self.drag, { - id: self.$items[self.drag.pos].options('data')[self.options.unique], - startPos: self.drag.pos, - startY: data.clientY, - stopPos: self.drag.pos - }); - self.$items[self.drag.pos] - .addClass('OxDrag') - .css({ - cursor: 'move' + var pos = findItemPosition(data), + $items = self.$items.filter(function($item, i) { + if ($item.is('.OxSelected')) { + $item.addClass('OxDrag'); + return true; + } + return false; }); + self.drag = { + $items: $items, + index: Ox.indexOf($items, function($item) { + return $item.options('position') == pos; + }), + length: $items.length, + startPos: pos, + startY: data.clientY, + stopPos: pos + }; } function move(data) { - var clientY = data.clientY - that.offset()['top'], + var clientY = data.clientY - that.offset().top, offset = clientY % 16, - position = Ox.limit(Math.floor(clientY / 16), 0, self.$items.length - 1); - if (position < self.drag.pos) { + position = Ox.limit( + Math.floor(clientY / 16), + 0, self.$items.length - 1 + ); + if (position < self.drag.startPos) { self.drag.stopPos = position + (offset > 8 ? 1 : 0); - } else if (position > self.drag.pos) { + } else if (position > self.drag.startPos) { self.drag.stopPos = position - (offset <= 8 ? 1 : 0); } - if (self.drag.stopPos != self.drag.pos) { - moveItem(self.drag.pos, self.drag.stopPos); - self.drag.pos = self.drag.stopPos; + if (self.drag.stopPos != self.drag.startPos) { + moveItems(self.drag.startPos, self.drag.stopPos); + self.drag.startPos = self.drag.stopPos; } } function moveend(data) { - self.$items[self.drag.pos] - .removeClass('OxDrag') - .css({ - cursor: 'default' - }); - that.triggerEvent('move', { - ids: self.$items.map(function($item) { - return $item.options('data')[self.options.unique]; - }) + var ids = []; + self.$items.forEach(function($item) { + $item.removeClass('OxDrag'); + ids.push($item.options('data')[self.options.unique]); }); + that.triggerEvent('move', {ids: ids}); delete self.drag; } - function moveItem(startPos, stopPos) { - var $item = self.$items[startPos], - insert = startPos < stopPos ? 'insertAfter' : 'insertBefore'; - $item.detach()[insert](self.$items[stopPos].$element); // fixme: why do we need .$element here? - //Ox.Log('List', 'moveItem', startPos, stopPos, insert, self.ids); - var $item = self.$items.splice(startPos, 1)[0]; - self.$items.splice(stopPos, 0, $item); + function moveItems(startPos, stopPos) { + var pos = stopPos; + while (self.$items[pos].is('.OxSelected')) { + pos = pos + (pos < startPos ? -1 : 1); + if (pos < 0 || pos > self.$items.length - 1) { + // handle item can still be moved, but group cannot + return; + } + } + self.drag.$items.forEach(function($item) { + $item.detach(); + }); + self.drag.$items.forEach(function($item, i) { + if (i == 0) { + $item[ + pos < startPos ? 'insertBefore' : 'insertAfter' + ](self.$items[pos].$element); // fixme: shouldn't require $element + } else { + $item.insertAfter(self.drag.$items[i - 1]); + } + }); + self.drag.$items.forEach(function($item, i) { + self.$items.splice($item.options('position') - i, 1); + }); + self.$items.splice.apply( + self.$items, + [stopPos - self.drag.index, 0].concat(self.drag.$items) + ); self.$items.forEach(function($item, pos) { $item.options({position: pos}); }); - self.selected = [stopPos]; + self.selected = []; + self.drag.$items.forEach(function($item) { + self.selected.push($item.options('position')); + }); } function open(isSpecialTarget) {