From 1532421bdf2421e93871ac7fd9be295d0bf64828 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 8 Jan 2015 07:18:31 +0200 Subject: [PATCH 1/6] test: disable debugInfo on all tests --- test/sortable.e2e.callbacks.spec.js | 6 ++++++ test/sortable.e2e.directiveoptions.spec.js | 6 ++++++ test/sortable.e2e.directives.spec.js | 6 ++++++ test/sortable.e2e.multi.spec.js | 6 ++++++ test/sortable.e2e.nested.spec.js | 6 ++++++ test/sortable.e2e.spec.js | 6 ++++++ test/sortable.spec.js | 6 ++++++ 7 files changed, 42 insertions(+) diff --git a/test/sortable.e2e.callbacks.spec.js b/test/sortable.e2e.callbacks.spec.js index 50b182b..f56af64 100644 --- a/test/sortable.e2e.callbacks.spec.js +++ b/test/sortable.e2e.callbacks.spec.js @@ -2,6 +2,12 @@ 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')); diff --git a/test/sortable.e2e.directiveoptions.spec.js b/test/sortable.e2e.directiveoptions.spec.js index bd2461c..9eba4b8 100644 --- a/test/sortable.e2e.directiveoptions.spec.js +++ b/test/sortable.e2e.directiveoptions.spec.js @@ -2,6 +2,12 @@ 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')); diff --git a/test/sortable.e2e.directives.spec.js b/test/sortable.e2e.directives.spec.js index 1c071a4..3292944 100644 --- a/test/sortable.e2e.directives.spec.js +++ b/test/sortable.e2e.directives.spec.js @@ -2,6 +2,12 @@ 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')); diff --git a/test/sortable.e2e.multi.spec.js b/test/sortable.e2e.multi.spec.js index efaed48..5149f86 100644 --- a/test/sortable.e2e.multi.spec.js +++ b/test/sortable.e2e.multi.spec.js @@ -2,6 +2,12 @@ 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')); diff --git a/test/sortable.e2e.nested.spec.js b/test/sortable.e2e.nested.spec.js index ba10be9..874ba8c 100644 --- a/test/sortable.e2e.nested.spec.js +++ b/test/sortable.e2e.nested.spec.js @@ -2,6 +2,12 @@ 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')); diff --git a/test/sortable.e2e.spec.js b/test/sortable.e2e.spec.js index 987a3e7..735d2e7 100644 --- a/test/sortable.e2e.spec.js +++ b/test/sortable.e2e.spec.js @@ -2,6 +2,12 @@ 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')); diff --git a/test/sortable.spec.js b/test/sortable.spec.js index ea99908..fd664bd 100644 --- a/test/sortable.spec.js +++ b/test/sortable.spec.js @@ -2,6 +2,12 @@ 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')); From 9520c989a812703a8b7a23b5da4abbbca6eab98c Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sat, 10 Jan 2015 17:04:28 +0200 Subject: [PATCH 2/6] test: rewrite tests to work whith disabled debugInfo --- test/sortable.e2e.callbacks.spec.js | 12 +++---- test/sortable.e2e.multi.spec.js | 52 ++++++++++++++++------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/test/sortable.e2e.callbacks.spec.js b/test/sortable.e2e.callbacks.spec.js index f56af64..ae4ceb5 100644 --- a/test/sortable.e2e.callbacks.spec.js +++ b/test/sortable.e2e.callbacks.spec.js @@ -41,7 +41,7 @@ describe('uiSortable', function() { $rootScope.$apply(function() { $rootScope.opts = { update: function(e, ui) { - if (ui.item.scope().item === 'Two') { + if (ui.item.sortable.model === 'Two') { ui.item.sortable.cancel(); } } @@ -83,7 +83,7 @@ describe('uiSortable', function() { return item; }, update: function(e, ui) { - if (ui.item.scope().item === 'Two') { + if (ui.item.sortable.model === 'Two') { ui.item.sortable.cancel(); } } @@ -123,7 +123,7 @@ describe('uiSortable', function() { $rootScope.$apply(function() { $rootScope.opts = { update: function(e, ui) { - $rootScope.logs.push('Moved element ' + ui.item.scope().item); + $rootScope.logs.push('Moved element ' + ui.item.sortable.model); } }; $rootScope.items = ['One', 'Two', 'Three']; @@ -154,7 +154,7 @@ describe('uiSortable', function() { $rootScope.$apply(function() { $rootScope.opts = { stop: function(e, ui) { - $rootScope.logs.push('Moved element ' + ui.item.scope().item); + $rootScope.logs.push('Moved element ' + ui.item.sortable.model); } }; $rootScope.items = ['One', 'Two', 'Three']; @@ -205,7 +205,7 @@ describe('uiSortable', function() { $rootScope.$apply(function() { $rootScope.opts = { update: function(e, ui) { - if (ui.item.scope().item === 'Two') { + if (ui.item.sortable.model === 'Two') { ui.item.sortable.cancel(); } updateCallbackExpectations(ui.item.sortable); @@ -282,7 +282,7 @@ describe('uiSortable', function() { uiItemSortable_Destroy = ui.item.sortable._destroy; }, update: function(e, ui) { - if (ui.item.scope().item === 'Two') { + if (ui.item.sortable.model === 'Two') { ui.item.sortable.cancel(); } } diff --git a/test/sortable.e2e.multi.spec.js b/test/sortable.e2e.multi.spec.js index 5149f86..bf2c0e0 100644 --- a/test/sortable.e2e.multi.spec.js +++ b/test/sortable.e2e.multi.spec.js @@ -74,14 +74,17 @@ describe('uiSortable', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom, wrapperTop, wrapperBottom, + wrapperTopScope, wrapperBottomScope, itemsTop, itemsBottom; - wrapperTop = $compile('
  • {{ item }}
