From c3f19b125af38aad5498aac964b642a61bd36f3d Mon Sep 17 00:00:00 2001 From: Tom Yam Date: Thu, 26 Mar 2015 14:59:25 +0200 Subject: [PATCH] feat(sortable): allow extra element before/after ng-repeat Fixes #41, Fixed #177, Fixed #98 and Fixes #207 --- src/sortable.js | 33 +- test/sortable.e2e.extraElements.spec.js | 716 ++++++++++++++++++++++++ test/sortable.test-helper.js | 2 +- 3 files changed, 746 insertions(+), 5 deletions(-) create mode 100644 test/sortable.e2e.extraElements.spec.js diff --git a/src/sortable.js b/src/sortable.js index 14c2679..1a59bef 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -63,7 +63,25 @@ angular.module('ui.sortable', []) ui.item.sortable._destroy(); } - var opts = {}; + // return the index of ui.item among the items + // we can't just do ui.item.index() because there it might have siblings + // which are not items + function getItemIndex(ui) { + return ui.item.parent().find('> [ng-repeat], > [data-ng-repeat], > [x-ng-repeat]') + .index(ui.item); + } + + // restrict the items option to include only ng-repeat items + function restrictItemsOption(items) { + items = items.trim(); + return items + '[ng-repeat],' + items + '[data-ng-repeat],' + items + '[x-ng-repeat]'; + } + + var opts = { + // this is jquery-ui sortable's default, we state it explicitly so even + // if it's not specified, we will apply restrictItemsOption on it + items: '> *' + }; // directive specific options var directiveOpts = { @@ -84,6 +102,8 @@ angular.module('ui.sortable', []) angular.extend(opts, directiveOpts, uiSortableConfig, scope.uiSortable); + opts.items = restrictItemsOption(opts.items); + if (!angular.element.fn || !angular.element.fn.jquery) { $log.error('ui.sortable: jQuery should be included before AngularJS!'); return; @@ -114,9 +134,10 @@ angular.module('ui.sortable', []) } // Save the starting position of dragged item + var index = getItemIndex(ui); ui.item.sortable = { - model: ngModel.$modelValue[ui.item.index()], - index: ui.item.index(), + model: ngModel.$modelValue[index], + index: index, source: ui.item.parent(), sourceModel: ngModel.$modelValue, cancel: function () { @@ -184,7 +205,7 @@ angular.module('ui.sortable', []) // update that happens when moving between lists because then // the value will be overwritten with the old value if(!ui.item.sortable.received) { - ui.item.sortable.dropindex = ui.item.index(); + ui.item.sortable.dropindex = getItemIndex(ui); var droptarget = ui.item.parent(); ui.item.sortable.droptarget = droptarget; @@ -325,6 +346,10 @@ angular.module('ui.sortable', []) value = wrappers[key](value); } + if (key === 'items') { + value = restrictItemsOption(value); + } + opts[key] = value; element.sortable('option', key, value); }); diff --git a/test/sortable.e2e.extraElements.spec.js b/test/sortable.e2e.extraElements.spec.js new file mode 100644 index 0000000..3e36421 --- /dev/null +++ b/test/sortable.e2e.extraElements.spec.js @@ -0,0 +1,716 @@ +'use strict'; + +describe('uiSortable', function() { + + beforeEach(module(function($compileProvider) { + if (typeof $compileProvider.debugInfoEnabled === 'function') { + $compileProvider.debugInfoEnabled(false); + } + })); + + // Ensure the sortable angular module is loaded + beforeEach(module('ui.sortable')); + beforeEach(module('ui.sortable.testHelper')); + + var EXTRA_DY_PERCENTAGE, listContent, listInnerContent; + + beforeEach(inject(function (sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + listInnerContent = sortableTestHelper.listInnerContent; + })); + + describe('Drag & Drop simulation, when there are extra elements', function() { + + var host; + + beforeEach(inject(function() { + host = $('
'); + $('body').append(host); + })); + + afterEach(function() { + host.remove(); + host = null; + }); + + it('should update model when order changes', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(2)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should not allow sorting of "locked" nodes', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + items:'> .sortable' + }; + $rootScope.items = [ + { text: 'One', sortable: true }, + { text: 'Two', sortable: true }, + { text: 'Three', sortable: false }, + { text: 'Four', sortable: true } + ]; + }); + + host.append(element); + + var li = element.find(':eq(3)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items.map(function(x){ return x.text; })).toEqual(['One', 'Two', 'Three', 'Four']); + expect($rootScope.items.map(function(x){ return x.text; })).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items.map(function(x){ return x.text; })).toEqual(['One', 'Three', 'Four', 'Two']); + expect($rootScope.items.map(function(x){ return x.text; })).toEqual(listContent(element)); + + li = element.find(':eq(3)'); + dy = -(2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items.map(function(x){ return x.text; })).toEqual(['Four', 'One', 'Three', 'Two']); + expect($rootScope.items.map(function(x){ return x.text; })).toEqual(listContent(element)); + + li = element.find(':eq(4)'); + dy = -(2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items.map(function(x){ return x.text; })).toEqual(['Four', 'Two', 'One', 'Three']); + expect($rootScope.items.map(function(x){ return x.text; })).toEqual(listContent(element)); + + // also placing right above the locked node seems a bit harder !?!? + + $(element).remove(); + }); + }); + + it('should work when "placeholder" option is used', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + placeholder: 'sortable-item-placeholder' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(2)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "placeholder" option equals the class of items', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + placeholder: 'sortable-item' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(2)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "placeholder" option equals the class of items [data-ng-repeat]', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + placeholder: 'sortable-item' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(2)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should continue to work after a drag is reverted', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + placeholder: 'sortable-item' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(1)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(1)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "handle" option is used', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + handle: '.handle' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find('li:eq(1)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.find('.handle').simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + li = element.find('li:eq(1)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.find('.handle').simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + $(element).remove(); + }); + }); + + it('should properly remove elements after a sorting', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + handle: '.handle' + }; + $rootScope.items = ['One', 'Two', 'Three']; + + $rootScope.remove = function (item, itemIndex) { + $rootScope.items.splice(itemIndex, 1); + }; + }); + + host.append(element); + + var li = element.find('li:eq(1)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.find('.handle').simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + li = element.find('li:eq(1)'); + li.find('.removeButton').click(); + expect($rootScope.items).toEqual(['One', 'Two']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + li = element.find('li:eq(0)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.find('.handle').simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + li = element.find('li:eq(0)'); + li.find('.removeButton').click(); + expect($rootScope.items).toEqual(['One']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + $(element).remove(); + }); + }); + + it('should properly remove elements after a drag is reverted', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + handle: '.handle' + }; + $rootScope.items = ['One', 'Two', 'Three']; + + $rootScope.remove = function (item, itemIndex) { + $rootScope.items.splice(itemIndex, 1); + }; + }); + + host.append(element); + + var li = element.find('li:eq(0)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.find('.handle').simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + li = element.find('li:eq(0)'); + li.find('.removeButton').click(); + expect($rootScope.items).toEqual(['Two', 'Three']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + li = element.find('li:eq(0)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.find('.handle').simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'Two']); + expect($rootScope.items).toEqual(listInnerContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: clone" option is used', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: 'clone' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(2)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: clone" option is used and a drag is reverted', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: 'clone' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(1)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(1)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: clone" and "appendTo" options are used together', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: 'clone', + appendTo: 'body' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(2)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(3)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: clone" and "placeholder" options are used together.', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: 'clone', + placeholder: 'sortable-item' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(1)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(1)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: function" option is used', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: function (e, item) { + return item.clone().text('helper'); + } + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(2)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: function" option is used and a drag is reverted', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: function (e, item) { + return item.clone().text('helper'); + } + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(1)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(1)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: function" and "placeholder" options are used together.', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: function (e, item) { + return item.clone().text('helper'); + }, + placeholder: 'sortable-item' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(1)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(1)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: function" that returns a list element is used', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: function (e, item) { + return item; + } + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(1)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(1)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + it('should work when "helper: function" that returns a list element and "placeholder" options are used together.', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('')($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: function (e, item) { + return item; + }, + placeholder: 'sortable-item' + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find(':eq(1)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Two', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(1)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('dragAndRevert', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + li = element.find(':eq(2)'); + dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'One', 'Three']); + expect($rootScope.items).toEqual(listContent(element)); + + $(element).remove(); + }); + }); + + }); + +}); diff --git a/test/sortable.test-helper.js b/test/sortable.test-helper.js index 5728d49..8cae026 100644 --- a/test/sortable.test-helper.js +++ b/test/sortable.test-helper.js @@ -6,7 +6,7 @@ angular.module('ui.sortable.testHelper', []) function listContent (list) { if (list && list.length) { - return list.children().map(function(){ return this.innerHTML; }).toArray(); + return list.children('[ng-repeat], [data-ng-repeat], [x-ng-repeat]').map(function(){ return this.innerHTML; }).toArray(); } return []; }