')($rootScope); - wrapperBottom = $compile('
  • {{ item }}
')($rootScope); + wrapperTopScope = $rootScope.$new(); + wrapperBottomScope = $rootScope.$new(); + wrapperTop = $compile('
  • {{ item }}
')(wrapperTopScope); + wrapperBottom = $compile('
  • {{ item }}
')(wrapperBottomScope); host.append(wrapperTop).append(wrapperBottom).append('
'); $rootScope.$apply(function() { - wrapperTop.scope().itemsTop = itemsTop = ['Top One', 'Top Two', 'Top Three']; - wrapperBottom.scope().itemsBottom = itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; + wrapperTopScope.itemsTop = itemsTop = ['Top One', 'Top Two', 'Top Three']; + wrapperBottomScope.itemsBottom = itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable' }; }); @@ -468,9 +471,9 @@ describe('uiSortable', function() { $rootScope.opts = { connectWith: '.cross-sortable', update: function(e, ui) { - if (ui.item.scope() && - (typeof ui.item.scope().item === 'string') && - ui.item.scope().item.indexOf('Two') >= 0) { + if (ui.item.sortable.model && + (typeof ui.item.sortable.model === 'string') && + ui.item.sortable.model.indexOf('Two') >= 0) { ui.item.sortable.cancel(); } } @@ -527,9 +530,9 @@ describe('uiSortable', function() { $rootScope.opts = { connectWith: '.cross-sortable', update: function(e, ui) { - if (ui.item.scope() && - (typeof ui.item.scope().item === 'string') && - ui.item.scope().item.indexOf('Two') >= 0) { + if (ui.item.sortable.model && + (typeof ui.item.sortable.model === 'string') && + ui.item.sortable.model.indexOf('Two') >= 0) { ui.item.sortable.cancel(); } updateCallbackExpectations(ui.item.sortable); @@ -666,9 +669,9 @@ describe('uiSortable', function() { $rootScope.opts = { connectWith: '.cross-sortable', update: function(e, ui) { - if (ui.item.scope() && - (typeof ui.item.scope().item === 'string') && - ui.item.scope().item.indexOf('Two') >= 0) { + if (ui.item.sortable.model && + (typeof ui.item.sortable.model === 'string') && + ui.item.sortable.model.indexOf('Two') >= 0) { ui.item.sortable.cancel(); } updateCallbackExpectations(ui.item.sortable); @@ -735,21 +738,24 @@ describe('uiSortable', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom, wrapperTop, wrapperBottom, + wrapperTopScope, wrapperBottomScope, itemsTop, itemsBottom, updateCallbackExpectations; - wrapperTop = $compile('
  • {{ item }}
')($rootScope); - wrapperBottom = $compile('
  • {{ item }}
')($rootScope); + wrapperTopScope = $rootScope.$new(); + wrapperBottomScope = $rootScope.$new(); + wrapperTop = $compile('
  • {{ item }}
')(wrapperTopScope); + wrapperBottom = $compile('
  • {{ item }}
')(wrapperBottomScope); host.append(wrapperTop).append(wrapperBottom).append('
'); $rootScope.$apply(function() { - wrapperTop.scope().itemsTop = itemsTop = ['Top One', 'Top Two', 'Top Three']; - wrapperBottom.scope().itemsBottom = itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; + wrapperTopScope.itemsTop = itemsTop = ['Top One', 'Top Two', 'Top Three']; + wrapperBottomScope.itemsBottom = itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable', update: function(e, ui) { - if (ui.item.scope() && - (typeof ui.item.scope().item === 'string') && - ui.item.scope().item.indexOf('Two') >= 0) { + if (ui.item.sortable.model && + (typeof ui.item.sortable.model === 'string') && + ui.item.sortable.model.indexOf('Two') >= 0) { ui.item.sortable.cancel(); } updateCallbackExpectations(ui.item.sortable); @@ -830,9 +836,9 @@ describe('uiSortable', function() { }, update: function(e, ui) { uiItem.sortable = ui.item.sortable; - if (ui.item.scope() && - (typeof ui.item.scope().item === 'string') && - ui.item.scope().item.indexOf('Two') >= 0) { + if (ui.item.sortable.model && + (typeof ui.item.sortable.model === 'string') && + ui.item.sortable.model.indexOf('Two') >= 0) { ui.item.sortable.cancel(); } } From 3dcefe9700401ce67d3238580642b0e10b44d797 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sun, 11 Jan 2015 22:01:59 +0200 Subject: [PATCH 3/6] test: add data-ng-repeat test --- test/sortable.e2e.spec.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/sortable.e2e.spec.js b/test/sortable.e2e.spec.js index 735d2e7..1be9306 100644 --- a/test/sortable.e2e.spec.js +++ b/test/sortable.e2e.spec.js @@ -166,6 +166,35 @@ describe('uiSortable', function() { }); }); + it('should work when "placeholder" option equals the class of items [data-ng-repeat]', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile('
  • {{ item }}
')($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 = (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(1)'); + 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; From c023e32d1ed8483279afc639dfbde0eb6bd3a265 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 8 Jan 2015 22:33:36 +0200 Subject: [PATCH 4/6] feat(sortable): add support for the case that debugInfo is disabled --- src/sortable.js | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 400ee15..10b4bd6 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -47,6 +47,16 @@ angular.module('ui.sortable', []) return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display')); } + function getElementScope(elementScopes, element) { + for (var i = 0; i < elementScopes.length; i++) { + var x = elementScopes[i]; + if (x.element[0] === element[0]) { + return x.scope; + } + } + return null; + } + function afterStop(e, ui) { ui.item.sortable._destroy(); } @@ -126,7 +136,7 @@ angular.module('ui.sortable', []) }; }; - callbacks.activate = function(/*e, ui*/) { + callbacks.activate = function(e, ui) { // We need to make a copy of the current element's contents so // we can restore it after sortable has messed it up. // This is inside activate (instead of start) in order to save @@ -151,10 +161,20 @@ angular.module('ui.sortable', []) // exact match with the placeholder's class attribute to handle // the case that multiple connected sortables exist and // the placehoilder option equals the class of sortable items - var excludes = element.find('[class="' + phElement.attr('class') + '"]'); + var excludes = element.find('[class="' + phElement.attr('class') + '"]:not([ng-repeat], [data-ng-repeat])'); savedNodes = savedNodes.not(excludes); } + + // save the directive's scope so that it is accessible from ui.item.sortable + var connectedSortables = ui.item.sortable._connectedSortables || []; + + connectedSortables.push({ + element: element, + scope: scope + }); + + ui.item.sortable._connectedSortables = connectedSortables; }; callbacks.update = function(e, ui) { @@ -165,8 +185,9 @@ angular.module('ui.sortable', []) ui.item.sortable.dropindex = ui.item.index(); var droptarget = ui.item.parent(); ui.item.sortable.droptarget = droptarget; - var attr = droptarget.attr('ng-model') || droptarget.attr('data-ng-model'); - ui.item.sortable.droptargetModel = droptarget.scope().$eval(attr); + + var droptargetScope = getElementScope(ui.item.sortable._connectedSortables, droptarget); + ui.item.sortable.droptargetModel = droptargetScope.ngModel; // Cancel the sort (let ng-repeat do the sort for us) // Don't cancel if this is the received list because it has From 9ef46229180f910e4bf4c0bfb142f94ec94b758b Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 15 Jan 2015 07:51:21 +0200 Subject: [PATCH 5/6] refactor(sortable): change getElementScope to increase code coverage --- src/sortable.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 10b4bd6..866f78d 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -48,13 +48,15 @@ angular.module('ui.sortable', []) } function getElementScope(elementScopes, element) { + var result = null; for (var i = 0; i < elementScopes.length; i++) { var x = elementScopes[i]; if (x.element[0] === element[0]) { - return x.scope; + result = x.scope; + break; } } - return null; + return result; } function afterStop(e, ui) { From b6734fe6ed1f4dd31e008f12be06c22c4bf6ee21 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sat, 17 Jan 2015 19:57:50 +0200 Subject: [PATCH 6/6] refactor(sortable): use the shorthand isolated scope property definition --- src/sortable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 866f78d..85f1f74 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -11,8 +11,8 @@ angular.module('ui.sortable', []) return { require: '?ngModel', scope: { - ngModel: '=ngModel', - uiSortable: '=uiSortable' + ngModel: '=', + uiSortable: '=' }, link: function(scope, element, attrs, ngModel) { var savedNodes;