From 2a409d5cab1ab3cbf2d2cb7c40742b4e02391ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Andr=C3=A9?= Date: Tue, 6 Dec 2016 18:23:19 -0300 Subject: [PATCH 01/41] introducing a $emit when a transaction finish --- src/sortable.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sortable.js b/src/sortable.js index c22c1bd..2ff8060 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -406,6 +406,9 @@ angular.module('ui.sortable', []) // It's now safe to clear the savedNodes // since stop is the last callback. savedNodes = null; + + //notifiy when sortable finished + scope.$emit('sortable:finished'); }; callbacks.receive = function(e, ui) { From 1be1ed01b8d5fba770ba5ba66a6afb27676d9d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Andr=C3=A9?= Date: Thu, 8 Dec 2016 09:40:55 -0300 Subject: [PATCH 02/41] notify parent when was moved (performance refactor) --- src/sortable.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 2ff8060..cc8a6d7 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -370,6 +370,11 @@ angular.module('ui.sortable', []) ui.item.sortable.moved); }); } + + if(wasMoved && !ui.item.sortable.received){ + scope.$emit('sortable:wasMoved'); + } + }; callbacks.stop = function(e, ui) { @@ -406,9 +411,6 @@ angular.module('ui.sortable', []) // It's now safe to clear the savedNodes // since stop is the last callback. savedNodes = null; - - //notifiy when sortable finished - scope.$emit('sortable:finished'); }; callbacks.receive = function(e, ui) { From c387ba540e12869b4b33b863d308dee53fda84f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20Andr=C3=A9?= Date: Thu, 8 Dec 2016 09:50:29 -0300 Subject: [PATCH 03/41] notify parent when was moved (performance refactor) fix --- src/sortable.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sortable.js b/src/sortable.js index cc8a6d7..128f2a2 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -322,6 +322,10 @@ angular.module('ui.sortable', []) // Save current drop position but only if this is not a second // update that happens when moving between lists because then // the value will be overwritten with the old value + + var wasMoved = ('dropindex' in ui.item.sortable) && + !ui.item.sortable.isCanceled(); + if(!ui.item.sortable.received) { ui.item.sortable.dropindex = getItemIndex(ui.item); var droptarget = ui.item.closest('[ui-sortable]'); From f275977f6dc6a7dc5371d0be902d1772cd5b806f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Aky=C4=B1ld=C4=B1z?= Date: Thu, 5 Jan 2017 17:23:01 +0300 Subject: [PATCH 04/41] Html attribute based event handling Event handle on html attribute tag. Readme.md updated. --- README.md | 36 ++++++++++++++++++++++++++++++++++++ src/sortable.js | 31 ++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f20543e..1e28fec 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,42 @@ To provide a solution/workaround (till jquery.ui.sortable.refresh() also tests t ``` + +#### Attributes For Event Handling + +To handle events with html bindings just define any expression to listed event attributes. +If you defined an attribute for this events and defined callback function in sortableOptions at the same time attribute based callback will be selected. +If attribute based callback expression is not filled then sortableOption based callback function will be selected. + +* **ui-sortable-receive** +* **ui-sortable-remove** +* **ui-sortable-start** +* **ui-sortable-stop** +* **ui-sortable-update** + + + +Expression works on update event. +```html +
    +
  • {{ item }}
  • +
+``` + + +callBackFunction2 works on update event. +```js +$scope.sortableOptions = { + 'update': callBackFunction +}; +``` +```html +
    +
  • {{ item }}
  • +
+``` + + **OR** ```js diff --git a/src/sortable.js b/src/sortable.js index 6ee75db..e79cf6d 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -16,8 +16,13 @@ angular.module('ui.sortable', []) return { require: '?ngModel', scope: { - ngModel: '=', - uiSortable: '=' + ngModel: '=', + uiSortable: '=', + receive :'&uiSortableReceive',//Expression bindings from html. + remove :'&uiSortableRemove', + start :'&uiSortableStart', + stop :'&uiSortableStop', + update :'&uiSortableUpdate' }, link: function(scope, element, attrs, ngModel) { var savedNodes; @@ -125,9 +130,25 @@ angular.module('ui.sortable', []) opts[key] = patchSortableOption(key, value); return; } - - value = patchSortableOption(key, value); - + + + /* + * If user defines ui-sortable-callback for @key and callback based option at the same time the html based ui-sortable-callback expression will be selected. (Overridden) + * If user defined ui-sortable-callback for @key but callback expression is empty then option based @key callback will be selected. + * If user not defines a option for @key callback then html based ui-sortable-callback will be just selected. + * If user just defines option for @key callback then it will be attached. + * */ + var attrKey = 'uiSortable'+key.substring(0,1).toUpperCase()+key.substring(1); + if(scope[key]!=undefined && scope[key] instanceof Function && attrs[attrKey] != undefined && attrs[attrKey].length > 0) + { + value = patchSortableOption(key, scope[key]); + } + else + { + value = patchSortableOption(key, value); + } + + if (!optsDiff) { optsDiff = {}; } From 6efeec26cf039a0b56cc81bb26515826a4192e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Aky=C4=B1ld=C4=B1z?= Date: Fri, 6 Jan 2017 10:46:19 +0300 Subject: [PATCH 05/41] Attribute callbacks capsulated Attribute callbacks capsulated with a function. This function has try-catch scope and calls scope.received function by default. Syntax warnings are cleared. --- src/sortable.js | 63 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index e79cf6d..9532ee8 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -14,15 +14,16 @@ angular.module('ui.sortable', []) 'uiSortableConfig', '$timeout', '$log', function(uiSortableConfig, $timeout, $log) { return { - require: '?ngModel', + require:'?ngModel', scope: { - ngModel: '=', - uiSortable: '=', - receive :'&uiSortableReceive',//Expression bindings from html. - remove :'&uiSortableRemove', - start :'&uiSortableStart', - stop :'&uiSortableStop', - update :'&uiSortableUpdate' + ngModel:'=', + uiSortable:'=', + receive:'&uiSortableReceive',//Expression bindings from html. + remove:'&uiSortableRemove', + start:'&uiSortableStart', + stop:'&uiSortableStop', + update:'&uiSortableUpdate', + received :'&uiSortableReceived' }, link: function(scope, element, attrs, ngModel) { var savedNodes; @@ -132,21 +133,41 @@ angular.module('ui.sortable', []) } - /* - * If user defines ui-sortable-callback for @key and callback based option at the same time the html based ui-sortable-callback expression will be selected. (Overridden) - * If user defined ui-sortable-callback for @key but callback expression is empty then option based @key callback will be selected. - * If user not defines a option for @key callback then html based ui-sortable-callback will be just selected. - * If user just defines option for @key callback then it will be attached. - * */ - var attrKey = 'uiSortable'+key.substring(0,1).toUpperCase()+key.substring(1); - if(scope[key]!=undefined && scope[key] instanceof Function && attrs[attrKey] != undefined && attrs[attrKey].length > 0) + /* + * If user defines ui-sortable-callback for @key and callback based option at the same time the html based ui-sortable-callback expression will be selected. (Overridden) + * If user defined ui-sortable-callback for @key but callback expression is empty then option based @key callback will be selected. + * If user not defines a option for @key callback then html based ui-sortable-callback will be just selected. + * If user just defines option for @key callback then it will be attached. + * */ + var attrKey = 'uiSortable'+key.substring(0,1).toUpperCase()+key.substring(1); + if(scope[key]!==undefined && scope[key] instanceof Function && attrs[attrKey] !== undefined && attrs[attrKey].length > 0) + { + + var expression = scope[key]; //Scope variable can be changed on fly. + var receivedFunct = scope.received; + var expressionCapsule = function(e, ui) { - value = patchSortableOption(key, scope[key]); - } - else - { - value = patchSortableOption(key, value); + try + { + + expression.apply(0,arguments); //Sends all of arguments to callBack function. + + if(receivedFunct instanceof Function) + receivedFunct.apply(0,arguments); + + } + catch(err) + { + //Can be printed to console. + } } + + value = patchSortableOption(key, expressionCapsule); + } + else + { + value = patchSortableOption(key, value); + } if (!optsDiff) { From d27f1900596b4c3726b06694bea727d952efa4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Aky=C4=B1ld=C4=B1z?= Date: Fri, 6 Jan 2017 11:17:39 +0300 Subject: [PATCH 06/41] Space warning fix for travis-ci --- src/sortable.js | 86 ++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 9532ee8..3688d80 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -16,14 +16,14 @@ angular.module('ui.sortable', []) return { require:'?ngModel', scope: { - ngModel:'=', - uiSortable:'=', - receive:'&uiSortableReceive',//Expression bindings from html. - remove:'&uiSortableRemove', - start:'&uiSortableStart', - stop:'&uiSortableStop', - update:'&uiSortableUpdate', - received :'&uiSortableReceived' + ngModel:'=', + uiSortable:'=', + receive:'&uiSortableReceive',//Expression bindings from html. + remove:'&uiSortableRemove', + start:'&uiSortableStart', + stop:'&uiSortableStop', + update:'&uiSortableUpdate', + received :'&uiSortableReceived' }, link: function(scope, element, attrs, ngModel) { var savedNodes; @@ -133,41 +133,41 @@ angular.module('ui.sortable', []) } - /* - * If user defines ui-sortable-callback for @key and callback based option at the same time the html based ui-sortable-callback expression will be selected. (Overridden) - * If user defined ui-sortable-callback for @key but callback expression is empty then option based @key callback will be selected. - * If user not defines a option for @key callback then html based ui-sortable-callback will be just selected. - * If user just defines option for @key callback then it will be attached. - * */ - var attrKey = 'uiSortable'+key.substring(0,1).toUpperCase()+key.substring(1); - if(scope[key]!==undefined && scope[key] instanceof Function && attrs[attrKey] !== undefined && attrs[attrKey].length > 0) - { - - var expression = scope[key]; //Scope variable can be changed on fly. - var receivedFunct = scope.received; - var expressionCapsule = function(e, ui) - { - try - { - - expression.apply(0,arguments); //Sends all of arguments to callBack function. - - if(receivedFunct instanceof Function) - receivedFunct.apply(0,arguments); - - } - catch(err) - { - //Can be printed to console. - } - } - - value = patchSortableOption(key, expressionCapsule); - } - else - { - value = patchSortableOption(key, value); - } + /* + * If user defines ui-sortable-callback for @key and callback based option at the same time the html based ui-sortable-callback expression will be selected. (Overridden) + * If user defined ui-sortable-callback for @key but callback expression is empty then option based @key callback will be selected. + * If user not defines a option for @key callback then html based ui-sortable-callback will be just selected. + * If user just defines option for @key callback then it will be attached. + * */ + var attrKey = 'uiSortable'+key.substring(0,1).toUpperCase()+key.substring(1); + if(scope[key]!==undefined && scope[key] instanceof Function && attrs[attrKey] !== undefined && attrs[attrKey].length > 0) + { + + var expression = scope[key]; //Scope variable can be changed on fly. + var receivedFunct = scope.received; + var expressionCapsule = function(e, ui) + { + try + { + + expression.apply(0,arguments); //Sends all of arguments to callBack function. + + if(receivedFunct instanceof Function) + receivedFunct.apply(0,arguments); + + } + catch(err) + { + //Can be printed to console. + } + } + + value = patchSortableOption(key, expressionCapsule); + } + else + { + value = patchSortableOption(key, value); + } if (!optsDiff) { From ec1b5f74960ffc7d9c1cb447ca09e4fe9c5928eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Aky=C4=B1ld=C4=B1z?= Date: Fri, 6 Jan 2017 11:23:43 +0300 Subject: [PATCH 07/41] Travis-ci fix again --- src/sortable.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 3688d80..e7f7d8f 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -145,7 +145,7 @@ angular.module('ui.sortable', []) var expression = scope[key]; //Scope variable can be changed on fly. var receivedFunct = scope.received; - var expressionCapsule = function(e, ui) + var expressionCapsule = function() { try { @@ -162,12 +162,12 @@ angular.module('ui.sortable', []) } } - value = patchSortableOption(key, expressionCapsule); - } - else - { - value = patchSortableOption(key, value); - } + value = patchSortableOption(key, expressionCapsule); + } + else + { + value = patchSortableOption(key, value); + } if (!optsDiff) { From fe2af1f77f39640623f2e98679873508f3067c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Aky=C4=B1ld=C4=B1z?= Date: Fri, 6 Jan 2017 11:31:05 +0300 Subject: [PATCH 08/41] Travis-ci fix again -_- --- src/sortable.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index e7f7d8f..dcb3073 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -153,22 +153,22 @@ angular.module('ui.sortable', []) expression.apply(0,arguments); //Sends all of arguments to callBack function. if(receivedFunct instanceof Function) + { receivedFunct.apply(0,arguments); + } } - catch(err) - { + catch(err){ //Can be printed to console. } } value = patchSortableOption(key, expressionCapsule); - } - else - { - value = patchSortableOption(key, value); - } - + } + else + { + value = patchSortableOption(key, value); + } if (!optsDiff) { optsDiff = {}; From 415d98320f19574f84b3c3f973894c12c8f6704c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Aky=C4=B1ld=C4=B1z?= Date: Fri, 6 Jan 2017 11:38:49 +0300 Subject: [PATCH 09/41] Travis-ci - There is no fail There is no missing semicolon. --- src/sortable.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index dcb3073..1ffda30 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -158,9 +158,11 @@ angular.module('ui.sortable', []) } } - catch(err){ - //Can be printed to console. + catch(err) + { + } + } value = patchSortableOption(key, expressionCapsule); From b6d8bdaed80bd066ce1274f1723953a0ce230d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Aky=C4=B1ld=C4=B1z?= Date: Fri, 6 Jan 2017 11:47:56 +0300 Subject: [PATCH 10/41] Travis ci There is no missing semicolon. This was my last commit for travis syntax fix. --- src/sortable.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 1ffda30..420afda 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -140,26 +140,21 @@ angular.module('ui.sortable', []) * If user just defines option for @key callback then it will be attached. * */ var attrKey = 'uiSortable'+key.substring(0,1).toUpperCase()+key.substring(1); - if(scope[key]!==undefined && scope[key] instanceof Function && attrs[attrKey] !== undefined && attrs[attrKey].length > 0) - { + if(scope[key]!==undefined && scope[key] instanceof Function && attrs[attrKey] !== undefined && attrs[attrKey].length > 0) { var expression = scope[key]; //Scope variable can be changed on fly. var receivedFunct = scope.received; - var expressionCapsule = function() - { - try - { + var expressionCapsule = function() { + try { expression.apply(0,arguments); //Sends all of arguments to callBack function. - if(receivedFunct instanceof Function) - { + if(receivedFunct instanceof Function) { receivedFunct.apply(0,arguments); } } - catch(err) - { + catch(err) { } @@ -167,8 +162,7 @@ angular.module('ui.sortable', []) value = patchSortableOption(key, expressionCapsule); } - else - { + else { value = patchSortableOption(key, value); } From ef5862c6905f41d26f5ee2c246c65033fa2d5bc7 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Mon, 6 Mar 2017 23:18:14 +0200 Subject: [PATCH 11/41] feat(sortable): change attr callback implementation w/ meta-programming --- src/sortable.js | 86 ++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 420afda..d57ff5c 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -18,12 +18,21 @@ angular.module('ui.sortable', []) scope: { ngModel:'=', uiSortable:'=', - receive:'&uiSortableReceive',//Expression bindings from html. - remove:'&uiSortableRemove', + ////Expression bindings from html. + create:'&uiSortableCreate', + // helper:'&uiSortableHelper', start:'&uiSortableStart', - stop:'&uiSortableStop', + activate:'&uiSortableActivate', + // sort:'&uiSortableSort', + // change:'&uiSortableChange', + // over:'&uiSortableOver', + // out:'&uiSortableOut', + beforeStop:'&uiSortableBeforeStop', update:'&uiSortableUpdate', - received :'&uiSortableReceived' + remove:'&uiSortableRemove', + receive:'&uiSortableReceive', + deactivate:'&uiSortableDeactivate', + stop:'&uiSortableStop' }, link: function(scope, element, attrs, ngModel) { var savedNodes; @@ -131,41 +140,9 @@ angular.module('ui.sortable', []) opts[key] = patchSortableOption(key, value); return; } - - - /* - * If user defines ui-sortable-callback for @key and callback based option at the same time the html based ui-sortable-callback expression will be selected. (Overridden) - * If user defined ui-sortable-callback for @key but callback expression is empty then option based @key callback will be selected. - * If user not defines a option for @key callback then html based ui-sortable-callback will be just selected. - * If user just defines option for @key callback then it will be attached. - * */ - var attrKey = 'uiSortable'+key.substring(0,1).toUpperCase()+key.substring(1); - if(scope[key]!==undefined && scope[key] instanceof Function && attrs[attrKey] !== undefined && attrs[attrKey].length > 0) { - - var expression = scope[key]; //Scope variable can be changed on fly. - var receivedFunct = scope.received; - var expressionCapsule = function() { - try { - - expression.apply(0,arguments); //Sends all of arguments to callBack function. - - if(receivedFunct instanceof Function) { - receivedFunct.apply(0,arguments); - } - - } - catch(err) { - - } - - } - - value = patchSortableOption(key, expressionCapsule); - } - else { - value = patchSortableOption(key, value); - } - + + value = patchSortableOption(key, value); + if (!optsDiff) { optsDiff = {}; } @@ -255,11 +232,19 @@ angular.module('ui.sortable', []) }; var callbacks = { - receive: null, - remove: null, + create: null, start: null, - stop: null, - update: null + activate: null, + // sort: null, + // change: null, + // over: null, + // out: null, + beforeStop: null, + update: null, + remove: null, + receive: null, + deactivate: null, + stop: null }; var wrappers = { @@ -471,6 +456,21 @@ angular.module('ui.sortable', []) } }; + // setup attribute handlers + angular.forEach(callbacks, function(value, key) { + callbacks[key] = combineCallbacks(callbacks[key], + function () { + var attrHandler = scope[key]; + var attrHandlerFn; + if (typeof attrHandler === 'function' && + ('uiSortable' + key.substring(0,1).toUpperCase() + key.substring(1)).length && + typeof (attrHandlerFn = attrHandler()) === 'function') { + attrHandlerFn.apply(this, arguments); + } + }); + }); + + wrappers.helper = function (inner) { if (inner && typeof inner === 'function') { return function (e, item) { From b506cb01b428f036f67395146d5e0bc8498bec6c Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Mon, 6 Mar 2017 23:18:40 +0200 Subject: [PATCH 12/41] test: add feat(sortable): attr callback implementation tests --- test/sortable.e2e.callbacks.attr.spec.js | 199 +++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 test/sortable.e2e.callbacks.attr.spec.js diff --git a/test/sortable.e2e.callbacks.attr.spec.js b/test/sortable.e2e.callbacks.attr.spec.js new file mode 100644 index 0000000..0226f3a --- /dev/null +++ b/test/sortable.e2e.callbacks.attr.spec.js @@ -0,0 +1,199 @@ +'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, hasUndefinedProperties, beforeLiElement, afterLiElement; + + beforeEach(inject(function (sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; + beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; + })); + + tests.description = 'Attribute Callbacks related'; + function tests (useExtraElements) { + + var host; + + beforeEach(inject(function() { + host = $('
'); + $('body').append(host); + + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + } + })); + + afterEach(function() { + host.remove(); + host = null; + }); + + it('should cancel sorting of node "Two"', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile(''.concat( + '
    ', + beforeLiElement, + '
  • {{ item }}
  • ', + afterLiElement, + '
'))($rootScope); + $rootScope.$apply(function() { + $rootScope.update = function(e, ui) { + if (ui.item.sortable.model === 'Two') { + ui.item.sortable.cancel(); + } + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find('[ng-repeat]:eq(1)'); + var 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)); + // try again + li = element.find('[ng-repeat]:eq(1)'); + 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)); + // try again + li = element.find('[ng-repeat]:eq(1)'); + 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)); + + li = element.find('[ng-repeat]:eq(0)'); + dy = (2 + 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('[ng-repeat]:eq(2)'); + dy = -(2 + 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 call all callbacks with the proper context', function() { + inject(function($compile, $rootScope) { + var element, callbackContexts = {}; + $rootScope.$apply(function() { + $rootScope.create = function() { + callbackContexts.create = this; + }; + // $rootScope.helper = function(e, item) { + // callbackContexts.helper = this; + // return item; + // }; + $rootScope.start = function() { + callbackContexts.start = this; + }; + $rootScope.activate = function() { + callbackContexts.activate = this; + }; + $rootScope.beforeStop = function() { + callbackContexts.beforeStop = this; + }; + $rootScope.update = function() { + callbackContexts.update = this; + }; + $rootScope.deactivate = function() { + callbackContexts.deactivate = this; + }; + $rootScope.stop = function() { + callbackContexts.stop = this; + }; + + // spyOn($rootScope, 'helper').and.callThrough(); + spyOn($rootScope, 'create').and.callThrough(); + spyOn($rootScope, 'start').and.callThrough(); + spyOn($rootScope, 'activate').and.callThrough(); + spyOn($rootScope, 'beforeStop').and.callThrough(); + spyOn($rootScope, 'update').and.callThrough(); + spyOn($rootScope, 'deactivate').and.callThrough(); + spyOn($rootScope, 'stop').and.callThrough(); + $rootScope.items = ['One', 'Two', 'Three']; + element = $compile(''.concat( + '
    ', + beforeLiElement, + '
  • {{ item }}
  • ', + afterLiElement + + '
'))($rootScope); + }); + + host.append(element); + + $rootScope.$apply(function() { + }); + var li = element.find('[ng-repeat]:eq(0)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + expect($rootScope.create).toHaveBeenCalled(); + // expect($rootScope.helper).toHaveBeenCalled(); + expect($rootScope.start).toHaveBeenCalled(); + expect($rootScope.activate).toHaveBeenCalled(); + expect($rootScope.beforeStop).toHaveBeenCalled(); + expect($rootScope.update).toHaveBeenCalled(); + expect($rootScope.deactivate).toHaveBeenCalled(); + expect($rootScope.stop).toHaveBeenCalled(); + + expect(callbackContexts.create).toEqual(element[0]); + // expect(callbackContexts.helper).toEqual(element[0]); + expect(callbackContexts.start).toEqual(element[0]); + expect(callbackContexts.activate).toEqual(element[0]); + expect(callbackContexts.beforeStop).toEqual(element[0]); + expect(callbackContexts.update).toEqual(element[0]); + expect(callbackContexts.deactivate).toEqual(element[0]); + expect(callbackContexts.stop).toEqual(element[0]); + + $(element).remove(); + }); + }); + } + + [0, 1].forEach(function(useExtraElements){ + var testDescription = tests.description; + + if (useExtraElements) { + testDescription += ' with extra elements'; + } + + describe(testDescription, function(){ + tests(useExtraElements); + }); + }); + +}); \ No newline at end of file From 7ebaa334610406a72c5277913007d3e703cb212f Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Mon, 6 Mar 2017 23:19:12 +0200 Subject: [PATCH 13/41] docs(README): improve docs for attr callbacks --- README.md | 61 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 1e28fec..3cb14d9 100644 --- a/README.md +++ b/README.md @@ -104,18 +104,41 @@ To provide a solution/workaround (till jquery.ui.sortable.refresh() also tests t ``` +**OR** + +```js +$scope.sortableOptions = { + 'ui-floating': true +}; +``` +```html +
    +
  • {{ item }}
  • +
+``` + + +**ui-floating** (default: undefined) +Type: [Boolean](http://api.jquery.com/Types/#Boolean)/[String](http://api.jquery.com/Types/#String)/`undefined` +* **undefined**: Relies on jquery.ui to detect the list's orientation. +* **false**: Forces jquery.ui.sortable to detect the list as vertical. +* **true**: Forces jquery.ui.sortable to detect the list as horizontal. +* **"auto"**: Detects on each drag `start` if the element is floating or not. #### Attributes For Event Handling To handle events with html bindings just define any expression to listed event attributes. -If you defined an attribute for this events and defined callback function in sortableOptions at the same time attribute based callback will be selected. -If attribute based callback expression is not filled then sortableOption based callback function will be selected. +If you defined an attribute for this events and defined callback function in sortableOptions at the same time, the attribute based callback will be called first. -* **ui-sortable-receive** -* **ui-sortable-remove** +* **ui-sortable-activate** * **ui-sortable-start** -* **ui-sortable-stop** +* **ui-sortable-activate** +* **ui-sortable-before-stop** * **ui-sortable-update** +* **ui-sortable-remove** +* **ui-sortable-receive** +* **ui-sortable-deactivate** +* **ui-sortable-stop** @@ -127,40 +150,18 @@ Expression works on update event. ``` -callBackFunction2 works on update event. -```js -$scope.sortableOptions = { - 'update': callBackFunction -}; -``` -```html -
    -
  • {{ item }}
  • -
-``` - - -**OR** - +On update event callBackFunction1 if called before callBackFunction2. ```js $scope.sortableOptions = { - 'ui-floating': true + 'update': callBackFunction2 }; ``` ```html -
    +
    • {{ item }}
    ``` - -**ui-floating** (default: undefined) -Type: [Boolean](http://api.jquery.com/Types/#Boolean)/[String](http://api.jquery.com/Types/#String)/`undefined` -* **undefined**: Relies on jquery.ui to detect the list's orientation. -* **false**: Forces jquery.ui.sortable to detect the list as vertical. -* **true**: Forces jquery.ui.sortable to detect the list as horizontal. -* **"auto"**: Detects on each drag `start` if the element is floating or not. - #### Canceling Inside the `update` callback, you can check the item that is dragged and cancel the sorting. From aab17108bbafa089d575ed4c2c5485bb0e83dd30 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Tue, 7 Mar 2017 12:03:08 +0200 Subject: [PATCH 14/41] fix(README): fix attribute handler code sample --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3cb14d9..259da9e 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ $scope.sortableOptions = { }; ``` ```html -
      +
      • {{ item }}
      ``` From 689b200157c7794181ffe996666103094c132e66 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Tue, 7 Mar 2017 20:48:44 +0200 Subject: [PATCH 15/41] feat: end up with the initial complete event $emit implementation --- src/sortable.js | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 217965b..e2a9f9c 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -345,11 +345,7 @@ angular.module('ui.sortable', []) // Save current drop position but only if this is not a second // update that happens when moving between lists because then // the value will be overwritten with the old value - - var wasMoved = ('dropindex' in ui.item.sortable) && - !ui.item.sortable.isCanceled(); - - if(!ui.item.sortable.received) { + if (!ui.item.sortable.received) { ui.item.sortable.dropindex = getItemIndex(ui.item); var droptarget = ui.item.closest('[ui-sortable], [data-ui-sortable], [x-ui-sortable]'); ui.item.sortable.droptarget = droptarget; @@ -383,7 +379,7 @@ angular.module('ui.sortable', []) // it's safe to clear the restored nodes since: // update is currently running and // stop is not called for the target list. - if(ui.item.sortable.received) { + if (ui.item.sortable.received) { savedNodes = null; } @@ -391,17 +387,13 @@ angular.module('ui.sortable', []) // then we add the new item to this list otherwise wait until the // stop event where we will know if it was a sort or item was // moved here from another list - if(ui.item.sortable.received && !ui.item.sortable.isCanceled()) { + if (ui.item.sortable.received && !ui.item.sortable.isCanceled()) { scope.$apply(function () { ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0, ui.item.sortable.moved); }); + scope.$emit('ui-sortable:moved', ui); } - - if(wasMoved && !ui.item.sortable.received){ - scope.$emit('sortable:wasMoved'); - } - }; callbacks.stop = function(e, ui) { @@ -418,6 +410,7 @@ angular.module('ui.sortable', []) ui.item.sortable.dropindex, 0, ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]); }); + scope.$emit('ui-sortable:moved', ui); } else if (!wasMoved && !angular.equals(element.contents().toArray(), savedNodes.toArray())) { // if the item was not moved From 8c01bc2f255eb2a2ef8ddc79adf020d3f524f191 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Tue, 7 Mar 2017 20:49:12 +0200 Subject: [PATCH 16/41] test(events): add tests about event `$emit`tion --- test/sortable.e2e.events.spec.js | 167 +++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 test/sortable.e2e.events.spec.js diff --git a/test/sortable.e2e.events.spec.js b/test/sortable.e2e.events.spec.js new file mode 100644 index 0000000..05c2647 --- /dev/null +++ b/test/sortable.e2e.events.spec.js @@ -0,0 +1,167 @@ +'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, simulateElementDrag, hasUndefinedProperties, beforeLiElement, afterLiElement; + + beforeEach(inject(function (sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + simulateElementDrag = sortableTestHelper.simulateElementDrag; + hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; + beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; + })); + + tests.description = 'Events related'; + function tests (useExtraElements) { + + var host; + + beforeEach(inject(function() { + host = $('
      '); + $('body').append(host); + + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + } + })); + + afterEach(function() { + host.remove(); + host = null; + }); + + it('should emit an event after sorting', function() { + inject(function($compile, $rootScope) { + var element, uiParam, emittedUiParam; + element = $compile(''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      '))($rootScope); + $rootScope.$apply(function() { + $rootScope.items = ['One', 'Two', 'Three']; + $rootScope.update = function (e, ui) { + uiParam = ui; + }; + $rootScope.onSorting = function (e, ui) { + emittedUiParam = ui; + }; + spyOn($rootScope, 'onSorting').and.callThrough(); + + $rootScope.$on('ui-sortable:moved', $rootScope.onSorting); + }); + + host.append(element); + + var li = element.find('[ng-repeat]:eq(0)'); + var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); + li.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Two', 'Three', 'One']); + expect($rootScope.items).toEqual(listContent(element)); + + expect($rootScope.onSorting).toHaveBeenCalled(); + expect(uiParam).toEqual(emittedUiParam); + + $(element).remove(); + }); + }); + + it('should emit an event after sorting between sortables of different scopes', function() { + inject(function($compile, $rootScope) { + var elementTop, elementBottom, + wrapperTop, wrapperBottom, + wrapperTopScope, wrapperBottomScope, + itemsTop, itemsBottom; + wrapperTopScope = $rootScope.$new(); + wrapperBottomScope = $rootScope.$new(); + wrapperTop = $compile(''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      '))(wrapperTopScope); + wrapperBottom = $compile(''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      '))(wrapperBottomScope); + + host.append(wrapperTop).append(wrapperBottom).append('
      '); + $rootScope.$apply(function() { + wrapperTopScope.itemsTop = itemsTop = ['Top One', 'Top Two', 'Top Three']; + wrapperTopScope.opts = { + connectWith: '.cross-sortable', + stop: function (e, ui) { + wrapperTopScope.uiParam = ui; + } + }; + wrapperTopScope.onSorting = function (e, ui) { + wrapperTopScope.emittedUiParam = ui; + }; + spyOn(wrapperTopScope, 'onSorting').and.callThrough(); + $rootScope.$on('ui-sortable:moved', wrapperTopScope.onSorting); + + wrapperBottomScope.itemsBottom = itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; + wrapperBottomScope.opts = { + connectWith: '.cross-sortable', + update: function (e, ui) { + wrapperBottomScope.uiParam = ui; + } + }; + wrapperBottomScope.onSorting = function (e, ui) { + wrapperBottomScope.emittedUiParam = ui; + }; + spyOn(wrapperBottomScope, 'onSorting').and.callThrough(); + $rootScope.$on('ui-sortable:moved', wrapperBottomScope.onSorting); + }); + + elementTop = wrapperTop.find('> [ui-sortable]'); + elementBottom = wrapperBottom.find('> [ui-sortable]'); + + var li1 = elementTop.find('[ng-repeat]:eq(0)'); + var li2 = elementBottom.find('[ng-repeat]:eq(0)'); + simulateElementDrag(li1, li2, 'below'); + expect(itemsTop).toEqual(['Top Two', 'Top Three']); + expect(itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect(itemsTop).toEqual(listContent(elementTop)); + expect(itemsBottom).toEqual(listContent(elementBottom)); + + expect(wrapperTopScope.onSorting).toHaveBeenCalled(); + expect(wrapperTopScope.uiParam.item).toEqual(wrapperTopScope.emittedUiParam.item); + + expect(wrapperBottomScope.onSorting).toHaveBeenCalled(); + expect(wrapperBottomScope.uiParam.item).toEqual(wrapperBottomScope.emittedUiParam.item); + + $(wrapperBottom).remove(); + $(wrapperTop).remove(); + }); + }); + } + + [0, 1].forEach(function(useExtraElements){ + var testDescription = tests.description; + + if (useExtraElements) { + testDescription += ' with extra elements'; + } + + describe(testDescription, function(){ + tests(useExtraElements); + }); + }); + +}); \ No newline at end of file From 220125b81d96f29f2bc7e8bac2184b656e15f076 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Tue, 7 Mar 2017 20:49:16 +0200 Subject: [PATCH 17/41] docs(API): add docs about the `$emit`ted event --- API.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/API.md b/API.md index 7288f81..d3fb53b 100644 --- a/API.md +++ b/API.md @@ -58,3 +58,16 @@ Returns whether the current sorting is marked as canceled, by an earlier call to ### isCustomHelperUsed[()](http://api.jquery.com/Types/#Function) Returns: [Boolean](http://api.jquery.com/Types/#Boolean) Returns whether the [`helper`](http://api.jqueryui.com/sortable/#option-helper) element used for the current sorting, is one of the original ui-sortable list elements. + + +## Events + +### `ui-sortable:moved` +Is emitted after the `stop` callback. +In connected sortables it is also emitted after the `update` on the receiving sortable. + +```js +$rootScope.$on('ui-sortable:moved', function (e, ui) { + +}); +``` From 9e1598fa39f563aa17a8b873a1ce6cfa7f245aa8 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Wed, 8 Mar 2017 07:28:11 +0200 Subject: [PATCH 18/41] docs(README): add attribure handlers demo --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 259da9e..ecfdf85 100644 --- a/README.md +++ b/README.md @@ -272,6 +272,7 @@ myAppModule.controller('MyController', function($scope) { ## Examples - [Simple Demo](http://codepen.io/thgreasi/pen/wzmvgw) + - [Simple Attribute Handlers Demo](http://codepen.io/thgreasi/pen/JWbmjb) - [Simple RequireJS Demo](http://codepen.io/thgreasi/pen/rrdNjj) - [Simple Touch-Enabled Demo](http://codepen.io/thgreasi/pen/wzmvJv) using [jQuery UI Touch Punch](https://github.com/furf/jquery-ui-touch-punch/) - [Multiple items sorting (ctrl+click)](http://codepen.io/thgreasi/pen/mJAcL) using [ui-sortable-multiselection](https://github.com/thgreasi/ui-sortable-multiselection) From 18cc2959acaa2b692ec72f7fcf661ef0815945ef Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Wed, 8 Mar 2017 19:29:18 +0200 Subject: [PATCH 19/41] chore: increase version to 0.17.0 --- bower.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index 7200b2f..ab1f79b 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.16.1", + "version": "0.17.0", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", diff --git a/package.json b/package.json index 4820e84..6070b7e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.16.1", + "version": "0.17.0", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", From 496fb42ba52fbbc5c947f842417fd22cd635c21c Mon Sep 17 00:00:00 2001 From: Johnson Chou Date: Sat, 15 Apr 2017 01:28:15 +0800 Subject: [PATCH 20/41] fix(sortable): fix incorrect helper returned from getSortingHelper(). The helper element is not always in the last position while created from a function and append it to another DOM. E.g. the following will mess up the DOM position after canceled update. ``` var sortableOption = { helper: function (evt, ui) { return ui.clone().appendTo('body'); } }; ``` --- src/sortable.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index e2a9f9c..951588a 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -36,6 +36,7 @@ angular.module('ui.sortable', []) }, link: function(scope, element, attrs, ngModel) { var savedNodes; + var helper; function combineCallbacks(first, second){ var firstIsFunc = typeof first === 'function'; @@ -190,8 +191,7 @@ angular.module('ui.sortable', []) if (hasSortingHelper(element, ui) && element.sortable( 'option', 'appendTo' ) === 'parent') { // The .ui-sortable-helper element (that's the default class name) - // is placed last. - result = savedNodes.last(); + result = helper; } return result; } @@ -331,6 +331,7 @@ angular.module('ui.sortable', []) // This is inside activate (instead of start) in order to save // both lists when dragging between connected lists. savedNodes = savedNodesOrigin.contents(); + helper = ui.helper; // If this list has a placeholder (the connected lists won't), // don't inlcude it in saved nodes. @@ -428,9 +429,10 @@ angular.module('ui.sortable', []) savedNodes.appendTo(elementContext.savedNodesOrigin); } - // It's now safe to clear the savedNodes + // It's now safe to clear the savedNodes and helper // since stop is the last callback. savedNodes = null; + helper = null; }; callbacks.receive = function(e, ui) { From 6f5604271e8445b3415624c05f5483210d9a7b9c Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sat, 15 Apr 2017 20:34:05 +0300 Subject: [PATCH 21/41] fix(sortable): fix lint error --- src/sortable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sortable.js b/src/sortable.js index 951588a..8bdaaf9 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -186,7 +186,7 @@ angular.module('ui.sortable', []) return helperOption === 'clone' || (typeof helperOption === 'function' && ui.item.sortable.isCustomHelperUsed()); } - function getSortingHelper (element, ui, savedNodes) { + function getSortingHelper (element, ui/*, savedNodes*/) { var result = null; if (hasSortingHelper(element, ui) && element.sortable( 'option', 'appendTo' ) === 'parent') { From a8d6002e717335fb29cad0be6fda804b14b01ef3 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sat, 15 Apr 2017 20:36:14 +0300 Subject: [PATCH 22/41] test(e2e.callbacks.spec): add test for cloned helper appended to body --- test/sortable.e2e.callbacks.spec.js | 59 +++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/test/sortable.e2e.callbacks.spec.js b/test/sortable.e2e.callbacks.spec.js index 8506ea3..e944353 100644 --- a/test/sortable.e2e.callbacks.spec.js +++ b/test/sortable.e2e.callbacks.spec.js @@ -156,6 +156,65 @@ describe('uiSortable', function() { }); }); + it('should cancel sorting of node "Two" when then helper is appended to the `body`', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile(''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + + '
      '))($rootScope); + $rootScope.$apply(function() { + $rootScope.opts = { + helper: function (e, item) { + return item.clone().appendTo('body'); + }, + update: function(e, ui) { + if (ui.item.sortable.model === 'Two') { + ui.item.sortable.cancel(); + } + } + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element); + + var li = element.find('[ng-repeat]:eq(1)'); + var 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)); + // try again + li = element.find('[ng-repeat]:eq(1)'); + 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)); + // try again + li = element.find('[ng-repeat]:eq(1)'); + 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)); + + li = element.find('[ng-repeat]:eq(0)'); + dy = (2 + 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('[ng-repeat]:eq(2)'); + dy = -(2 + 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 cancel sorting of node "Two" and "helper: function" that returns a list element is used', function() { inject(function($compile, $rootScope) { var element; From a9d796fa8e01ade72508fbdfb8c2eaa7e37de7e3 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sat, 15 Apr 2017 20:37:13 +0300 Subject: [PATCH 23/41] chore: increase version to 0.17.1 --- bower.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index ab1f79b..ad361a8 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.17.0", + "version": "0.17.1", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", diff --git a/package.json b/package.json index 6070b7e..51a1c80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.17.0", + "version": "0.17.1", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", From 2ff4a1ae02ba0901de78795800fa8dad0515f42f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Navarro=20P=C3=A9rez?= Date: Tue, 25 Jul 2017 10:46:32 +0200 Subject: [PATCH 24/41] Fix in Material example title. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ecfdf85..04e240e 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ list A: stop For more details about the events check the [jQueryUI API documentation](http://api.jqueryui.com/sortable/). ## Integrating with directives doing transclusion -Wrap the transclusion directive element with the ui-sortable directive and set the `items` to target your `ng-repeat`ed elements. Following best practices, it is also highly recommended that you add a `track by` expression to your `ng-repeat`. [Angular Meterial example](http://codepen.io/thgreasi/pen/NbyLVK). +Wrap the transclusion directive element with the ui-sortable directive and set the `items` to target your `ng-repeat`ed elements. Following best practices, it is also highly recommended that you add a `track by` expression to your `ng-repeat`. [Angular Material example](http://codepen.io/thgreasi/pen/NbyLVK). ```js myAppModule.controller('MyController', function($scope) { From 6d31d46766445701130cfdae1941673f100e816b Mon Sep 17 00:00:00 2001 From: tsujiura Date: Wed, 26 Jul 2017 00:32:09 +0900 Subject: [PATCH 25/41] fix(README): fix duplicate event --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 04e240e..b4f29b6 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,6 @@ Type: [Boolean](http://api.jquery.com/Types/#Boolean)/[String](http://api.jquery To handle events with html bindings just define any expression to listed event attributes. If you defined an attribute for this events and defined callback function in sortableOptions at the same time, the attribute based callback will be called first. -* **ui-sortable-activate** * **ui-sortable-start** * **ui-sortable-activate** * **ui-sortable-before-stop** From 204825afbc826277ccef01c4ec442bf44866962a Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sat, 5 Aug 2017 16:36:23 +0300 Subject: [PATCH 26/41] docs(README): update for jQuery-UI v1.12 Resolves #531 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b4f29b6..f4369c7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This directive allows you to sort an array with drag & drop. **Notes:** > * JQuery must be included before AngularJS. -> * JQueryUI dependecies include [core](http://api.jqueryui.com/category/ui-core/), [widget](http://api.jqueryui.com/jQuery.widget/), [mouse](http://api.jqueryui.com/mouse/) & [sortable](http://api.jqueryui.com/sortable/). Creating a [custom build](http://jqueryui.com/download/#!version=1.10&components=1110000010000000000000000000000000) will [greatly reduce](https://github.com/angular-ui/ui-sortable/issues/154#issuecomment-40279430) the required file size. ([CDN](http://www.jsdelivr.com/) links for comparison: [full](http://cdn.jsdelivr.net/g/jquery.ui@1.10) vs [minimal](http://cdn.jsdelivr.net/g/jquery.ui@1.10%28jquery.ui.core.min.js+jquery.ui.widget.min.js+jquery.ui.mouse.min.js+jquery.ui.sortable.min.js%29)) +> * JQueryUI dependecies include [widget](http://api.jqueryui.com/jQuery.widget/), [data](http://api.jqueryui.com/data-selector/), [scroll-parent](http://api.jqueryui.com/scrollParent/), [mouse](http://api.jqueryui.com/mouse/) & [sortable](http://api.jqueryui.com/sortable/). Creating a [custom build](http://jqueryui.com/download/#!version=1.12.1&components=101000000100000010000000010000000000000000000000) will [greatly reduce](https://github.com/angular-ui/ui-sortable/issues/154#issuecomment-40279430) the required file size. ([CDN](http://www.jsdelivr.com/) links for comparison: [full](https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js) vs [minimal](https://cdn.jsdelivr.net/combine/npm/jquery-ui@1.12/ui/version.min.js,npm/jquery-ui@1.12/ui/widget.min.js,npm/jquery-ui@1.12/ui/data.min.js,npm/jquery-ui@1.12/ui/scroll-parent.min.js,npm/jquery-ui@1.12/ui/widgets/mouse.min.js,npm/jquery-ui@1.12/ui/widgets/sortable.min.js)) > * Users of AngularJS pre v1.2 can use [v0.10.x](https://github.com/angular-ui/ui-sortable/tree/v0.10.x-stable) or [v0.12.x](https://github.com/angular-ui/ui-sortable/tree/v0.12.x-stable) branches. > * Early adopters of [Angular2](https://angular.io/) can use the [ng2 branch](https://github.com/angular-ui/ui-sortable/tree/ng2). From 5a860d11a1ca6df254f8e6da4de211221836a268 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 17 Aug 2017 15:45:24 +0300 Subject: [PATCH 27/41] chore: add npm scripts --- package.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 51a1c80..665edc0 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,12 @@ "requirejs": "2.1.x", "wiredep": "1.8.x" }, - "scripts": {}, + "scripts": { + "coverage": "grunt coverage", + "dist": "grunt dist", + "serve": "grunt serve", + "test": "grunt test" + }, "repository": { "type": "git", "url": "git://github.com/angular-ui/ui-sortable.git" From 3e19a579733b0c889f56ccd1b2b0ef340749f23b Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 17 Aug 2017 16:42:02 +0300 Subject: [PATCH 28/41] chore(travis): update to node 6 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7900299..f141de0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ language: node_js node_js: -- '0.10' +- '6' addons: firefox: "latest" before_install: - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start -- npm install -qg bower grunt-cli +- npm install -qg bower grunt grunt-cli - npm install -q - bower install after_success: From 6a92dfe63dd32f21cd1181c1c149dd235d13d164 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 17 Aug 2017 16:46:50 +0300 Subject: [PATCH 29/41] chore(travis): limit firefox to v54 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f141de0..6d05475 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: node_js node_js: - '6' addons: - firefox: "latest" + firefox: "54.0.1" before_install: - export DISPLAY=:99.0 - sh -e /etc/init.d/xvfb start From 09c01123c1327e05bee290de2cc7b3f739e0528c Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 17 Aug 2017 16:25:03 +0300 Subject: [PATCH 30/41] test(e2e.nested): test directly nested sortables --- test/sortable.e2e.nested.spec.js | 53 ++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/test/sortable.e2e.nested.spec.js b/test/sortable.e2e.nested.spec.js index 874ba8c..9fb3f1b 100644 --- a/test/sortable.e2e.nested.spec.js +++ b/test/sortable.e2e.nested.spec.js @@ -128,6 +128,59 @@ describe('uiSortable', function() { }); }); + it('should update model when sorting between drectly nested sortables', function() { + inject(function($compile, $rootScope) { + var elementTree, li1, li2; + + elementTree = $compile(''.concat( + '
      ', + '
      ', + '
      {{item.text}}
      ', + '
      ', + '
      {{i.text}}
      ', + '
      ', + '
      ', + '
      ', + '
      '))($rootScope); + + $rootScope.$apply(function() { + $rootScope.items = [ + { + text: 'Item 1', + items: [ + { text: 'Item 1.1', items: [] }, + { text: 'Item 1.2', items: [] } + ] + }, + { + text: 'Item 2', + items: [ + { text: 'Item 2.1', items: [] }, + { text: 'Item 2.2', items: [] } + ] + } + ]; + + $rootScope.sortableOptions = {}; + $rootScope.innerSortableOptions = { + connectWith: '.nested-sortable' + }; + }); + + host.append(elementTree); + + li1 = elementTree.find('.innerList:last'); + li2 = elementTree.find('.innerList:first'); + simulateElementDrag(li1, li2, { place: 'above', extradx: -10, extrady: -6 }); + expect($rootScope.items.map(function(x){ return x.text; })) + .toEqual(['Item 2', 'Item 1']); + expect($rootScope.items.map(function(x){ return x.text; })) + .toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); + + $(elementTree).remove(); + }); + }); + }); }); \ No newline at end of file From 9bb11af97647a968e6be9d58d2b4a31c09cf18fa Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 17 Aug 2017 16:27:46 +0300 Subject: [PATCH 31/41] fix(sortable): fix droptarget detection on directly nested sortables --- src/sortable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sortable.js b/src/sortable.js index 8bdaaf9..9b6bf4e 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -348,7 +348,7 @@ angular.module('ui.sortable', []) // the value will be overwritten with the old value if (!ui.item.sortable.received) { ui.item.sortable.dropindex = getItemIndex(ui.item); - var droptarget = ui.item.closest('[ui-sortable], [data-ui-sortable], [x-ui-sortable]'); + var droptarget = ui.item.parent().closest('[ui-sortable], [data-ui-sortable], [x-ui-sortable]'); ui.item.sortable.droptarget = droptarget; ui.item.sortable.droptargetList = ui.item.parent(); From 17c4158b071f978c919e15ffe44875b38ae9e4c0 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Thu, 17 Aug 2017 17:00:55 +0300 Subject: [PATCH 32/41] chore: increase version to 0.17.2 --- bower.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bower.json b/bower.json index ad361a8..886098f 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.17.1", + "version": "0.17.2", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", diff --git a/package.json b/package.json index 665edc0..22d266f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.17.1", + "version": "0.17.2", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", From d151ca3c4fa6ee940b46a6247a9895aa4c54bd74 Mon Sep 17 00:00:00 2001 From: Jason P Date: Mon, 16 Oct 2017 12:42:52 +0800 Subject: [PATCH 33/41] added `ui-preserve-size` option --- src/sortable.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sortable.js b/src/sortable.js index 9b6bf4e..40d5f25 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -18,6 +18,7 @@ angular.module('ui.sortable', []) scope: { ngModel:'=', uiSortable:'=', + uiPreserveSize: '=uiPreserveSize', ////Expression bindings from html. create:'&uiSortableCreate', // helper:'&uiSortableHelper', @@ -480,6 +481,16 @@ angular.module('ui.sortable', []) return function (e, item) { var oldItemSortable = item.sortable; var index = getItemIndex(item); + + if (typeof scope.uiPreserveSize === 'boolean' && scope.uiPreserveSize !== false) { + item.children().each(function () { + var $el = angular.element(this); + + // Preserve the with of the element + $el.width($el.width()); + }); + } + item.sortable = { model: ngModel.$modelValue[index], index: index, From c062ff5a8e231ed3a66d0ebdaf37aeec54f1ea1d Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sat, 25 Nov 2017 13:56:16 +0200 Subject: [PATCH 34/41] Add ui-preserve-size option --- API.md | 11 ++ README.md | 36 +++-- src/sortable.js | 64 ++++++--- test/sortable.e2e.directiveoptions.spec.js | 146 ++++++++++++++++++++- test/sortable.test-helper.js | 2 + 5 files changed, 228 insertions(+), 31 deletions(-) diff --git a/API.md b/API.md index d3fb53b..0094f7d 100644 --- a/API.md +++ b/API.md @@ -1,5 +1,16 @@ # ui.item.sortable API documentation +This refers to the additional properties that are exposed through the `ui` parameter in the provided callback hooks. eg: +```js +$scope.sortableOptions = { + update: function(e, ui) { + if (ui.item.sortable.model == "can't be moved") { + ui.item.sortable.cancel(); + } + } +}; +``` + ## Properties **Note:** diff --git a/README.md b/README.md index f4369c7..bf8cebb 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,15 @@ myAppModule.controller('MyController', function($scope) { When using event callbacks ([start](http://api.jqueryui.com/sortable/#event-start)/[update](http://api.jqueryui.com/sortable/#event-update)/[stop](http://api.jqueryui.com/sortable/#event-stop)...), avoid manipulating DOM elements (especially the one with the ng-repeat attached). The suggested pattern is to use callbacks for emmiting events and altering the scope (inside the 'Angular world'). -#### Floating +#### ui-floating + +**ui-floating** (default: undefined) +Description: Enables a workaround for smooth horizontal sorting. +Type: [Boolean](http://api.jquery.com/Types/#Boolean)/[String](http://api.jquery.com/Types/#String)/`undefined` +* **undefined**: Relies on jquery.ui to detect the list's orientation. +* **false**: Forces jquery.ui.sortable to detect the list as vertical. +* **true**: Forces jquery.ui.sortable to detect the list as horizontal. +* **"auto"**: Detects on each drag `start` if the element is floating or not. To have a smooth horizontal-list reordering, jquery.ui.sortable needs to detect the orientation of the list. This detection takes place during the initialization of the plugin (and some of the checks include: whether the first item is floating left/right or if 'axis' parameter is 'x', etc). @@ -118,14 +126,24 @@ $scope.sortableOptions = { ``` -**ui-floating** (default: undefined) -Type: [Boolean](http://api.jquery.com/Types/#Boolean)/[String](http://api.jquery.com/Types/#String)/`undefined` -* **undefined**: Relies on jquery.ui to detect the list's orientation. -* **false**: Forces jquery.ui.sortable to detect the list as vertical. -* **true**: Forces jquery.ui.sortable to detect the list as horizontal. -* **"auto"**: Detects on each drag `start` if the element is floating or not. +#### ui-model-items + +**ui-model-items** (default: `> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]`) +Description: Defines which elements should be considered as part of your model. +Type: [CSS selector](http://api.jquery.com/Types/#Selector)/[String](http://api.jquery.com/Types/#String) + +This is the model related counterpart option of [jQuery's items option](http://api.jqueryui.com/sortable/#option-items). + +#### ui-preserve-size + +**ui-preserve-size** (default: undefined) +Description: Set's the size of the sorting helper to the size of the original element before the sorting. +Type: [Boolean](http://api.jquery.com/Types/#Boolean)/`undefined` + +This is useful for elements that their size is dependent to other page characteristics. +A representative example of such cases are `` ``s and `', + afterTrElement: '', beforeDivElement: '
      extra element
      ', afterDivElement: '
      extra element
      ' } From 227d01829ad7be44762f4b39a1ce930088ac5b80 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sun, 26 Nov 2017 12:59:11 +0200 Subject: [PATCH 35/41] chore: increase version to 0.18.0 --- bower.json | 1 - package.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/bower.json b/bower.json index 886098f..ca91322 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,5 @@ { "name": "angular-ui-sortable", - "version": "0.17.2", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", diff --git a/package.json b/package.json index 22d266f..93fcd4c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.17.2", + "version": "0.18.0", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", From 1900f97cde432b82b3241ba8b3dca4f5a20f6cc5 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sun, 26 Nov 2017 13:09:04 +0200 Subject: [PATCH 36/41] chore: add prettier & husky --- .prettierrc | 3 +++ package.json | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..5c5237b --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "single-quote": true +} diff --git a/package.json b/package.json index 93fcd4c..bb36f2c 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "grunt-karma": "^0.12.1", "grunt-ngmin": "0.0.x", "grunt-surround": "0.1.x", + "husky": "^0.14.3", "jasmine-core": "^2.4.1", "karma": "^0.13.22", "karma-chrome-launcher": "0.1.x", @@ -31,18 +32,28 @@ "karma-phantomjs-launcher": "^1.0.0", "karma-requirejs": "^0.2.5", "karma-script-launcher": "^0.2.0", + "lint-staged": "^5.0.0", "load-grunt-tasks": "0.2.x", + "prettier": "^1.8.2", "requirejs": "2.1.x", "wiredep": "1.8.x" }, "scripts": { "coverage": "grunt coverage", "dist": "grunt dist", + "precommit": "lint-staged", + "prettify": "prettier --write \"src/**/*.js\" \"test/**/*.js\"", "serve": "grunt serve", "test": "grunt test" }, "repository": { "type": "git", "url": "git://github.com/angular-ui/ui-sortable.git" + }, + "lint-staged": { + "*.js": [ + "prettier --write", + "git add" + ] } } From 248ff43937a7d77f4e3df9f99f8605c36647e313 Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sun, 26 Nov 2017 13:09:20 +0200 Subject: [PATCH 37/41] chore: prettify sources --- src/sortable.js | 305 ++-- test/karma.conf.js | 22 +- test/libs/jquery.simulate.dragandrevert.js | 118 +- test/sortable.e2e.callbacks.attr.spec.js | 120 +- test/sortable.e2e.callbacks.spec.js | 315 ++-- test/sortable.e2e.directiveoptions.spec.js | 333 +++-- test/sortable.e2e.directives.spec.js | 303 ++-- test/sortable.e2e.events.spec.js | 173 ++- test/sortable.e2e.multi.spec.js | 1497 ++++++++++++++------ test/sortable.e2e.nested.spec.js | 261 ++-- test/sortable.e2e.spec.js | 432 +++--- test/sortable.spec.js | 167 ++- test/sortable.test-directives.js | 100 +- test/sortable.test-helper.js | 58 +- 14 files changed, 2744 insertions(+), 1460 deletions(-) diff --git a/src/sortable.js b/src/sortable.js index 1076c85..ed0c482 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -3,45 +3,48 @@ @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config */ -angular.module('ui.sortable', []) - .value('uiSortableConfig',{ +angular + .module('ui.sortable', []) + .value('uiSortableConfig', { // the default for jquery-ui sortable is "> *", we need to restrict this to // ng-repeat items // if the user uses items: '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]' }) .directive('uiSortable', [ - 'uiSortableConfig', '$timeout', '$log', + 'uiSortableConfig', + '$timeout', + '$log', function(uiSortableConfig, $timeout, $log) { return { - require:'?ngModel', + require: '?ngModel', scope: { - ngModel:'=', - uiSortable:'=', + ngModel: '=', + uiSortable: '=', ////Expression bindings from html. - create:'&uiSortableCreate', + create: '&uiSortableCreate', // helper:'&uiSortableHelper', - start:'&uiSortableStart', - activate:'&uiSortableActivate', + start: '&uiSortableStart', + activate: '&uiSortableActivate', // sort:'&uiSortableSort', // change:'&uiSortableChange', // over:'&uiSortableOver', // out:'&uiSortableOut', - beforeStop:'&uiSortableBeforeStop', - update:'&uiSortableUpdate', - remove:'&uiSortableRemove', - receive:'&uiSortableReceive', - deactivate:'&uiSortableDeactivate', - stop:'&uiSortableStop' + beforeStop: '&uiSortableBeforeStop', + update: '&uiSortableUpdate', + remove: '&uiSortableRemove', + receive: '&uiSortableReceive', + deactivate: '&uiSortableDeactivate', + stop: '&uiSortableStop' }, link: function(scope, element, attrs, ngModel) { var savedNodes; var helper; - function combineCallbacks(first, second){ + function combineCallbacks(first, second) { var firstIsFunc = typeof first === 'function'; var secondIsFunc = typeof second === 'function'; - if(firstIsFunc && secondIsFunc) { + if (firstIsFunc && secondIsFunc) { return function() { first.apply(this, arguments); second.apply(this, arguments); @@ -56,7 +59,11 @@ angular.module('ui.sortable', []) // this is a fix to support jquery-ui prior to v1.11.x // otherwise we should be using `element.sortable('instance')` var data = element.data('ui-sortable'); - if (data && typeof data === 'object' && data.widgetFullName === 'ui-sortable') { + if ( + data && + typeof data === 'object' && + data.widgetFullName === 'ui-sortable' + ) { return data; } return null; @@ -77,10 +84,11 @@ angular.module('ui.sortable', []) function patchSortableOption(key, value) { if (callbacks[key]) { - if( key === 'stop' ){ + if (key === 'stop') { // call apply after stop - value = combineCallbacks( - value, function() { scope.$apply(); }); + value = combineCallbacks(value, function() { + scope.$apply(); + }); value = combineCallbacks(value, afterStop); } @@ -98,8 +106,11 @@ angular.module('ui.sortable', []) return value; } - function patchUISortableOptions(newOpts, oldOpts, sortableWidgetInstance) { - + function patchUISortableOptions( + newOpts, + oldOpts, + sortableWidgetInstance + ) { function addDummyOptionKey(value, key) { if (!(key in opts)) { // add the key in the opts object so that @@ -148,17 +159,27 @@ angular.module('ui.sortable', []) // handle the custom option of the directive first angular.forEach(newOpts, function(value, key) { if (key in directiveOpts) { - if (key === 'ui-floating' && (value === false || value === true) && sortableWidgetInstance) { + if ( + key === 'ui-floating' && + (value === false || value === true) && + sortableWidgetInstance + ) { sortableWidgetInstance.floating = value; } - if (key === 'ui-preserve-size' && (value === false || value === true)) { + if ( + key === 'ui-preserve-size' && + (value === false || value === true) + ) { var userProvidedHelper = opts.helper; newOpts.helper = function(e, item) { if (opts['ui-preserve-size'] === true) { setItemChildrenWidth(item); } - return (userProvidedHelper || dummyHelper).apply(this, arguments); + return (userProvidedHelper || dummyHelper).apply( + this, + arguments + ); }; } @@ -185,15 +206,19 @@ angular.module('ui.sortable', []) return optsDiff; } - function getPlaceholderElement (element) { - var placeholder = element.sortable('option','placeholder'); + function getPlaceholderElement(element) { + var placeholder = element.sortable('option', 'placeholder'); // placeholder.element will be a function if the placeholder, has // been created (placeholder will be an object). If it hasn't // been created, either placeholder will be false if no // placeholder class was given or placeholder.element will be // undefined if a class was given (placeholder will be a string) - if (placeholder && placeholder.element && typeof placeholder.element === 'function') { + if ( + placeholder && + placeholder.element && + typeof placeholder.element === 'function' + ) { var result = placeholder.element(); // workaround for jquery ui 1.9.x, // not returning jquery collection @@ -203,24 +228,36 @@ angular.module('ui.sortable', []) return null; } - function getPlaceholderExcludesludes (element, placeholder) { + function getPlaceholderExcludesludes(element, placeholder) { // exact match with the placeholder's class attribute to handle // the case that multiple connected sortables exist and // the placeholder option equals the class of sortable items var notCssSelector = opts['ui-model-items'].replace(/[^,]*>/g, ''); - var excludes = element.find('[class="' + placeholder.attr('class') + '"]:not(' + notCssSelector + ')'); + var excludes = element.find( + '[class="' + + placeholder.attr('class') + + '"]:not(' + + notCssSelector + + ')' + ); return excludes; } - function hasSortingHelper (element, ui) { - var helperOption = element.sortable('option','helper'); - return helperOption === 'clone' || (typeof helperOption === 'function' && ui.item.sortable.isCustomHelperUsed()); + function hasSortingHelper(element, ui) { + var helperOption = element.sortable('option', 'helper'); + return ( + helperOption === 'clone' || + (typeof helperOption === 'function' && + ui.item.sortable.isCustomHelperUsed()) + ); } - function getSortingHelper (element, ui/*, savedNodes*/) { + function getSortingHelper(element, ui /*, savedNodes*/) { var result = null; - if (hasSortingHelper(element, ui) && - element.sortable( 'option', 'appendTo' ) === 'parent') { + if ( + hasSortingHelper(element, ui) && + element.sortable('option', 'appendTo') === 'parent' + ) { // The .ui-sortable-helper element (that's the default class name) result = helper; } @@ -229,7 +266,10 @@ angular.module('ui.sortable', []) // thanks jquery-ui function isFloating(item) { - return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display')); + return ( + /left|right/.test(item.css('float')) || + /inline|table-cell/.test(item.css('display')) + ); } function getElementContext(elementScopes, element) { @@ -249,7 +289,8 @@ angular.module('ui.sortable', []) // we can't just do ui.item.index() because there it might have siblings // which are not items function getItemIndex(item) { - return item.parent() + return item + .parent() .find(opts['ui-model-items']) .index(item); } @@ -283,25 +324,36 @@ angular.module('ui.sortable', []) helper: null }; - angular.extend(opts, directiveOpts, uiSortableConfig, scope.uiSortable); + angular.extend( + opts, + directiveOpts, + uiSortableConfig, + scope.uiSortable + ); if (!angular.element.fn || !angular.element.fn.jquery) { - $log.error('ui.sortable: jQuery should be included before AngularJS!'); + $log.error( + 'ui.sortable: jQuery should be included before AngularJS!' + ); return; } - function wireUp () { + function wireUp() { // When we add or remove elements, we need the sortable to 'refresh' // so it can find the new/removed elements. scope.$watchCollection('ngModel', function() { // Timeout to let ng-repeat modify the DOM - $timeout(function() { - // ensure that the jquery-ui-sortable widget instance - // is still bound to the directive's element - if (!!getSortableWidgetInstance(element)) { - element.sortable('refresh'); - } - }, 0, false); + $timeout( + function() { + // ensure that the jquery-ui-sortable widget instance + // is still bound to the directive's element + if (!!getSortableWidgetInstance(element)) { + element.sortable('refresh'); + } + }, + 0, + false + ); }); callbacks.start = function(e, ui) { @@ -309,7 +361,9 @@ angular.module('ui.sortable', []) // since the drag has started, the element will be // absolutely positioned, so we check its siblings var siblings = ui.item.siblings(); - var sortableWidgetInstance = getSortableWidgetInstance(angular.element(e.target)); + var sortableWidgetInstance = getSortableWidgetInstance( + angular.element(e.target) + ); sortableWidgetInstance.floating = isFloating(siblings); } @@ -321,24 +375,24 @@ angular.module('ui.sortable', []) source: element, sourceList: ui.item.parent(), sourceModel: ngModel.$modelValue, - cancel: function () { + cancel: function() { ui.item.sortable._isCanceled = true; }, - isCanceled: function () { + isCanceled: function() { return ui.item.sortable._isCanceled; }, - isCustomHelperUsed: function () { + isCustomHelperUsed: function() { return !!ui.item.sortable._isCustomHelperUsed; }, _isCanceled: false, _isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed, - _destroy: function () { + _destroy: function() { angular.forEach(ui.item.sortable, function(value, key) { ui.item.sortable[key] = undefined; }); }, _connectedSortables: [], - _getElementContext: function (element) { + _getElementContext: function(element) { return getElementContext(this._connectedSortables, element); } }; @@ -346,9 +400,9 @@ angular.module('ui.sortable', []) callbacks.activate = function(e, ui) { var isSourceContext = ui.item.sortable.source === element; - var savedNodesOrigin = isSourceContext ? - ui.item.sortable.sourceList : - element; + var savedNodesOrigin = isSourceContext + ? ui.item.sortable.sourceList + : element; var elementContext = { element: element, scope: scope, @@ -369,7 +423,10 @@ angular.module('ui.sortable', []) // don't inlcude it in saved nodes. var placeholder = getPlaceholderElement(element); if (placeholder && placeholder.length) { - var excludes = getPlaceholderExcludesludes(element, placeholder); + var excludes = getPlaceholderExcludesludes( + element, + placeholder + ); savedNodes = savedNodes.not(excludes); } }; @@ -380,12 +437,19 @@ angular.module('ui.sortable', []) // the value will be overwritten with the old value if (!ui.item.sortable.received) { ui.item.sortable.dropindex = getItemIndex(ui.item); - var droptarget = ui.item.parent().closest('[ui-sortable], [data-ui-sortable], [x-ui-sortable]'); + var droptarget = ui.item + .parent() + .closest( + '[ui-sortable], [data-ui-sortable], [x-ui-sortable]' + ); ui.item.sortable.droptarget = droptarget; ui.item.sortable.droptargetList = ui.item.parent(); - var droptargetContext = ui.item.sortable._getElementContext(droptarget); - ui.item.sortable.droptargetModel = droptargetContext.scope.ngModel; + var droptargetContext = ui.item.sortable._getElementContext( + droptarget + ); + ui.item.sortable.droptargetModel = + droptargetContext.scope.ngModel; // Cancel the sort (let ng-repeat do the sort for us) // Don't cancel if this is the received list because it has @@ -399,7 +463,9 @@ angular.module('ui.sortable', []) // the start and stop of repeat sections and sortable doesn't // respect their order (even if we cancel, the order of the // comments are still messed up). - var sortingHelper = !ui.item.sortable.received && getSortingHelper(element, ui, savedNodes); + var sortingHelper = + !ui.item.sortable.received && + getSortingHelper(element, ui, savedNodes); if (sortingHelper && sortingHelper.length) { // Restore all the savedNodes except from the sorting helper element. // That way it will be garbage collected. @@ -421,9 +487,12 @@ angular.module('ui.sortable', []) // stop event where we will know if it was a sort or item was // moved here from another list if (ui.item.sortable.received && !ui.item.sortable.isCanceled()) { - scope.$apply(function () { - ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0, - ui.item.sortable.moved); + scope.$apply(function() { + ngModel.$modelValue.splice( + ui.item.sortable.dropindex, + 0, + ui.item.sortable.moved + ); }); scope.$emit('ui-sortable:moved', ui); } @@ -433,19 +502,26 @@ angular.module('ui.sortable', []) // If the received flag hasn't be set on the item, this is a // normal sort, if dropindex is set, the item was moved, so move // the items in the list. - var wasMoved = ('dropindex' in ui.item.sortable) && - !ui.item.sortable.isCanceled(); + var wasMoved = + 'dropindex' in ui.item.sortable && + !ui.item.sortable.isCanceled(); if (wasMoved && !ui.item.sortable.received) { - - scope.$apply(function () { + scope.$apply(function() { ngModel.$modelValue.splice( - ui.item.sortable.dropindex, 0, - ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]); + ui.item.sortable.dropindex, + 0, + ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0] + ); }); scope.$emit('ui-sortable:moved', ui); - } else if (!wasMoved && - !angular.equals(element.contents().toArray(), savedNodes.toArray())) { + } else if ( + !wasMoved && + !angular.equals( + element.contents().toArray(), + savedNodes.toArray() + ) + ) { // if the item was not moved // and the DOM element order has changed, // then restore the elements @@ -457,7 +533,9 @@ angular.module('ui.sortable', []) // That way it will be garbage collected. savedNodes = savedNodes.not(sortingHelper); } - var elementContext = ui.item.sortable._getElementContext(element); + var elementContext = ui.item.sortable._getElementContext( + element + ); savedNodes.appendTo(elementContext.savedNodesOrigin); } @@ -485,31 +563,37 @@ angular.module('ui.sortable', []) // Remove the item from this list's model and copy data into item, // so the next list can retrive it if (!ui.item.sortable.isCanceled()) { - scope.$apply(function () { + scope.$apply(function() { ui.item.sortable.moved = ngModel.$modelValue.splice( - ui.item.sortable.index, 1)[0]; + ui.item.sortable.index, + 1 + )[0]; }); } }; // setup attribute handlers angular.forEach(callbacks, function(value, key) { - callbacks[key] = combineCallbacks(callbacks[key], - function () { - var attrHandler = scope[key]; - var attrHandlerFn; - if (typeof attrHandler === 'function' && - ('uiSortable' + key.substring(0,1).toUpperCase() + key.substring(1)).length && - typeof (attrHandlerFn = attrHandler()) === 'function') { - attrHandlerFn.apply(this, arguments); - } - }); + callbacks[key] = combineCallbacks(callbacks[key], function() { + var attrHandler = scope[key]; + var attrHandlerFn; + if ( + typeof attrHandler === 'function' && + ( + 'uiSortable' + + key.substring(0, 1).toUpperCase() + + key.substring(1) + ).length && + typeof (attrHandlerFn = attrHandler()) === 'function' + ) { + attrHandlerFn.apply(this, arguments); + } + }); }); - - wrappers.helper = function (inner) { + wrappers.helper = function(inner) { if (inner && typeof inner === 'function') { - return function (e, item) { + return function(e, item) { var oldItemSortable = item.sortable; var index = getItemIndex(item); @@ -519,7 +603,7 @@ angular.module('ui.sortable', []) source: element, sourceList: item.parent(), sourceModel: ngModel.$modelValue, - _restore: function () { + _restore: function() { angular.forEach(item.sortable, function(value, key) { item.sortable[key] = undefined; }); @@ -537,23 +621,31 @@ angular.module('ui.sortable', []) return inner; }; - scope.$watchCollection('uiSortable', function(newOpts, oldOpts) { - // ensure that the jquery-ui-sortable widget instance - // is still bound to the directive's element - var sortableWidgetInstance = getSortableWidgetInstance(element); - if (!!sortableWidgetInstance) { - var optsDiff = patchUISortableOptions(newOpts, oldOpts, sortableWidgetInstance); - - if (optsDiff) { - element.sortable('option', optsDiff); + scope.$watchCollection( + 'uiSortable', + function(newOpts, oldOpts) { + // ensure that the jquery-ui-sortable widget instance + // is still bound to the directive's element + var sortableWidgetInstance = getSortableWidgetInstance(element); + if (!!sortableWidgetInstance) { + var optsDiff = patchUISortableOptions( + newOpts, + oldOpts, + sortableWidgetInstance + ); + + if (optsDiff) { + element.sortable('option', optsDiff); + } } - } - }, true); + }, + true + ); patchUISortableOptions(opts); } - function init () { + function init() { if (ngModel) { wireUp(); } else { @@ -564,7 +656,7 @@ angular.module('ui.sortable', []) element.sortable(opts); } - function initIfEnabled () { + function initIfEnabled() { if (scope.uiSortable && scope.uiSortable.disabled) { return false; } @@ -581,7 +673,10 @@ angular.module('ui.sortable', []) initIfEnabled.cancelWatcher = angular.noop; if (!initIfEnabled()) { - initIfEnabled.cancelWatcher = scope.$watch('uiSortable.disabled', initIfEnabled); + initIfEnabled.cancelWatcher = scope.$watch( + 'uiSortable.disabled', + initIfEnabled + ); } } }; diff --git a/test/karma.conf.js b/test/karma.conf.js index a803dcc..1067454 100644 --- a/test/karma.conf.js +++ b/test/karma.conf.js @@ -7,7 +7,9 @@ module.exports = function(config) { var wiredep = require('wiredep'); var fs = require('fs'); - var bowerOverrides = JSON.parse(fs.readFileSync('./test/bower_overrides.json')); + var bowerOverrides = JSON.parse( + fs.readFileSync('./test/bower_overrides.json') + ); var devJSDependencies = wiredep({ devDependencies: true, @@ -15,15 +17,12 @@ module.exports = function(config) { }).js; config.set({ - // base path, that will be used to resolve files and exclude basePath: '..', - // frameworks to use frameworks: ['jasmine'], - // list of files / patterns to load in the browser files: devJSDependencies.concat([ 'test/libs/jquery.simulate.dragandrevert.js', @@ -34,35 +33,26 @@ module.exports = function(config) { 'test/sortable.tests.css' ]), - // list of files to exclude - exclude: [ - - ], - + exclude: [], // test results reporter to use // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage' reporters: ['progress'], - // web server port port: 9876, - // enable / disable colors in the output (reporters and logs) colors: true, - // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG logLevel: config.LOG_INFO, - // enable / disable watching file and executing tests whenever any file changes autoWatch: false, - // Start these browsers, currently available: // - Chrome // - ChromeCanary @@ -71,13 +61,11 @@ module.exports = function(config) { // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`) // - PhantomJS // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`) - browsers: ['Chrome', 'Firefox'/*, 'PhantomJS'*/], - + browsers: ['Chrome', 'Firefox' /*, 'PhantomJS'*/], // If browser does not capture in given timeout [ms], kill it captureTimeout: 60000, - // Continuous Integration mode // if true, it capture browsers, run tests and exit singleRun: false diff --git a/test/libs/jquery.simulate.dragandrevert.js b/test/libs/jquery.simulate.dragandrevert.js index 03cda66..5ca102f 100644 --- a/test/libs/jquery.simulate.dragandrevert.js +++ b/test/libs/jquery.simulate.dragandrevert.js @@ -1,60 +1,60 @@ -;(function($, undefined) { - function findCenter(elem) { - var offset, - document = $(elem.ownerDocument); - elem = $(elem); - offset = elem.offset(); - - return { - x: offset.left + elem.outerWidth() / 2 - document.scrollLeft(), - y: offset.top + elem.outerHeight() / 2 - document.scrollTop() - }; - } - - $.extend($.simulate.prototype, { - simulateDragAndRevert: function() { - var i = 0, - target = this.target, - options = this.options, - center = findCenter(target), - x = Math.floor(center.x), - y = Math.floor(center.y), - dx = options.dx || 0, - dy = options.dy || 0, - moves = options.moves || 3, - coord = { - clientX: x, - clientY: y - }; - - this.simulateEvent(target, "mousedown", coord); - - for (; i < moves; i++) { - x += dx / moves; - y += dy / moves; - - coord = { - clientX: Math.round(x), - clientY: Math.round(y) - }; - - this.simulateEvent(document, "mousemove", coord); - } - - for (i = 0; i < moves; i++) { - x -= dx / moves; - y -= dy / moves; - - coord = { - clientX: Math.round(x), - clientY: Math.round(y) - }; - - this.simulateEvent(document, "mousemove", coord); - } - - this.simulateEvent(target, "mouseup", coord); - this.simulateEvent(target, "click", coord); - } - }); +(function($, undefined) { + function findCenter(elem) { + var offset, + document = $(elem.ownerDocument); + elem = $(elem); + offset = elem.offset(); + + return { + x: offset.left + elem.outerWidth() / 2 - document.scrollLeft(), + y: offset.top + elem.outerHeight() / 2 - document.scrollTop() + }; + } + + $.extend($.simulate.prototype, { + simulateDragAndRevert: function() { + var i = 0, + target = this.target, + options = this.options, + center = findCenter(target), + x = Math.floor(center.x), + y = Math.floor(center.y), + dx = options.dx || 0, + dy = options.dy || 0, + moves = options.moves || 3, + coord = { + clientX: x, + clientY: y + }; + + this.simulateEvent(target, 'mousedown', coord); + + for (; i < moves; i++) { + x += dx / moves; + y += dy / moves; + + coord = { + clientX: Math.round(x), + clientY: Math.round(y) + }; + + this.simulateEvent(document, 'mousemove', coord); + } + + for (i = 0; i < moves; i++) { + x -= dx / moves; + y -= dy / moves; + + coord = { + clientX: Math.round(x), + clientY: Math.round(y) + }; + + this.simulateEvent(document, 'mousemove', coord); + } + + this.simulateEvent(target, 'mouseup', coord); + this.simulateEvent(target, 'click', coord); + } + }); })(jQuery); diff --git a/test/sortable.e2e.callbacks.attr.spec.js b/test/sortable.e2e.callbacks.attr.spec.js index 0226f3a..f09f8ff 100644 --- a/test/sortable.e2e.callbacks.attr.spec.js +++ b/test/sortable.e2e.callbacks.attr.spec.js @@ -1,40 +1,52 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + 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, hasUndefinedProperties, beforeLiElement, afterLiElement; - - beforeEach(inject(function (sortableTestHelper) { - EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; - listContent = sortableTestHelper.listContent; - hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; - beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; - afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; - })); + var EXTRA_DY_PERCENTAGE, + listContent, + hasUndefinedProperties, + beforeLiElement, + afterLiElement; + + beforeEach( + inject(function(sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; + beforeLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterLiElement; + }) + ); tests.description = 'Attribute Callbacks related'; - function tests (useExtraElements) { - + function tests(useExtraElements) { var host; - beforeEach(inject(function() { - host = $('
      '); - $('body').append(host); + beforeEach( + inject(function() { + host = $('
      '); + $('body').append(host); - if (!useExtraElements) { - beforeLiElement = afterLiElement = ''; - } - })); + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + } + }) + ); afterEach(function() { host.remove(); @@ -44,12 +56,15 @@ describe('uiSortable', function() { it('should cancel sorting of node "Two"', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.update = function(e, ui) { if (ui.item.sortable.model === 'Two') { @@ -97,7 +112,8 @@ describe('uiSortable', function() { it('should call all callbacks with the proper context', function() { inject(function($compile, $rootScope) { - var element, callbackContexts = {}; + var element, + callbackContexts = {}; $rootScope.$apply(function() { $rootScope.create = function() { callbackContexts.create = this; @@ -134,27 +150,28 @@ describe('uiSortable', function() { spyOn($rootScope, 'deactivate').and.callThrough(); spyOn($rootScope, 'stop').and.callThrough(); $rootScope.items = ['One', 'Two', 'Three']; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); }); host.append(element); - $rootScope.$apply(function() { - }); + $rootScope.$apply(function() {}); var li = element.find('[ng-repeat]:eq(0)'); var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); li.simulate('drag', { dy: dy }); @@ -184,16 +201,15 @@ describe('uiSortable', function() { }); } - [0, 1].forEach(function(useExtraElements){ + [0, 1].forEach(function(useExtraElements) { var testDescription = tests.description; if (useExtraElements) { testDescription += ' with extra elements'; } - describe(testDescription, function(){ + describe(testDescription, function() { tests(useExtraElements); }); }); - -}); \ No newline at end of file +}); diff --git a/test/sortable.e2e.callbacks.spec.js b/test/sortable.e2e.callbacks.spec.js index e944353..29356f8 100644 --- a/test/sortable.e2e.callbacks.spec.js +++ b/test/sortable.e2e.callbacks.spec.js @@ -1,40 +1,52 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + 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, hasUndefinedProperties, beforeLiElement, afterLiElement; - - beforeEach(inject(function (sortableTestHelper) { - EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; - listContent = sortableTestHelper.listContent; - hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; - beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; - afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; - })); + var EXTRA_DY_PERCENTAGE, + listContent, + hasUndefinedProperties, + beforeLiElement, + afterLiElement; + + beforeEach( + inject(function(sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; + beforeLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterLiElement; + }) + ); tests.description = 'Callbacks related'; - function tests (useExtraElements) { - + function tests(useExtraElements) { var host; - beforeEach(inject(function() { - host = $('
      '); - $('body').append(host); + beforeEach( + inject(function() { + host = $('
      '); + $('body').append(host); - if (!useExtraElements) { - beforeLiElement = afterLiElement = ''; - } - })); + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + } + }) + ); afterEach(function() { host.remove(); @@ -44,12 +56,15 @@ describe('uiSortable', function() { it('should cancel sorting of node "Two"', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { update: function(e, ui) { @@ -100,15 +115,17 @@ describe('uiSortable', function() { it('should cancel sorting of node "Two" and "helper: function" that returns an element is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item.clone(); }, update: function(e, ui) { @@ -159,15 +176,17 @@ describe('uiSortable', function() { it('should cancel sorting of node "Two" when then helper is appended to the `body`', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item.clone().appendTo('body'); }, update: function(e, ui) { @@ -218,15 +237,17 @@ describe('uiSortable', function() { it('should cancel sorting of node "Two" and "helper: function" that returns a list element is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item; }, update: function(e, ui) { @@ -277,18 +298,22 @@ describe('uiSortable', function() { it('should update model from update() callback', function() { inject(function($compile, $rootScope) { var element, logsElement; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); - logsElement = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ log }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); + logsElement = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ log }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { update: function(e, ui) { @@ -318,18 +343,22 @@ describe('uiSortable', function() { it('should update model from stop() callback', function() { inject(function($compile, $rootScope) { var element, logsElement; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); - logsElement = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ log }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); + logsElement = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ log }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { stop: function(e, ui) { @@ -361,17 +390,17 @@ describe('uiSortable', function() { $rootScope.$apply(function() { $rootScope.items = ['One', 'Two', 'Three']; $rootScope.opts = { - create: function() { - - } + create: function() {} }; spyOn($rootScope.opts, 'create'); - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); }); host.append(element); @@ -385,12 +414,14 @@ describe('uiSortable', function() { it('should properly set ui.item.sortable properties', function() { inject(function($compile, $rootScope) { var element, updateCallbackExpectations; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { update: function(e, ui) { @@ -405,8 +436,7 @@ describe('uiSortable', function() { host.append(element); - $rootScope.$apply(function() { - }); + $rootScope.$apply(function() {}); var li = element.find('[ng-repeat]:eq(1)'); var dy = (1 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); updateCallbackExpectations = function(uiItemSortable) { @@ -461,7 +491,8 @@ describe('uiSortable', function() { it('should call all callbacks with the proper context', function() { inject(function($compile, $rootScope) { - var element, callbackContexts = {}; + var element, + callbackContexts = {}; $rootScope.$apply(function() { $rootScope.opts = { helper: function(e, item) { @@ -499,18 +530,19 @@ describe('uiSortable', function() { spyOn($rootScope.opts, 'deactivate').and.callThrough(); spyOn($rootScope.opts, 'stop').and.callThrough(); $rootScope.items = ['One', 'Two', 'Three']; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); }); host.append(element); - $rootScope.$apply(function() { - }); + $rootScope.$apply(function() {}); var li = element.find('[ng-repeat]:eq(0)'); var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); li.simulate('drag', { dy: dy }); @@ -542,15 +574,17 @@ describe('uiSortable', function() { it('should properly free ui.item.sortable object', function() { inject(function($compile, $rootScope) { var element, uiItem, uiItemSortable_Destroy; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - start: function (e, ui) { + start: function(e, ui) { uiItem = ui.item; spyOn(ui.item.sortable, '_destroy').and.callThrough(); uiItemSortable_Destroy = ui.item.sortable._destroy; @@ -575,7 +609,6 @@ describe('uiSortable', function() { expect(hasUndefinedProperties(uiItem.sortable)).toBe(true); uiItem = uiItemSortable_Destroy = undefined; - li = element.find('[ng-repeat]:eq(0)'); dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); li.simulate('drag', { dy: dy }); @@ -585,7 +618,6 @@ describe('uiSortable', function() { expect(hasUndefinedProperties(uiItem.sortable)).toBe(true); uiItem = uiItemSortable_Destroy = undefined; - li = element.find('[ng-repeat]:eq(2)'); dy = -(2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); li.simulate('drag', { dy: dy }); @@ -601,20 +633,26 @@ describe('uiSortable', function() { it('should provide the item.sortable properties on helper callback', function() { inject(function($compile, $rootScope) { - var element, helperItem, itemSortable_Restore, sortableAfterRestore, helperCallbackExpectations; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + var element, + helperItem, + itemSortable_Restore, + sortableAfterRestore, + helperCallbackExpectations; + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { helper: function(e, item) { helperItem = item; var oldRestore = item.sortable._restore; - item.sortable._restore = function () { + item.sortable._restore = function() { oldRestore.apply(this, arguments); // hold the value of the sortable object // right after the _restore method completes @@ -632,8 +670,7 @@ describe('uiSortable', function() { host.append(element); - $rootScope.$apply(function() { - }); + $rootScope.$apply(function() {}); var li = element.find('[ng-repeat]:eq(0)'); var dy = (2 + EXTRA_DY_PERCENTAGE) * li.outerHeight(); @@ -660,18 +697,22 @@ describe('uiSortable', function() { it('should properly reset a deleted callback option', function() { inject(function($compile, $rootScope) { var element, logsElement; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); - logsElement = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ log }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); + logsElement = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ log }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { stop: function(e, ui) { @@ -693,7 +734,7 @@ describe('uiSortable', function() { expect($rootScope.logs).toEqual(listContent(logsElement)); $rootScope.$digest(); - + $rootScope.$apply(function() { $rootScope.opts = {}; }); @@ -711,19 +752,17 @@ describe('uiSortable', function() { $(logsElement).remove(); }); }); - } - [0, 1].forEach(function(useExtraElements){ + [0, 1].forEach(function(useExtraElements) { var testDescription = tests.description; if (useExtraElements) { testDescription += ' with extra elements'; } - describe(testDescription, function(){ + describe(testDescription, function() { tests(useExtraElements); }); }); - -}); \ No newline at end of file +}); diff --git a/test/sortable.e2e.directiveoptions.spec.js b/test/sortable.e2e.directiveoptions.spec.js index 8fefffb..af7c91c 100644 --- a/test/sortable.e2e.directiveoptions.spec.js +++ b/test/sortable.e2e.directiveoptions.spec.js @@ -1,42 +1,59 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + 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, beforeLiElement, afterLiElement, beforeTrElement, afterTrElement; - - beforeEach(inject(function (sortableTestHelper) { - EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; - listContent = sortableTestHelper.listContent; - beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; - afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; - beforeTrElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeTrElement; - afterTrElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterTrElement; - })); + var EXTRA_DY_PERCENTAGE, + listContent, + beforeLiElement, + afterLiElement, + beforeTrElement, + afterTrElement; + + beforeEach( + inject(function(sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + beforeLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterLiElement; + beforeTrElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeTrElement; + afterTrElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterTrElement; + }) + ); tests.description = 'Custom directive options related'; - function tests (useExtraElements) { - + function tests(useExtraElements) { var host; - beforeEach(inject(function() { - host = $('
      '); - $('body').append(host); + beforeEach( + inject(function() { + host = $('
      '); + $('body').append(host); - if (!useExtraElements) { - beforeLiElement = afterLiElement = ''; - beforeTrElement = afterTrElement = ''; - } - })); + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + beforeTrElement = afterTrElement = ''; + } + }) + ); afterEach(function() { host.remove(); @@ -46,12 +63,15 @@ describe('uiSortable', function() { it('should work when "ui-floating: false" option is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { 'ui-floating': false @@ -86,12 +106,15 @@ describe('uiSortable', function() { it('should work when "ui-floating: true" option is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement.replace('
      • ', '
      • '), - '
      • {{ item }}
      • ', - afterLiElement.replace('
      • ', '
      • '), - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement.replace('
      • ', '
      • '), + '
      • {{ item }}
      • ', + afterLiElement.replace('
      • ', '
      • '), + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { 'ui-floating': true @@ -126,12 +149,15 @@ describe('uiSortable', function() { it('should work when "ui-floating: \'auto\'" option is used and elements are "float"ing', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement.replace('
      • ', '
      • '), - '
      • {{ item }}
      • ', - afterLiElement.replace('
      • ', '
      • '), - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement.replace('
      • ', '
      • '), + '
      • {{ item }}
      • ', + afterLiElement.replace('
      • ', '
      • '), + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { 'ui-floating': 'auto' @@ -166,12 +192,15 @@ describe('uiSortable', function() { it('should work when "ui-floating: \'auto\'" option is used and elements are "display: inline-block"', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement.replace('
      • ', '
      • '), - '
      • {{ item }}
      • ', - afterLiElement.replace('
      • ', '
      • '), - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement.replace('
      • ', '
      • '), + '
      • {{ item }}
      • ', + afterLiElement.replace('
      • ', '
      • '), + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { 'ui-floating': 'auto' @@ -206,12 +235,14 @@ describe('uiSortable', function() { it('should properly reset deleted directive options', function() { inject(function($compile, $rootScope) { var element, logsElement; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement + - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { 'ui-floating': true, @@ -223,11 +254,11 @@ describe('uiSortable', function() { host.append(element).append(logsElement); var sortableWidgetInstance = element.data('ui-sortable'); - + expect(sortableWidgetInstance.floating).toBe(true); $rootScope.$digest(); - + $rootScope.$apply(function() { $rootScope.opts = {}; }); @@ -247,12 +278,15 @@ describe('uiSortable', function() { it('should work when custom "ui-model-items" option is used with an attribute selector', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); var itemsSelector = '[ui-sortable-item]'; $rootScope.$apply(function() { @@ -284,12 +318,15 @@ describe('uiSortable', function() { it('should work when custom "ui-model-items" option is used with a class selector', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); var itemsSelector = '.ui-sortable-item'; $rootScope.$apply(function() { @@ -321,14 +358,23 @@ describe('uiSortable', function() { xit('should work with multiple [ng-repeat] when attribute "ui-model-items" selector', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - beforeLiElement.replace('
      • ', '
      • {{ item }}'), - '
      • {{ item }}
      • ', - afterLiElement.replace('
      • ', '
      • {{ item }}'), - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + beforeLiElement.replace( + '
      • ', + '
      • {{ item }}' + ), + '
      • {{ item }}
      • ', + afterLiElement.replace( + '
      • ', + '
      • {{ item }}' + ), + afterLiElement, + '
      ' + ) + )($rootScope); var itemsSelector = '[ui-sortable-item]'; $rootScope.$apply(function() { @@ -360,14 +406,23 @@ describe('uiSortable', function() { xit('should work with multiple [ng-repeat] when class "ui-model-items" selector', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - beforeLiElement.replace('
      • ', '
      • {{ item }}'), - '
      • {{ item }}
      • ', - afterLiElement.replace('
      • ', '
      • {{ item }}'), - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + beforeLiElement.replace( + '
      • ', + '
      • {{ item }}' + ), + '
      • {{ item }}
      • ', + afterLiElement.replace( + '
      • ', + '
      • {{ item }}' + ), + afterLiElement, + '
      ' + ) + )($rootScope); var itemsSelector = '.ui-sortable-item'; $rootScope.$apply(function() { @@ -400,18 +455,20 @@ describe('uiSortable', function() { inject(function($compile, $rootScope) { var width = '200px'; var element; - element = $compile(''.concat( - '
      `s. -#### Attributes For Event Handling +### Attributes For Event Handling To handle events with html bindings just define any expression to listed event attributes. If you defined an attribute for this events and defined callback function in sortableOptions at the same time, the attribute based callback will be called first. @@ -161,7 +179,7 @@ $scope.sortableOptions = { ``` -#### Canceling +### Canceling Inside the `update` callback, you can check the item that is dragged and cancel the sorting. diff --git a/src/sortable.js b/src/sortable.js index 40d5f25..1076c85 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -18,7 +18,6 @@ angular.module('ui.sortable', []) scope: { ngModel:'=', uiSortable:'=', - uiPreserveSize: '=uiPreserveSize', ////Expression bindings from html. create:'&uiSortableCreate', // helper:'&uiSortableHelper', @@ -63,6 +62,19 @@ angular.module('ui.sortable', []) return null; } + function setItemChildrenWidth(item) { + item.children().each(function() { + var $el = angular.element(this); + + // Preserve the with of the element + $el.width($el.width()); + }); + } + + function dummyHelper(e, item) { + return item; + } + function patchSortableOption(key, value) { if (callbacks[key]) { if( key === 'stop' ){ @@ -86,7 +98,8 @@ angular.module('ui.sortable', []) return value; } - function patchUISortableOptions(newVal, oldVal, sortableWidgetInstance) { + function patchUISortableOptions(newOpts, oldOpts, sortableWidgetInstance) { + function addDummyOptionKey(value, key) { if (!(key in opts)) { // add the key in the opts object so that @@ -101,11 +114,11 @@ angular.module('ui.sortable', []) // update some options of the sortable var optsDiff = null; - if (oldVal) { + if (oldOpts) { // reset deleted options to default var defaultOptions; - angular.forEach(oldVal, function(oldValue, key) { - if (!newVal || !(key in newVal)) { + angular.forEach(oldOpts, function(oldValue, key) { + if (!newOpts || !(key in newOpts)) { if (key in directiveOpts) { if (key === 'ui-floating') { opts[key] = 'auto'; @@ -130,16 +143,33 @@ angular.module('ui.sortable', []) }); } + newOpts = angular.extend({}, newOpts); // update changed options - angular.forEach(newVal, function(value, key) { - // if it's a custom option of the directive, - // handle it approprietly + // handle the custom option of the directive first + angular.forEach(newOpts, function(value, key) { if (key in directiveOpts) { if (key === 'ui-floating' && (value === false || value === true) && sortableWidgetInstance) { sortableWidgetInstance.floating = value; } + if (key === 'ui-preserve-size' && (value === false || value === true)) { + var userProvidedHelper = opts.helper; + newOpts.helper = function(e, item) { + if (opts['ui-preserve-size'] === true) { + setItemChildrenWidth(item); + } + return (userProvidedHelper || dummyHelper).apply(this, arguments); + }; + } + opts[key] = patchSortableOption(key, value); + } + }); + + // handle the normal option of the directive + angular.forEach(newOpts, function(value, key) { + if (key in directiveOpts) { + // the custom option of the directive are already handled return; } @@ -198,7 +228,7 @@ angular.module('ui.sortable', []) } // thanks jquery-ui - function isFloating (item) { + function isFloating(item) { return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display')); } @@ -229,7 +259,8 @@ angular.module('ui.sortable', []) // directive specific options var directiveOpts = { 'ui-floating': undefined, - 'ui-model-items': uiSortableConfig.items + 'ui-model-items': uiSortableConfig.items, + 'ui-preserve-size': undefined }; var callbacks = { @@ -482,15 +513,6 @@ angular.module('ui.sortable', []) var oldItemSortable = item.sortable; var index = getItemIndex(item); - if (typeof scope.uiPreserveSize === 'boolean' && scope.uiPreserveSize !== false) { - item.children().each(function () { - var $el = angular.element(this); - - // Preserve the with of the element - $el.width($el.width()); - }); - } - item.sortable = { model: ngModel.$modelValue[index], index: index, @@ -515,12 +537,12 @@ angular.module('ui.sortable', []) return inner; }; - scope.$watchCollection('uiSortable', function(newVal, oldVal) { + scope.$watchCollection('uiSortable', function(newOpts, oldOpts) { // ensure that the jquery-ui-sortable widget instance // is still bound to the directive's element var sortableWidgetInstance = getSortableWidgetInstance(element); if (!!sortableWidgetInstance) { - var optsDiff = patchUISortableOptions(newVal, oldVal, sortableWidgetInstance); + var optsDiff = patchUISortableOptions(newOpts, oldOpts, sortableWidgetInstance); if (optsDiff) { element.sortable('option', optsDiff); diff --git a/test/sortable.e2e.directiveoptions.spec.js b/test/sortable.e2e.directiveoptions.spec.js index 0b4b174..8fefffb 100644 --- a/test/sortable.e2e.directiveoptions.spec.js +++ b/test/sortable.e2e.directiveoptions.spec.js @@ -12,13 +12,15 @@ describe('uiSortable', function() { beforeEach(module('ui.sortable')); beforeEach(module('ui.sortable.testHelper')); - var EXTRA_DY_PERCENTAGE, listContent, beforeLiElement, afterLiElement; + var EXTRA_DY_PERCENTAGE, listContent, beforeLiElement, afterLiElement, beforeTrElement, afterTrElement; beforeEach(inject(function (sortableTestHelper) { EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; listContent = sortableTestHelper.listContent; beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; + beforeTrElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeTrElement; + afterTrElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterTrElement; })); tests.description = 'Custom directive options related'; @@ -32,6 +34,7 @@ describe('uiSortable', function() { if (!useExtraElements) { beforeLiElement = afterLiElement = ''; + beforeTrElement = afterTrElement = ''; } })); @@ -393,6 +396,147 @@ describe('uiSortable', function() { }); }); + it('should work when the "ui-preserve-size" option is used', function() { + inject(function($compile, $rootScope) { + var width = '200px'; + var element; + element = $compile(''.concat( + '', + '', + '', + beforeTrElement, + '', + '', + '', + afterTrElement, + '', + '
      {{ item }}
      ' + ))($rootScope); + + var itemsSelector = '.sortable-item'; + $rootScope.$apply(function() { + $rootScope.opts = { + 'ui-preserve-size': true, + stop: function(e, ui) { + expect(ui.item.children().css('width')).toEqual(width); + } + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element).append('
      '); + + var tr = element.find(itemsSelector + ':eq(1)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); + tr.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + + tr = element.find(itemsSelector + ':eq(1)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); + tr.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + + $(element).remove(); + }); + }); + + it('should work when the "ui-preserve-size" option is false', function() { + inject(function($compile, $rootScope) { + var width = '200px'; + var element; + element = $compile(''.concat( + '', + '', + '', + beforeTrElement, + '', + '', + '', + afterTrElement, + '', + '
      {{ item }}
      ' + ))($rootScope); + + var itemsSelector = '.sortable-item'; + $rootScope.$apply(function() { + $rootScope.opts = { + 'ui-preserve-size': false, + stop: function(e, ui) { + expect(ui.item.children().attr('style')).toEqual(undefined); + } + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element).append('
      '); + + var tr = element.find(itemsSelector + ':eq(1)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); + tr.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + + tr = element.find(itemsSelector + ':eq(1)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); + tr.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + + $(element).remove(); + }); + }); + + it('should work when the "ui-preserve-size" & helper options are used', function() { + inject(function($compile, $rootScope) { + var width = '200px'; + var element; + element = $compile(''.concat( + '', + '', + '', + beforeTrElement, + '', + '', + '', + afterTrElement, + '', + '
      {{ item }}
      ' + ))($rootScope); + + var itemsSelector = '.sortable-item'; + $rootScope.$apply(function() { + $rootScope.opts = { + 'ui-preserve-size': true, + helper: function (e, item) { + return item.clone(); + }, + stop: function(e, ui) { + expect(ui.item.children().css('width')).toEqual(width); + } + }; + $rootScope.items = ['One', 'Two', 'Three']; + }); + + host.append(element).append('
      '); + + var tr = element.find(itemsSelector + ':eq(1)'); + var dy = (1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); + tr.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['One', 'Three', 'Two']); + expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + + tr = element.find(itemsSelector + ':eq(1)'); + dy = -(1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); + tr.simulate('drag', { dy: dy }); + expect($rootScope.items).toEqual(['Three', 'One', 'Two']); + expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + + $(element).remove(); + }); + }); + } [0, 1].forEach(function(useExtraElements){ diff --git a/test/sortable.test-helper.js b/test/sortable.test-helper.js index 38721b4..6f5dd7b 100644 --- a/test/sortable.test-helper.js +++ b/test/sortable.test-helper.js @@ -102,6 +102,8 @@ angular.module('ui.sortable.testHelper', []) extraElements: { beforeLiElement: '
    • extra element
    • ', afterLiElement: '
    • extra element
    • ', + beforeTrElement: '
      extra element
      extra element
      ', + element = $compile( + ''.concat( + '
      ', '', '', - beforeTrElement, - '', - '', - '', - afterTrElement, + beforeTrElement, + '', + '', + '', + afterTrElement, '', - '
      {{ item }}
      {{ item }}
      ' - ))($rootScope); + '' + ) + )($rootScope); var itemsSelector = '.sortable-item'; $rootScope.$apply(function() { @@ -430,13 +487,21 @@ describe('uiSortable', function() { var dy = (1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); tr.simulate('drag', { dy: dy }); expect($rootScope.items).toEqual(['One', 'Three', 'Two']); - expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + expect($rootScope.items).toEqual( + listContent(element.find('tbody')) + .map($) + .map($.text) + ); tr = element.find(itemsSelector + ':eq(1)'); dy = -(1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); tr.simulate('drag', { dy: dy }); expect($rootScope.items).toEqual(['Three', 'One', 'Two']); - expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + expect($rootScope.items).toEqual( + listContent(element.find('tbody')) + .map($) + .map($.text) + ); $(element).remove(); }); @@ -446,18 +511,20 @@ describe('uiSortable', function() { inject(function($compile, $rootScope) { var width = '200px'; var element; - element = $compile(''.concat( - '', + element = $compile( + ''.concat( + '
      ', '', '', - beforeTrElement, - '', - '', - '', - afterTrElement, + beforeTrElement, + '', + '', + '', + afterTrElement, '', - '
      {{ item }}
      {{ item }}
      ' - ))($rootScope); + '' + ) + )($rootScope); var itemsSelector = '.sortable-item'; $rootScope.$apply(function() { @@ -476,13 +543,21 @@ describe('uiSortable', function() { var dy = (1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); tr.simulate('drag', { dy: dy }); expect($rootScope.items).toEqual(['One', 'Three', 'Two']); - expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + expect($rootScope.items).toEqual( + listContent(element.find('tbody')) + .map($) + .map($.text) + ); tr = element.find(itemsSelector + ':eq(1)'); dy = -(1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); tr.simulate('drag', { dy: dy }); expect($rootScope.items).toEqual(['Three', 'One', 'Two']); - expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + expect($rootScope.items).toEqual( + listContent(element.find('tbody')) + .map($) + .map($.text) + ); $(element).remove(); }); @@ -492,24 +567,26 @@ describe('uiSortable', function() { inject(function($compile, $rootScope) { var width = '200px'; var element; - element = $compile(''.concat( - '', + element = $compile( + ''.concat( + '
      ', '', '', - beforeTrElement, - '', - '', - '', - afterTrElement, + beforeTrElement, + '', + '', + '', + afterTrElement, '', - '
      {{ item }}
      {{ item }}
      ' - ))($rootScope); + '' + ) + )($rootScope); var itemsSelector = '.sortable-item'; $rootScope.$apply(function() { $rootScope.opts = { 'ui-preserve-size': true, - helper: function (e, item) { + helper: function(e, item) { return item.clone(); }, stop: function(e, ui) { @@ -525,30 +602,36 @@ describe('uiSortable', function() { var dy = (1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); tr.simulate('drag', { dy: dy }); expect($rootScope.items).toEqual(['One', 'Three', 'Two']); - expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + expect($rootScope.items).toEqual( + listContent(element.find('tbody')) + .map($) + .map($.text) + ); tr = element.find(itemsSelector + ':eq(1)'); dy = -(1 + EXTRA_DY_PERCENTAGE) * tr.outerHeight(); tr.simulate('drag', { dy: dy }); expect($rootScope.items).toEqual(['Three', 'One', 'Two']); - expect($rootScope.items).toEqual(listContent(element.find('tbody')).map($).map($.text)); + expect($rootScope.items).toEqual( + listContent(element.find('tbody')) + .map($) + .map($.text) + ); $(element).remove(); }); }); - } - [0, 1].forEach(function(useExtraElements){ + [0, 1].forEach(function(useExtraElements) { var testDescription = tests.description; if (useExtraElements) { testDescription += ' with extra elements'; } - describe(testDescription, function(){ + describe(testDescription, function() { tests(useExtraElements); }); }); - -}); \ No newline at end of file +}); diff --git a/test/sortable.e2e.directives.spec.js b/test/sortable.e2e.directives.spec.js index 193af85..7e900fb 100644 --- a/test/sortable.e2e.directives.spec.js +++ b/test/sortable.e2e.directives.spec.js @@ -1,46 +1,66 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + 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')); beforeEach(module('ui.sortable.testDirectives')); - var EXTRA_DY_PERCENTAGE, listContent, listFindContent, listInnerContent, simulateElementDrag, beforeLiElement, afterLiElement, beforeDivElement, afterDivElement; - - beforeEach(inject(function (sortableTestHelper) { - EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; - listContent = sortableTestHelper.listContent; - listFindContent = sortableTestHelper.listFindContent; - listInnerContent = sortableTestHelper.listInnerContent; - simulateElementDrag = sortableTestHelper.simulateElementDrag; - beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; - afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; - beforeDivElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeDivElement; - afterDivElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterDivElement; - })); + var EXTRA_DY_PERCENTAGE, + listContent, + listFindContent, + listInnerContent, + simulateElementDrag, + beforeLiElement, + afterLiElement, + beforeDivElement, + afterDivElement; + + beforeEach( + inject(function(sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + listFindContent = sortableTestHelper.listFindContent; + listInnerContent = sortableTestHelper.listInnerContent; + simulateElementDrag = sortableTestHelper.simulateElementDrag; + beforeLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterLiElement; + beforeDivElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeDivElement; + afterDivElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterDivElement; + }) + ); tests.description = 'Inner directives related'; - function tests (useExtraElements) { - + function tests(useExtraElements) { var host; - beforeEach(inject(function() { - host = $('
      '); - $('body').append(host); + beforeEach( + inject(function() { + host = $('
      '); + $('body').append(host); - if (!useExtraElements) { - beforeLiElement = afterLiElement = ''; - beforeDivElement = afterDivElement = ''; - } - })); + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + beforeDivElement = afterDivElement = ''; + } + }) + ); afterEach(function() { host.remove(); @@ -50,17 +70,20 @@ describe('uiSortable', function() { it('should work when inner directives are used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', + element = $compile( + ''.concat( + '
          ', beforeLiElement, '
        • ', - '', + '', '
        • ', afterLiElement, - '
        '))($rootScope); + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { - $rootScope.opts = { }; + $rootScope.opts = {}; $rootScope.items = ['One', 'Two', 'Three']; }); @@ -85,17 +108,20 @@ describe('uiSortable', function() { it('should not $destroy directives after sorting.', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', + element = $compile( + ''.concat( + '
          ', beforeLiElement, '
        • ', - '', + '', '
        • ', afterLiElement, - '
        '))($rootScope); + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { - $rootScope.opts = { }; + $rootScope.opts = {}; $rootScope.items = ['One', 'Two', 'Three']; }); @@ -120,16 +146,19 @@ describe('uiSortable', function() { it('should work when the items are inside a transcluded directive', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
      ', + element = $compile( + ''.concat( + '
      ', '', - beforeLiElement, - '
      ', - '{{ item }}', - '
      ', - afterLiElement, + beforeLiElement, + '
      ', + '{{ item }}', + '
      ', + afterLiElement, '', - '
      '))($rootScope); + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { @@ -159,16 +188,19 @@ describe('uiSortable', function() { it('should properly cancel() when the items are inside a transcluded directive', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
      ', + element = $compile( + ''.concat( + '
      ', '', - beforeLiElement, - '
      ', - '{{ item }}', - '
      ', - afterLiElement, + beforeLiElement, + '
      ', + '{{ item }}', + '
      ', + afterLiElement, '', - '
      '))($rootScope); + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { @@ -214,7 +246,6 @@ describe('uiSortable', function() { expect($rootScope.items).toEqual(['Two', 'Three', 'One']); expect($rootScope.items).toEqual(listFindContent(element)); - $(element).remove(); }); }); @@ -222,22 +253,28 @@ describe('uiSortable', function() { it('should update model when the items are inside a transcluded directive and sorting between sortables', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
      ', + elementTop = $compile( + ''.concat( + '
      ', '', - beforeDivElement, - '
      {{ item }}
      ', - afterDivElement, + beforeDivElement, + '
      {{ item }}
      ', + afterDivElement, '', - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
      ', + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
      ', '', - beforeDivElement, - '
      {{ item }}
      ', - afterDivElement, + beforeDivElement, + '
      {{ item }}
      ', + afterDivElement, '', - '
      '))($rootScope); + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; @@ -247,13 +284,21 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('.sortable-item:eq(0)'); var li2 = elementBottom.find('.sortable-item:eq(2)'); simulateElementDrag(li1, li2, { place: 'above', moves: 100 }); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Top One', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Top One', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listFindContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listFindContent(elementBottom)); @@ -261,8 +306,16 @@ describe('uiSortable', function() { li1 = elementBottom.find('.sortable-item:eq(2)'); li2 = elementTop.find('.sortable-item:eq(1)'); simulateElementDrag(li1, li2, { place: 'below', moves: 100 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three', 'Top One']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top Three', + 'Top One' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listFindContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listFindContent(elementBottom)); @@ -274,22 +327,28 @@ describe('uiSortable', function() { it('should properly cancel() when the items are inside a transcluded directive and sorting between sortables', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
      ', + elementTop = $compile( + ''.concat( + '
      ', '', - beforeDivElement, - '
      {{ item }}
      ', - afterDivElement, + beforeDivElement, + '
      {{ item }}
      ', + afterDivElement, '', - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
      ', + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
      ', '', - beforeDivElement, - '
      {{ item }}
      ', - afterDivElement, + beforeDivElement, + '
      {{ item }}
      ', + afterDivElement, '', - '
      '))($rootScope); + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; @@ -297,38 +356,67 @@ describe('uiSortable', function() { connectWith: '.cross-sortable', items: '> * .sortable-item', update: function(e, ui) { - if (ui.item.sortable.model && - (typeof ui.item.sortable.model === 'string') && - ui.item.sortable.model.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(); } } }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('.sortable-item:eq(1)'); var li2 = elementBottom.find('.sortable-item:eq(0)'); simulateElementDrag(li1, li2, { place: 'below', moves: 100 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listFindContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listFindContent(elementBottom)); // try again li1 = elementBottom.find('.sortable-item:eq(1)'); li2 = elementTop.find('.sortable-item:eq(1)'); simulateElementDrag(li1, li2, { place: 'above', moves: 100 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listFindContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listFindContent(elementBottom)); // try again li1 = elementBottom.find('.sortable-item:eq(1)'); li2 = elementTop.find('.sortable-item:eq(1)'); simulateElementDrag(li1, li2, { place: 'above', moves: 100 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listFindContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listFindContent(elementBottom)); @@ -336,7 +424,12 @@ describe('uiSortable', function() { li2 = elementBottom.find('.sortable-item:eq(2)'); simulateElementDrag(li1, li2, { place: 'above', moves: 100 }); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Top One', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Top One', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listFindContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listFindContent(elementBottom)); @@ -344,8 +437,16 @@ describe('uiSortable', function() { li1 = elementBottom.find('.sortable-item:eq(2)'); li2 = elementTop.find('.sortable-item:eq(1)'); simulateElementDrag(li1, li2, { place: 'below', moves: 100 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three', 'Top One']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top Three', + 'Top One' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listFindContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listFindContent(elementBottom)); @@ -353,19 +454,17 @@ describe('uiSortable', function() { $(elementBottom).remove(); }); }); - } - [0, 1].forEach(function(useExtraElements){ + [0, 1].forEach(function(useExtraElements) { var testDescription = tests.description; if (useExtraElements) { testDescription += ' with extra elements'; } - describe(testDescription, function(){ + describe(testDescription, function() { tests(useExtraElements); }); }); - -}); \ No newline at end of file +}); diff --git a/test/sortable.e2e.events.spec.js b/test/sortable.e2e.events.spec.js index 05c2647..3aad70e 100644 --- a/test/sortable.e2e.events.spec.js +++ b/test/sortable.e2e.events.spec.js @@ -1,41 +1,54 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + 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, simulateElementDrag, hasUndefinedProperties, beforeLiElement, afterLiElement; - - beforeEach(inject(function (sortableTestHelper) { - EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; - listContent = sortableTestHelper.listContent; - simulateElementDrag = sortableTestHelper.simulateElementDrag; - hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; - beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; - afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; - })); + var EXTRA_DY_PERCENTAGE, + listContent, + simulateElementDrag, + hasUndefinedProperties, + beforeLiElement, + afterLiElement; + + beforeEach( + inject(function(sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + simulateElementDrag = sortableTestHelper.simulateElementDrag; + hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; + beforeLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterLiElement; + }) + ); tests.description = 'Events related'; - function tests (useExtraElements) { - + function tests(useExtraElements) { var host; - beforeEach(inject(function() { - host = $('
      '); - $('body').append(host); + beforeEach( + inject(function() { + host = $('
      '); + $('body').append(host); - if (!useExtraElements) { - beforeLiElement = afterLiElement = ''; - } - })); + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + } + }) + ); afterEach(function() { host.remove(); @@ -45,18 +58,21 @@ describe('uiSortable', function() { it('should emit an event after sorting', function() { inject(function($compile, $rootScope) { var element, uiParam, emittedUiParam; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.items = ['One', 'Two', 'Three']; - $rootScope.update = function (e, ui) { + $rootScope.update = function(e, ui) { uiParam = ui; }; - $rootScope.onSorting = function (e, ui) { + $rootScope.onSorting = function(e, ui) { emittedUiParam = ui; }; spyOn($rootScope, 'onSorting').and.callThrough(); @@ -81,48 +97,69 @@ describe('uiSortable', function() { it('should emit an event after sorting between sortables of different scopes', function() { inject(function($compile, $rootScope) { - var elementTop, elementBottom, - wrapperTop, wrapperBottom, - wrapperTopScope, wrapperBottomScope, - itemsTop, itemsBottom; + var elementTop, + elementBottom, + wrapperTop, + wrapperBottom, + wrapperTopScope, + wrapperBottomScope, + itemsTop, + itemsBottom; wrapperTopScope = $rootScope.$new(); wrapperBottomScope = $rootScope.$new(); - wrapperTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))(wrapperTopScope); - wrapperBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))(wrapperBottomScope); - - host.append(wrapperTop).append(wrapperBottom).append('
      '); + wrapperTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )(wrapperTopScope); + wrapperBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )(wrapperBottomScope); + + host + .append(wrapperTop) + .append(wrapperBottom) + .append('
      '); $rootScope.$apply(function() { - wrapperTopScope.itemsTop = itemsTop = ['Top One', 'Top Two', 'Top Three']; + wrapperTopScope.itemsTop = itemsTop = [ + 'Top One', + 'Top Two', + 'Top Three' + ]; wrapperTopScope.opts = { connectWith: '.cross-sortable', - stop: function (e, ui) { + stop: function(e, ui) { wrapperTopScope.uiParam = ui; } }; - wrapperTopScope.onSorting = function (e, ui) { + wrapperTopScope.onSorting = function(e, ui) { wrapperTopScope.emittedUiParam = ui; }; spyOn(wrapperTopScope, 'onSorting').and.callThrough(); $rootScope.$on('ui-sortable:moved', wrapperTopScope.onSorting); - wrapperBottomScope.itemsBottom = itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; + wrapperBottomScope.itemsBottom = itemsBottom = [ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]; wrapperBottomScope.opts = { connectWith: '.cross-sortable', - update: function (e, ui) { + update: function(e, ui) { wrapperBottomScope.uiParam = ui; } }; - wrapperBottomScope.onSorting = function (e, ui) { + wrapperBottomScope.onSorting = function(e, ui) { wrapperBottomScope.emittedUiParam = ui; }; spyOn(wrapperBottomScope, 'onSorting').and.callThrough(); @@ -136,15 +173,24 @@ describe('uiSortable', function() { var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect(itemsTop).toEqual(['Top Two', 'Top Three']); - expect(itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect(itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect(itemsTop).toEqual(listContent(elementTop)); expect(itemsBottom).toEqual(listContent(elementBottom)); expect(wrapperTopScope.onSorting).toHaveBeenCalled(); - expect(wrapperTopScope.uiParam.item).toEqual(wrapperTopScope.emittedUiParam.item); + expect(wrapperTopScope.uiParam.item).toEqual( + wrapperTopScope.emittedUiParam.item + ); expect(wrapperBottomScope.onSorting).toHaveBeenCalled(); - expect(wrapperBottomScope.uiParam.item).toEqual(wrapperBottomScope.emittedUiParam.item); + expect(wrapperBottomScope.uiParam.item).toEqual( + wrapperBottomScope.emittedUiParam.item + ); $(wrapperBottom).remove(); $(wrapperTop).remove(); @@ -152,16 +198,15 @@ describe('uiSortable', function() { }); } - [0, 1].forEach(function(useExtraElements){ + [0, 1].forEach(function(useExtraElements) { var testDescription = tests.description; if (useExtraElements) { testDescription += ' with extra elements'; } - describe(testDescription, function(){ + describe(testDescription, function() { tests(useExtraElements); }); }); - -}); \ No newline at end of file +}); diff --git a/test/sortable.e2e.multi.spec.js b/test/sortable.e2e.multi.spec.js index 26a0f2d..3d755ba 100644 --- a/test/sortable.e2e.multi.spec.js +++ b/test/sortable.e2e.multi.spec.js @@ -1,42 +1,56 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + 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, simulateElementDrag, hasUndefinedProperties, beforeLiElement, afterLiElement; - - beforeEach(inject(function (sortableTestHelper) { - EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; - listContent = sortableTestHelper.listContent; - listInnerContent = sortableTestHelper.listInnerContent; - simulateElementDrag = sortableTestHelper.simulateElementDrag; - hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; - beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; - afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; - })); - tests.description = 'Multiple sortables related'; - function tests (useExtraElements) { + var EXTRA_DY_PERCENTAGE, + listContent, + listInnerContent, + simulateElementDrag, + hasUndefinedProperties, + beforeLiElement, + afterLiElement; + + beforeEach( + inject(function(sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + listInnerContent = sortableTestHelper.listInnerContent; + simulateElementDrag = sortableTestHelper.simulateElementDrag; + hasUndefinedProperties = sortableTestHelper.hasUndefinedProperties; + beforeLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterLiElement; + }) + ); + tests.description = 'Multiple sortables related'; + function tests(useExtraElements) { var host; - beforeEach(inject(function() { - host = $('
      '); - $('body').append(host); + beforeEach( + inject(function() { + host = $('
      '); + $('body').append(host); - if (!useExtraElements) { - beforeLiElement = afterLiElement = ''; - } - })); + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + } + }) + ); afterEach(function() { host.remove(); @@ -46,39 +60,65 @@ describe('uiSortable', function() { it('should update model when sorting between sortables', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable' }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -89,29 +129,50 @@ describe('uiSortable', function() { it('should update model when sorting between sortables of different scopes', function() { inject(function($compile, $rootScope) { - var elementTop, elementBottom, - wrapperTop, wrapperBottom, - wrapperTopScope, wrapperBottomScope, - itemsTop, itemsBottom; + var elementTop, + elementBottom, + wrapperTop, + wrapperBottom, + wrapperTopScope, + wrapperBottomScope, + itemsTop, + itemsBottom; wrapperTopScope = $rootScope.$new(); wrapperBottomScope = $rootScope.$new(); - wrapperTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))(wrapperTopScope); - wrapperBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))(wrapperBottomScope); - - host.append(wrapperTop).append(wrapperBottom).append('
      '); + wrapperTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )(wrapperTopScope); + wrapperBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )(wrapperBottomScope); + + host + .append(wrapperTop) + .append(wrapperBottom) + .append('
      '); $rootScope.$apply(function() { - wrapperTopScope.itemsTop = itemsTop = ['Top One', 'Top Two', 'Top Three']; - wrapperBottomScope.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' }; }); @@ -122,15 +183,28 @@ describe('uiSortable', function() { var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect(itemsTop).toEqual(['Top Two', 'Top Three']); - expect(itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect(itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect(itemsTop).toEqual(listContent(elementTop)); expect(itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); expect(itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect(itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect(itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect(itemsTop).toEqual(listContent(elementTop)); expect(itemsBottom).toEqual(listContent(elementBottom)); @@ -142,27 +216,36 @@ describe('uiSortable', function() { it('should update model when sorting a "falsy" item between sortables', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = [0, 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable' }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); - function parseFalsyValue (value) { + function parseFalsyValue(value) { if (value === '0') { return 0; } @@ -173,17 +256,38 @@ describe('uiSortable', function() { var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 0, 'Bottom Two', 'Bottom Three']); - expect($rootScope.itemsTop).toEqual(listContent(elementTop).map(parseFalsyValue)); - expect($rootScope.itemsBottom).toEqual(listContent(elementBottom).map(parseFalsyValue)); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 0, + 'Bottom Two', + 'Bottom Three' + ]); + expect($rootScope.itemsTop).toEqual( + listContent(elementTop).map(parseFalsyValue) + ); + expect($rootScope.itemsBottom).toEqual( + listContent(elementBottom).map(parseFalsyValue) + ); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); expect($rootScope.itemsTop).toEqual(['Top Two', 0, 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); - expect($rootScope.itemsTop).toEqual(listContent(elementTop).map(parseFalsyValue)); - expect($rootScope.itemsBottom).toEqual(listContent(elementBottom).map(parseFalsyValue)); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); + expect($rootScope.itemsTop).toEqual( + listContent(elementTop).map(parseFalsyValue) + ); + expect($rootScope.itemsBottom).toEqual( + listContent(elementBottom).map(parseFalsyValue) + ); $(elementTop).remove(); $(elementBottom).remove(); @@ -193,18 +297,24 @@ describe('uiSortable', function() { it('should work when "placeholder" option is used', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; @@ -214,21 +324,41 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -240,18 +370,24 @@ describe('uiSortable', function() { it('should work when "placeholder" option equals the class of items', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; @@ -261,21 +397,41 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -287,18 +443,24 @@ describe('uiSortable', function() { it('should work when "helper: clone" option is used', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; @@ -308,21 +470,41 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -334,18 +516,24 @@ describe('uiSortable', function() { it('should work when "placeholder" and "helper: clone" options are used', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; @@ -356,21 +544,41 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -382,44 +590,70 @@ describe('uiSortable', function() { it('should work when "helper: function" option is used', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item.clone().text('helper'); }, connectWith: '.cross-sortable' }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -431,23 +665,29 @@ describe('uiSortable', function() { it('should work when "placeholder" and "helper: function" options are used', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item.clone().text('helper'); }, placeholder: 'sortable-item-placeholder', @@ -455,21 +695,41 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -481,23 +741,29 @@ describe('uiSortable', function() { it('should work when "placeholder" and "helper: function" options are used and a drag is reverted', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item.clone().text('helper'); }, placeholder: 'sortable-item-placeholder', @@ -505,13 +771,27 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(2)'); var li2 = elementBottom.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'below', action: 'dragAndRevert' }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'below', + action: 'dragAndRevert' + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -519,23 +799,49 @@ describe('uiSortable', function() { li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementTop.find('[ng-repeat]:eq(2)'); li2 = elementBottom.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'below', extradx: -20, extrady: -11 }); + simulateElementDrag(li1, li2, { + place: 'below', + extradx: -20, + extrady: -11 + }); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Top Three', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Top Three', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -547,44 +853,70 @@ describe('uiSortable', function() { it('should work when "helper: function" that returns a list element is used', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item; }, connectWith: '.cross-sortable' }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -596,23 +928,29 @@ describe('uiSortable', function() { it('should work when "placeholder" and "helper: function" that returns a list element are used', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item; }, placeholder: 'sortable-item-placeholder', @@ -620,21 +958,41 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(0)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -646,48 +1004,79 @@ describe('uiSortable', function() { it('should cancel sorting of nodes that contain "Two"', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable', update: function(e, ui) { - if (ui.item.sortable.model && - (typeof ui.item.sortable.model === 'string') && - ui.item.sortable.model.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(); } } }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(1)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -695,15 +1084,32 @@ describe('uiSortable', function() { li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); @@ -714,28 +1120,39 @@ describe('uiSortable', function() { it('should properly set ui.item.sortable properties', function() { inject(function($compile, $rootScope) { - var elementTop, elementBottom, updateCallbackExpectations, stopCallbackExpectations; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + var elementTop, + elementBottom, + updateCallbackExpectations, + stopCallbackExpectations; + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable', update: function(e, ui) { - if (ui.item.sortable.model && - (typeof ui.item.sortable.model === 'string') && - ui.item.sortable.model.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); @@ -746,7 +1163,10 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(1)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); @@ -768,9 +1188,21 @@ describe('uiSortable', function() { expect(uiItemSortable.received).toBe(true); expect(uiItemSortable.moved).toBe(undefined); }; - simulateElementDrag(li1, li2, { place: 'below', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'below', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = stopCallbackExpectations = undefined; @@ -795,9 +1227,21 @@ describe('uiSortable', function() { expect(uiItemSortable.received).toBe(true); expect(uiItemSortable.moved).toBe(undefined); }; - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = stopCallbackExpectations = undefined; @@ -824,7 +1268,12 @@ describe('uiSortable', function() { }; simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = stopCallbackExpectations = undefined; @@ -849,9 +1298,21 @@ describe('uiSortable', function() { expect(uiItemSortable.received).toBe(true); expect(uiItemSortable.moved).toBe('Top One'); }; - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = stopCallbackExpectations = undefined; @@ -864,27 +1325,35 @@ describe('uiSortable', function() { it('should properly set ui.item.sortable.droptargetModel when using data-ng-model', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom, updateCallbackExpectations; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable', update: function(e, ui) { - if (ui.item.sortable.model && - (typeof ui.item.sortable.model === 'string') && - ui.item.sortable.model.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); @@ -892,16 +1361,31 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(1)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe($rootScope.itemsBottom); }; - simulateElementDrag(li1, li2, { place: 'below', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'below', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -911,9 +1395,21 @@ describe('uiSortable', function() { updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe($rootScope.itemsTop); }; - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -925,7 +1421,12 @@ describe('uiSortable', function() { }; simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -935,9 +1436,21 @@ describe('uiSortable', function() { updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe($rootScope.itemsTop); }; - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -950,27 +1463,35 @@ describe('uiSortable', function() { it('should properly set ui.item.sortable.droptargetModel when using data-ui-sortable', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom, updateCallbackExpectations; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable', update: function(e, ui) { - if (ui.item.sortable.model && - (typeof ui.item.sortable.model === 'string') && - ui.item.sortable.model.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); @@ -978,16 +1499,31 @@ describe('uiSortable', function() { }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(1)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe($rootScope.itemsBottom); }; - simulateElementDrag(li1, li2, { place: 'below', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'below', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -997,9 +1533,21 @@ describe('uiSortable', function() { updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe($rootScope.itemsTop); }; - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -1011,7 +1559,12 @@ describe('uiSortable', function() { }; simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -1021,9 +1574,21 @@ describe('uiSortable', function() { updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe($rootScope.itemsTop); }; - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -1035,36 +1600,59 @@ describe('uiSortable', function() { it('should properly set ui.item.sortable.droptargetModel when sorting between different scopes', function() { inject(function($compile, $rootScope) { - var elementTop, elementBottom, - wrapperTop, wrapperBottom, - wrapperTopScope, wrapperBottomScope, - itemsTop, itemsBottom, - updateCallbackExpectations; + var elementTop, + elementBottom, + wrapperTop, + wrapperBottom, + wrapperTopScope, + wrapperBottomScope, + itemsTop, + itemsBottom, + updateCallbackExpectations; wrapperTopScope = $rootScope.$new(); wrapperBottomScope = $rootScope.$new(); - wrapperTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))(wrapperTopScope); - wrapperBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))(wrapperBottomScope); - - host.append(wrapperTop).append(wrapperBottom).append('
      '); + wrapperTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )(wrapperTopScope); + wrapperBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )(wrapperBottomScope); + + host + .append(wrapperTop) + .append(wrapperBottom) + .append('
      '); $rootScope.$apply(function() { - wrapperTopScope.itemsTop = itemsTop = ['Top One', 'Top Two', 'Top Three']; - wrapperBottomScope.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.sortable.model && - (typeof ui.item.sortable.model === 'string') && - ui.item.sortable.model.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); @@ -1080,9 +1668,17 @@ describe('uiSortable', function() { updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe(itemsBottom); }; - simulateElementDrag(li1, li2, { place: 'below', extradx: -20, extrady: -11 }); + simulateElementDrag(li1, li2, { + place: 'below', + extradx: -20, + extrady: -11 + }); expect(itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect(itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect(itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect(itemsTop).toEqual(listContent(elementTop)); expect(itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -1092,9 +1688,17 @@ describe('uiSortable', function() { updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe(itemsTop); }; - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); expect(itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect(itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect(itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect(itemsTop).toEqual(listContent(elementTop)); expect(itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -1106,7 +1710,12 @@ describe('uiSortable', function() { }; simulateElementDrag(li1, li2, 'below'); expect(itemsTop).toEqual(['Top Two', 'Top Three']); - expect(itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect(itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect(itemsTop).toEqual(listContent(elementTop)); expect(itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -1116,9 +1725,17 @@ describe('uiSortable', function() { updateCallbackExpectations = function(uiItemSortable) { expect(uiItemSortable.droptargetModel).toBe(itemsTop); }; - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); expect(itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect(itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect(itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect(itemsTop).toEqual(listContent(elementTop)); expect(itemsBottom).toEqual(listContent(elementBottom)); updateCallbackExpectations = undefined; @@ -1131,46 +1748,65 @@ describe('uiSortable', function() { it('should properly free ui.item.sortable object', function() { inject(function($compile, $rootScope) { var elementTop, elementBottom, uiItem, uiItemSortable_Destroy; - elementTop = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); - elementBottom = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + elementTop = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); + elementBottom = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.itemsTop = ['Top One', 'Top Two', 'Top Three']; $rootScope.itemsBottom = ['Bottom One', 'Bottom Two', 'Bottom Three']; $rootScope.opts = { connectWith: '.cross-sortable', - start: function (e, ui) { + start: function(e, ui) { uiItem = ui.item; spyOn(ui.item.sortable, '_destroy').and.callThrough(); uiItemSortable_Destroy = ui.item.sortable._destroy; }, update: function(e, ui) { uiItem.sortable = ui.item.sortable; - if (ui.item.sortable.model && - (typeof ui.item.sortable.model === 'string') && - ui.item.sortable.model.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(); } } }; }); - host.append(elementTop).append(elementBottom).append('
      '); + host + .append(elementTop) + .append(elementBottom) + .append('
      '); var li1 = elementTop.find('[ng-repeat]:eq(1)'); var li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); expect(uiItemSortable_Destroy).toHaveBeenCalled(); @@ -1179,9 +1815,21 @@ describe('uiSortable', function() { li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top One', 'Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top One', + 'Top Two', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); expect(uiItemSortable_Destroy).toHaveBeenCalled(); @@ -1192,7 +1840,12 @@ describe('uiSortable', function() { li2 = elementBottom.find('[ng-repeat]:eq(0)'); simulateElementDrag(li1, li2, 'below'); expect($rootScope.itemsTop).toEqual(['Top Two', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Top One', 'Bottom Two', 'Bottom Three']); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Top One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); expect(uiItemSortable_Destroy).toHaveBeenCalled(); @@ -1201,9 +1854,21 @@ describe('uiSortable', function() { li1 = elementBottom.find('[ng-repeat]:eq(1)'); li2 = elementTop.find('[ng-repeat]:eq(1)'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -20, extrady: -11 }); - expect($rootScope.itemsTop).toEqual(['Top Two', 'Top One', 'Top Three']); - expect($rootScope.itemsBottom).toEqual(['Bottom One', 'Bottom Two', 'Bottom Three']); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -20, + extrady: -11 + }); + expect($rootScope.itemsTop).toEqual([ + 'Top Two', + 'Top One', + 'Top Three' + ]); + expect($rootScope.itemsBottom).toEqual([ + 'Bottom One', + 'Bottom Two', + 'Bottom Three' + ]); expect($rootScope.itemsTop).toEqual(listContent(elementTop)); expect($rootScope.itemsBottom).toEqual(listContent(elementBottom)); expect(uiItemSortable_Destroy).toHaveBeenCalled(); @@ -1214,19 +1879,17 @@ describe('uiSortable', function() { $(elementBottom).remove(); }); }); - } - [0, 1].forEach(function(useExtraElements){ + [0, 1].forEach(function(useExtraElements) { var testDescription = tests.description; if (useExtraElements) { testDescription += ' with extra elements'; } - describe(testDescription, function(){ + describe(testDescription, function() { tests(useExtraElements); }); }); - -}); \ No newline at end of file +}); diff --git a/test/sortable.e2e.nested.spec.js b/test/sortable.e2e.nested.spec.js index 9fb3f1b..6759ff3 100644 --- a/test/sortable.e2e.nested.spec.js +++ b/test/sortable.e2e.nested.spec.js @@ -1,33 +1,37 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + 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, listInnerContent, simulateElementDrag; - beforeEach(inject(function (sortableTestHelper) { - EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; - listInnerContent = sortableTestHelper.listInnerContent; - simulateElementDrag = sortableTestHelper.simulateElementDrag; - })); + beforeEach( + inject(function(sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listInnerContent = sortableTestHelper.listInnerContent; + simulateElementDrag = sortableTestHelper.simulateElementDrag; + }) + ); describe('Nested sortables related', function() { - var host; - beforeEach(inject(function() { - host = $('
      '); - $('body').append(host); - })); + beforeEach( + inject(function() { + host = $('
      '); + $('body').append(host); + }) + ); afterEach(function() { host.remove(); @@ -38,20 +42,23 @@ describe('uiSortable', function() { inject(function($compile, $rootScope) { var elementTree, li1, li2; - elementTree = $compile(''.concat( - '
        ', + elementTree = $compile( + ''.concat( + '
          ', '
        • ', - '
          ', - '{{item.text}}', - '
            ', - '
          • ', - '{{i.text}}', - '
          • ', - '
          ', - '
          ', + '
          ', + '{{item.text}}', + '
            ', + '
          • ', + '{{i.text}}', '
          • ', - '
          ', - '
          '))($rootScope); + '
        ', + '', + '', + '
      ', + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.items = [ @@ -67,7 +74,7 @@ describe('uiSortable', function() { ] } ]; - + $rootScope.sortableOptions = { connectWith: '.nested-sortable' }; @@ -79,50 +86,131 @@ describe('uiSortable', function() { // the item should return back to its original position li1 = elementTree.find('.innerList:last').find('li:last'); li1.simulate('drag', { dx: -200, moves: 30 }); - expect($rootScope.items.map(function(x){ return x.text; })) - .toEqual(['Item 1', 'Item 2']); - expect($rootScope.items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); - expect($rootScope.items[0].items.map(function(x){ return x.text; })) - .toEqual([]); - expect($rootScope.items[0].items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree.find('.innerList:eq(0)'), '.lvl2ItemContent')); - expect($rootScope.items[1].items.map(function(x){ return x.text; })) - .toEqual(['Item 2.1', 'Item 2.2']); - expect($rootScope.items[1].items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree.find('.innerList:eq(1)'), '.lvl2ItemContent')); + expect( + $rootScope.items.map(function(x) { + return x.text; + }) + ).toEqual(['Item 1', 'Item 2']); + expect( + $rootScope.items.map(function(x) { + return x.text; + }) + ).toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); + expect( + $rootScope.items[0].items.map(function(x) { + return x.text; + }) + ).toEqual([]); + expect( + $rootScope.items[0].items.map(function(x) { + return x.text; + }) + ).toEqual( + listInnerContent( + elementTree.find('.innerList:eq(0)'), + '.lvl2ItemContent' + ) + ); + expect( + $rootScope.items[1].items.map(function(x) { + return x.text; + }) + ).toEqual(['Item 2.1', 'Item 2.2']); + expect( + $rootScope.items[1].items.map(function(x) { + return x.text; + }) + ).toEqual( + listInnerContent( + elementTree.find('.innerList:eq(1)'), + '.lvl2ItemContent' + ) + ); // this should drag the item from the outter list and // drop it to the inner list li1 = elementTree.find('> li:first'); li2 = elementTree.find('.innerList:last').find('li:last'); - simulateElementDrag(li1, li2, { place: 'above', extradx: 10, extrady: -5 }); - expect($rootScope.items.map(function(x){ return x.text; })) - .toEqual(['Item 2']); - expect($rootScope.items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); - expect($rootScope.items[0].items.map(function(x){ return x.text; })) - .toEqual(['Item 2.1', 'Item 1', 'Item 2.2']); - expect($rootScope.items[0].items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree.find('.innerList:eq(0)'), '.lvl2ItemContent')); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: 10, + extrady: -5 + }); + expect( + $rootScope.items.map(function(x) { + return x.text; + }) + ).toEqual(['Item 2']); + expect( + $rootScope.items.map(function(x) { + return x.text; + }) + ).toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); + expect( + $rootScope.items[0].items.map(function(x) { + return x.text; + }) + ).toEqual(['Item 2.1', 'Item 1', 'Item 2.2']); + expect( + $rootScope.items[0].items.map(function(x) { + return x.text; + }) + ).toEqual( + listInnerContent( + elementTree.find('.innerList:eq(0)'), + '.lvl2ItemContent' + ) + ); // this should drag the item from the inner list and // drop it to the outter list li1 = elementTree.find('.innerList:last').find('li:last'); li2 = elementTree.find('> li:first'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -10, extrady: -6 }); - expect($rootScope.items.map(function(x){ return x.text; })) - .toEqual(['Item 2.2', 'Item 2']); - expect($rootScope.items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); - expect($rootScope.items[0].items.map(function(x){ return x.text; })) - .toEqual([]); - expect($rootScope.items[0].items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree.find('.innerList:eq(0)'), '.lvl2ItemContent')); - expect($rootScope.items[1].items.map(function(x){ return x.text; })) - .toEqual(['Item 2.1', 'Item 1']); - expect($rootScope.items[1].items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree.find('.innerList:eq(1)'), '.lvl2ItemContent')); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -10, + extrady: -6 + }); + expect( + $rootScope.items.map(function(x) { + return x.text; + }) + ).toEqual(['Item 2.2', 'Item 2']); + expect( + $rootScope.items.map(function(x) { + return x.text; + }) + ).toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); + expect( + $rootScope.items[0].items.map(function(x) { + return x.text; + }) + ).toEqual([]); + expect( + $rootScope.items[0].items.map(function(x) { + return x.text; + }) + ).toEqual( + listInnerContent( + elementTree.find('.innerList:eq(0)'), + '.lvl2ItemContent' + ) + ); + expect( + $rootScope.items[1].items.map(function(x) { + return x.text; + }) + ).toEqual(['Item 2.1', 'Item 1']); + expect( + $rootScope.items[1].items.map(function(x) { + return x.text; + }) + ).toEqual( + listInnerContent( + elementTree.find('.innerList:eq(1)'), + '.lvl2ItemContent' + ) + ); $(elementTree).remove(); }); @@ -132,16 +220,19 @@ describe('uiSortable', function() { inject(function($compile, $rootScope) { var elementTree, li1, li2; - elementTree = $compile(''.concat( - '
      ', + elementTree = $compile( + ''.concat( + '
      ', '
      ', - '
      {{item.text}}
      ', - '
      ', - '
      {{i.text}}
      ', - '
      ', + '
      {{item.text}}
      ', + '
      ', + '
      {{i.text}}
      ', + '
      ', '
      ', - '
      ', - '
      '))($rootScope); + '
      ', + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.items = [ @@ -160,7 +251,7 @@ describe('uiSortable', function() { ] } ]; - + $rootScope.sortableOptions = {}; $rootScope.innerSortableOptions = { connectWith: '.nested-sortable' @@ -171,16 +262,24 @@ describe('uiSortable', function() { li1 = elementTree.find('.innerList:last'); li2 = elementTree.find('.innerList:first'); - simulateElementDrag(li1, li2, { place: 'above', extradx: -10, extrady: -6 }); - expect($rootScope.items.map(function(x){ return x.text; })) - .toEqual(['Item 2', 'Item 1']); - expect($rootScope.items.map(function(x){ return x.text; })) - .toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); + simulateElementDrag(li1, li2, { + place: 'above', + extradx: -10, + extrady: -6 + }); + expect( + $rootScope.items.map(function(x) { + return x.text; + }) + ).toEqual(['Item 2', 'Item 1']); + expect( + $rootScope.items.map(function(x) { + return x.text; + }) + ).toEqual(listInnerContent(elementTree, '.lvl1ItemContent')); $(elementTree).remove(); }); }); - }); - -}); \ No newline at end of file +}); diff --git a/test/sortable.e2e.spec.js b/test/sortable.e2e.spec.js index bbd1f84..ff2168f 100644 --- a/test/sortable.e2e.spec.js +++ b/test/sortable.e2e.spec.js @@ -1,40 +1,52 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + 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, beforeLiElement, afterLiElement; - - beforeEach(inject(function (sortableTestHelper) { - EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; - listContent = sortableTestHelper.listContent; - listInnerContent = sortableTestHelper.listInnerContent; - beforeLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.beforeLiElement; - afterLiElement = sortableTestHelper.extraElements && sortableTestHelper.extraElements.afterLiElement; - })); + var EXTRA_DY_PERCENTAGE, + listContent, + listInnerContent, + beforeLiElement, + afterLiElement; + + beforeEach( + inject(function(sortableTestHelper) { + EXTRA_DY_PERCENTAGE = sortableTestHelper.EXTRA_DY_PERCENTAGE; + listContent = sortableTestHelper.listContent; + listInnerContent = sortableTestHelper.listInnerContent; + beforeLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.beforeLiElement; + afterLiElement = + sortableTestHelper.extraElements && + sortableTestHelper.extraElements.afterLiElement; + }) + ); tests.description = 'Drag & Drop simulation'; - function tests (useExtraElements) { - + function tests(useExtraElements) { var host; - beforeEach(inject(function() { - host = $('
      '); - $('body').append(host); - - if (!useExtraElements) { - beforeLiElement = afterLiElement = ''; - } - })); + beforeEach( + inject(function() { + host = $('
      '); + $('body').append(host); + + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + } + }) + ); afterEach(function() { host.remove(); @@ -44,12 +56,15 @@ describe('uiSortable', function() { it('should update model when order changes', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.items = ['One', 'Two', 'Three']; }); @@ -75,15 +90,18 @@ describe('uiSortable', function() { it('should not allow sorting of "locked" nodes', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item.text }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item.text }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - items:'> .sortable' + items: '> .sortable' }; $rootScope.items = [ { text: 'One', sortable: true }, @@ -98,26 +116,58 @@ describe('uiSortable', function() { var li = element.find('[ng-repeat]:eq(2)'); 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)); + 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('[ng-repeat]:eq(1)'); 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)); + 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('[ng-repeat]:eq(2)'); 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)); + 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('[ng-repeat]: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', 'Two', 'One', 'Three']); - expect($rootScope.items.map(function(x){ return x.text; })).toEqual(listContent(element)); + 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 !?!? @@ -128,12 +178,15 @@ describe('uiSortable', function() { it('should work when "placeholder" option is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { placeholder: 'sortable-item-placeholder' @@ -162,12 +215,15 @@ describe('uiSortable', function() { it('should work when "placeholder" option equals the class of items', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { placeholder: 'sortable-item' @@ -196,12 +252,15 @@ 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(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { placeholder: 'sortable-item' @@ -230,12 +289,15 @@ describe('uiSortable', function() { it('should continue to work after a drag is reverted', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { placeholder: 'sortable-item' @@ -276,12 +338,15 @@ describe('uiSortable', function() { it('should work when "handle" option is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • H {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • H {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { handle: '.handle' @@ -310,19 +375,22 @@ describe('uiSortable', function() { it('should properly remove elements after a sorting', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • H {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • H {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { handle: '.handle' }; $rootScope.items = ['One', 'Two', 'Three']; - $rootScope.remove = function (item, itemIndex) { + $rootScope.remove = function(item, itemIndex) { $rootScope.items.splice(itemIndex, 1); }; }); @@ -358,19 +426,22 @@ describe('uiSortable', function() { it('should properly remove elements after a drag is reverted', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • H {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • H {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { handle: '.handle' }; $rootScope.items = ['One', 'Two', 'Three']; - $rootScope.remove = function (item, itemIndex) { + $rootScope.remove = function(item, itemIndex) { $rootScope.items.splice(itemIndex, 1); }; }); @@ -401,12 +472,15 @@ describe('uiSortable', function() { it('should work when "helper: clone" option is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { helper: 'clone' @@ -435,12 +509,15 @@ describe('uiSortable', function() { it('should work when "helper: clone" option is used and a drag is reverted', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { helper: 'clone' @@ -481,12 +558,15 @@ describe('uiSortable', function() { it('should work when "helper: clone" and "appendTo [selector]" options are used together', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { helper: 'clone', @@ -516,12 +596,15 @@ describe('uiSortable', function() { it('should work when "helper: clone" and "appendTo [element]" options are used together', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { helper: 'clone', @@ -551,12 +634,15 @@ describe('uiSortable', function() { it('should work when "helper: clone" and "appendTo [jQuery object]" options are used together', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { helper: 'clone', @@ -586,12 +672,15 @@ describe('uiSortable', function() { it('should work when "helper: clone" and "placeholder" options are used together.', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { helper: 'clone', @@ -639,15 +728,18 @@ describe('uiSortable', function() { it('should work when "helper: function" option is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item.clone().text('helper'); } }; @@ -675,15 +767,18 @@ describe('uiSortable', function() { it('should work when "helper: function" option is used and a drag is reverted', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item.clone().text('helper'); } }; @@ -723,15 +818,18 @@ describe('uiSortable', function() { it('should work when "helper: function" and "placeholder" options are used together.', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item.clone().text('helper'); }, placeholder: 'sortable-item' @@ -778,15 +876,18 @@ describe('uiSortable', function() { it('should work when "helper: function" that returns a list element is used', function() { inject(function($compile, $rootScope) { var element; - element = $compile(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item; } }; @@ -826,15 +927,18 @@ describe('uiSortable', function() { 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(''.concat( - '
        ', - beforeLiElement, - '
      • {{ item }}
      • ', - afterLiElement, - '
      '))($rootScope); + element = $compile( + ''.concat( + '
        ', + beforeLiElement, + '
      • {{ item }}
      • ', + afterLiElement, + '
      ' + ) + )($rootScope); $rootScope.$apply(function() { $rootScope.opts = { - helper: function (e, item) { + helper: function(e, item) { return item; }, placeholder: 'sortable-item' @@ -877,19 +981,17 @@ describe('uiSortable', function() { $(element).remove(); }); }); - } - [0, 1].forEach(function(useExtraElements){ + [0, 1].forEach(function(useExtraElements) { var testDescription = tests.description; if (useExtraElements) { testDescription += ' with extra elements'; } - describe(testDescription, function(){ + describe(testDescription, function() { tests(useExtraElements); }); }); - }); diff --git a/test/sortable.spec.js b/test/sortable.spec.js index 62960fb..a4bbb9d 100644 --- a/test/sortable.spec.js +++ b/test/sortable.spec.js @@ -1,12 +1,13 @@ 'use strict'; describe('uiSortable', function() { - - beforeEach(module(function($compileProvider) { - if (typeof $compileProvider.debugInfoEnabled === 'function') { - $compileProvider.debugInfoEnabled(false); - } - })); + beforeEach( + module(function($compileProvider) { + if (typeof $compileProvider.debugInfoEnabled === 'function') { + $compileProvider.debugInfoEnabled(false); + } + }) + ); // Ensure the sortable angular module is loaded beforeEach(module('ui.sortable')); @@ -14,12 +15,13 @@ describe('uiSortable', function() { var listContent; - beforeEach(inject(function (sortableTestHelper) { - listContent = sortableTestHelper.listContent; - })); + beforeEach( + inject(function(sortableTestHelper) { + listContent = sortableTestHelper.listContent; + }) + ); describe('Simple use', function() { - it('should have a ui-sortable class', function() { inject(function($compile, $rootScope) { var element; @@ -31,14 +33,18 @@ describe('uiSortable', function() { it('should log that ngModel was not provided', function() { inject(function($compile, $rootScope, $log) { var element; - element = $compile('
      • {{ item }}
      ')($rootScope); + element = $compile( + '
      • {{ item }}
      ' + )($rootScope); $rootScope.$apply(function() { $rootScope.items = ['One', 'Two', 'Three']; }); expect($log.info.logs.length).toEqual(1); expect($log.info.logs[0].length).toEqual(2); - expect($log.info.logs[0][0]).toEqual('ui.sortable: ngModel not provided!'); + expect($log.info.logs[0][0]).toEqual( + 'ui.sortable: ngModel not provided!' + ); }); }); @@ -50,14 +56,18 @@ describe('uiSortable', function() { angular.element.fn = mockJQliteFn; var element; - element = $compile('
      • {{ item }}
      ')($rootScope); + element = $compile( + '
      • {{ item }}
      ' + )($rootScope); $rootScope.$apply(function() { $rootScope.items = ['One', 'Two', 'Three']; }); expect($log.error.logs.length).toEqual(1); expect($log.error.logs[0].length).toEqual(1); - expect($log.error.logs[0][0]).toEqual('ui.sortable: jQuery should be included before AngularJS!'); + expect($log.error.logs[0][0]).toEqual( + 'ui.sortable: jQuery should be included before AngularJS!' + ); angular.element.fn = oldAngularElementFn; }); @@ -67,7 +77,9 @@ describe('uiSortable', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); - element = $compile('
      • {{ item }}
      ')(childScope); + element = $compile( + '
      • {{ item }}
      ' + )(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; }); @@ -85,7 +97,9 @@ describe('uiSortable', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); - element = $compile('
      • {{ item }}
      ')(childScope); + element = $compile( + '
      • {{ item }}
      ' + )(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; childScope.opts = {}; @@ -104,7 +118,9 @@ describe('uiSortable', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); - element = $compile('
      • {{ item }}
      ')(childScope); + element = $compile( + '
      • {{ item }}
      ' + )(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; }); @@ -113,7 +129,6 @@ describe('uiSortable', function() { expect(function() { $timeout.flush(); }).not.toThrow(); - }); }); @@ -121,7 +136,9 @@ describe('uiSortable', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); - element = $compile('
      • {{ item }}
      ')(childScope); + element = $compile( + '
      • {{ item }}
      ' + )(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; childScope.opts = {}; @@ -131,7 +148,6 @@ describe('uiSortable', function() { expect(function() { $timeout.flush(); }).not.toThrow(); - }); }); @@ -139,7 +155,9 @@ describe('uiSortable', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); - element = $compile('
      • {{ item }}
      ')(childScope); + element = $compile( + '
      • {{ item }}
      ' + )(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; childScope.opts = { @@ -152,7 +170,6 @@ describe('uiSortable', function() { expect(function() { $timeout.flush(); }).not.toThrow(); - }); }); @@ -160,7 +177,9 @@ describe('uiSortable', function() { inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); - element = $compile('
      • {{ item }}
      ')(childScope); + element = $compile( + '
      • {{ item }}
      ' + )(childScope); $rootScope.$apply(function() { childScope.items = ['One', 'Two', 'Three']; childScope.opts = { @@ -173,35 +192,33 @@ describe('uiSortable', function() { expect(function() { $timeout.flush(); }).not.toThrow(); - }); }); describe('items option', function() { - it('should use a default items that is restricted to ng-repeat items', function() { - inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); - element = $compile('
        ')(childScope); + element = $compile( + '
          ' + )(childScope); $rootScope.$digest(); - expect(element.find('ul').sortable('option', 'items')).toBe('> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'); + expect(element.find('ul').sortable('option', 'items')).toBe( + '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]' + ); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); - }); - }); it('should not change items option if given', function() { - inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); @@ -209,24 +226,25 @@ describe('uiSortable', function() { items: '> .class' }; - element = $compile('
            ')(childScope); + element = $compile( + '
              ' + )(childScope); $rootScope.$digest(); - expect(element.find('ul').sortable('option', 'items')).toBe('> .class'); + expect(element.find('ul').sortable('option', 'items')).toBe( + '> .class' + ); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); - }); - }); it('should restrict to ng-items if items is removed after initialization', function() { - inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); @@ -234,7 +252,9 @@ describe('uiSortable', function() { items: '> .class' }; - element = $compile('
                ')(childScope); + element = $compile( + '
                  ' + )(childScope); $rootScope.$digest(); @@ -242,35 +262,40 @@ describe('uiSortable', function() { childScope.opts = { items: null }; }); - expect(element.find('ul').sortable('option', 'items')).toBe('> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]'); + expect(element.find('ul').sortable('option', 'items')).toBe( + '> [ng-repeat],> [data-ng-repeat],> [x-ng-repeat]' + ); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); - }); - }); it('should properly reset the value of a deleted option', function() { - inject(function($compile, $rootScope, $timeout) { var element; var childScope = $rootScope.$new(); childScope.opts = { opacity: 0.7, placeholder: 'phClass', - update: function() { } + update: function() {} }; - element = $compile('
                    ')(childScope); + element = $compile( + '
                      ' + )(childScope); var $sortableElement = element.find('[data-ui-sortable]'); expect($sortableElement.sortable('option', 'opacity')).toBe(0.7); - expect($sortableElement.sortable('option', 'placeholder')).toBe('phClass'); - expect(typeof $sortableElement.sortable('option', 'update')).toBe('function'); + expect($sortableElement.sortable('option', 'placeholder')).toBe( + 'phClass' + ); + expect(typeof $sortableElement.sortable('option', 'update')).toBe( + 'function' + ); $rootScope.$digest(); @@ -279,8 +304,12 @@ describe('uiSortable', function() { }); expect($sortableElement.sortable('option', 'opacity')).toBe(false); - expect($sortableElement.sortable('option', 'placeholder')).toBe('phClass'); - expect(typeof $sortableElement.sortable('option', 'update')).toBe('function'); + expect($sortableElement.sortable('option', 'placeholder')).toBe( + 'phClass' + ); + expect(typeof $sortableElement.sortable('option', 'update')).toBe( + 'function' + ); $rootScope.$digest(); @@ -289,17 +318,19 @@ describe('uiSortable', function() { }); expect($sortableElement.sortable('option', 'opacity')).toBe(false); - expect($sortableElement.sortable('option', 'placeholder')).toBe(false); - expect(typeof $sortableElement.sortable('option', 'update')).toBe('function'); + expect($sortableElement.sortable('option', 'placeholder')).toBe( + false + ); + expect(typeof $sortableElement.sortable('option', 'update')).toBe( + 'function' + ); element.remove(element.firstChild); expect(function() { $timeout.flush(); }).not.toThrow(); - }); - }); it('should not initialize a disabled sortable', function() { @@ -312,7 +343,9 @@ describe('uiSortable', function() { childScope.opts = { disabled: true }; - element = $compile('
                      • {{ item }}
                      ')(childScope); + element = $compile( + '
                      • {{ item }}
                      ' + )(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); }); @@ -328,7 +361,9 @@ describe('uiSortable', function() { childScope.opts = { disabled: true }; - element = $compile('
                      • {{ item }}
                      ')(childScope); + element = $compile( + '
                      • {{ item }}
                      ' + )(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); @@ -354,22 +389,23 @@ describe('uiSortable', function() { childScope.opts = { disabled: true }; - element = $compile('
                      • {{ item }}
                      ')(childScope); + element = $compile( + '
                      • {{ item }}
                      ' + )(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); - $timeout(function () { + $timeout(function() { childScope.opts.disabled = false; }); - $timeout(function () { + $timeout(function() { expect(angular.element.fn.sortable).toHaveBeenCalled(); }); expect(function() { $timeout.flush(); }).not.toThrow(); - }); }); @@ -383,7 +419,9 @@ describe('uiSortable', function() { childScope.opts = { disabled: true }; - element = $compile('
                      • {{ item }}
                      ')(childScope); + element = $compile( + '
                      • {{ item }}
                      ' + )(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); @@ -409,7 +447,9 @@ describe('uiSortable', function() { childScope.opts = { disabled: true }; - element = $compile('
                      • {{ item }}
                      ')(childScope); + element = $compile( + '
                      • {{ item }}
                      ' + )(childScope); expect(angular.element.fn.sortable).not.toHaveBeenCalled(); @@ -417,24 +457,19 @@ describe('uiSortable', function() { $timeout.flush(); }).not.toThrow(); - $timeout(function () { + $timeout(function() { childScope.opts = {}; }); - $timeout(function () { + $timeout(function() { expect(angular.element.fn.sortable).toHaveBeenCalled(); }); expect(function() { $timeout.flush(); }).not.toThrow(); - }); }); - }); - - }); - }); diff --git a/test/sortable.test-directives.js b/test/sortable.test-directives.js index 9ee801f..8186789 100644 --- a/test/sortable.test-directives.js +++ b/test/sortable.test-directives.js @@ -1,54 +1,52 @@ 'use strict'; -angular.module('ui.sortable.testDirectives', []) - .directive('uiSortableSimpleTestDirective', - function() { - return { - restrict: 'AE', - scope: true, - require: '?ngModel', - template: '
                      Directive: !!!
                      ', - link: function(scope, element, attrs) { - scope.$watch(attrs.ngModel, function(value) { - scope.text = value; - }); - } - }; - } - ) - .directive('uiSortableDestroyableTestDirective', - function() { - return { - restrict: 'AE', - scope: true, - require: '?ngModel', - template: '
                      $destroy(able) Directive: !!!
                      ', - link: function(scope, element, attrs) { - scope.$watch(attrs.ngModel, function(value) { - scope.text = value; - }); - - element.bind('$destroy', function() { - element.html(''); - }); - } - }; - } - ).directive('uiSortableTransclusionTestDirective', - function() { - return { - restrict: 'E', - transclude: true, - scope: true, - template: '
                      ' + - '

                      Transclusion Directive

                      ' + - '
                      ' + - '
                      ' + - '' + - '
                      ' + - '
                      ' + - '
                      ' - }; - } - ); +angular + .module('ui.sortable.testDirectives', []) + .directive('uiSortableSimpleTestDirective', function() { + return { + restrict: 'AE', + scope: true, + require: '?ngModel', + template: + '
                      Directive: !!!
                      ', + link: function(scope, element, attrs) { + scope.$watch(attrs.ngModel, function(value) { + scope.text = value; + }); + } + }; + }) + .directive('uiSortableDestroyableTestDirective', function() { + return { + restrict: 'AE', + scope: true, + require: '?ngModel', + template: + '
                      $destroy(able) Directive: !!!
                      ', + link: function(scope, element, attrs) { + scope.$watch(attrs.ngModel, function(value) { + scope.text = value; + }); + element.bind('$destroy', function() { + element.html(''); + }); + } + }; + }) + .directive('uiSortableTransclusionTestDirective', function() { + return { + restrict: 'E', + transclude: true, + scope: true, + template: + '
                      ' + + '

                      Transclusion Directive

                      ' + + '
                      ' + + '
                      ' + + '' + + '
                      ' + + '
                      ' + + '
                      ' + }; + }); diff --git a/test/sortable.test-helper.js b/test/sortable.test-helper.js index 6f5dd7b..0cd4a24 100644 --- a/test/sortable.test-helper.js +++ b/test/sortable.test-helper.js @@ -1,38 +1,56 @@ 'use strict'; -angular.module('ui.sortable.testHelper', []) - .factory('sortableTestHelper', function () { +angular + .module('ui.sortable.testHelper', []) + .factory('sortableTestHelper', function() { var EXTRA_DY_PERCENTAGE = 0.25; - function listContent (list, contentSelector) { + function listContent(list, contentSelector) { if (!contentSelector) { contentSelector = '[ng-repeat], [data-ng-repeat], [x-ng-repeat]'; } if (list && list.length) { - return list.children(contentSelector).map(function(){ return this.innerHTML; }).toArray(); + return list + .children(contentSelector) + .map(function() { + return this.innerHTML; + }) + .toArray(); } return []; } - function listFindContent (list, contentSelector) { + function listFindContent(list, contentSelector) { if (!contentSelector) { contentSelector = '.sortable-item'; } if (list && list.length) { - return list.find(contentSelector).map(function(){ return this.innerHTML; }).toArray(); + return list + .find(contentSelector) + .map(function() { + return this.innerHTML; + }) + .toArray(); } return []; } - function listInnerContent (list, contentSelector) { + function listInnerContent(list, contentSelector) { if (!contentSelector) { contentSelector = '.itemContent'; } if (list && list.length) { - return list.children().map(function(){ return $(this).find(contentSelector).html(); }).toArray(); + return list + .children() + .map(function() { + return $(this) + .find(contentSelector) + .html(); + }) + .toArray(); } return []; } @@ -54,9 +72,11 @@ angular.module('ui.sortable.testHelper', []) if (typeof options === 'object') { if ('place' in options) { if (options.place === 'above') { - dragOptions.dy -= EXTRA_DY_PERCENTAGE * draggedElement.outerHeight(); + dragOptions.dy -= + EXTRA_DY_PERCENTAGE * draggedElement.outerHeight(); } else if (options.place === 'below') { - dragOptions.dy += EXTRA_DY_PERCENTAGE * draggedElement.outerHeight(); + dragOptions.dy += + EXTRA_DY_PERCENTAGE * draggedElement.outerHeight(); } } @@ -66,7 +86,7 @@ angular.module('ui.sortable.testHelper', []) if (isFinite(options.dy)) { dragOptions.dy = options.dy; } - + if (isFinite(options.extrady)) { dragOptions.dy += options.extrady; } @@ -84,12 +104,14 @@ angular.module('ui.sortable.testHelper', []) } function hasUndefinedProperties(testObject) { - return testObject && Object.keys(testObject) - .filter(function(key) { - return testObject.hasOwnProperty(key) && - testObject[key] !== undefined; - }) - .length === 0; + return ( + testObject && + Object.keys(testObject).filter(function(key) { + return ( + testObject.hasOwnProperty(key) && testObject[key] !== undefined + ); + }).length === 0 + ); } return { @@ -109,6 +131,6 @@ angular.module('ui.sortable.testHelper', []) } }; }) - .controller('dummyController', function ($scope) { + .controller('dummyController', function($scope) { $scope.testItems = ['One', 'Two', 'Three']; }); From 0c88d075019913b0c8902bf801174640305887a0 Mon Sep 17 00:00:00 2001 From: Robert Bradley <7204286+robertbradleyux@users.noreply.github.com> Date: Wed, 10 Jan 2018 14:36:29 -0500 Subject: [PATCH 38/41] Add run-time dependencies The run-time dependencies when pulled in through NPM do not match the run-time dependencies listed in the Bower package. This means that when using NPM for dependency management the package's dependencies will not be pulled in. This update simply makes the dependencies in package.json match those of bower.json. --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index bb36f2c..3a7ef01 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,11 @@ "license": "MIT", "homepage": "http://angular-ui.github.com", "main": "./src/sortable.js", - "dependencies": {}, + "dependencies": { + "angular": ">=1.2.x", + "jquery": ">=3.1.x", + "jquery-ui": ">=1.12.x" + }, "devDependencies": { "angular-ui-publisher": "1.2.x", "grunt": "~0.4.x", From 22ba7f363de2907c2b35c037cc5c7bddf24f02db Mon Sep 17 00:00:00 2001 From: Robert Bradley <7204286+robertbradleyux@users.noreply.github.com> Date: Wed, 10 Jan 2018 14:56:15 -0500 Subject: [PATCH 39/41] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3a7ef01..299e17c 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dependencies": { "angular": ">=1.2.x", "jquery": ">=3.1.x", - "jquery-ui": ">=1.12.x" + "jquery-ui-dist": ">=1.12.x" }, "devDependencies": { "angular-ui-publisher": "1.2.x", From 1de674ead1a599c98600842440b2727a7eaabf6e Mon Sep 17 00:00:00 2001 From: Thodoris Greasidis Date: Sun, 14 Jan 2018 18:19:05 +0200 Subject: [PATCH 40/41] chore: increase version to v1.19.0 Resolves #546 --- bower.json | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bower.json b/bower.json index ca91322..db20c0c 100644 --- a/bower.json +++ b/bower.json @@ -1,5 +1,6 @@ { "name": "angular-ui-sortable", + "version": "0.19.0", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", diff --git a/package.json b/package.json index 299e17c..9a61e8f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.18.0", + "version": "0.19.0", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", From 89f964eb8536c29679276cb5191cd7e64052006e Mon Sep 17 00:00:00 2001 From: Max Arendsen Date: Wed, 16 May 2018 13:40:04 +0200 Subject: [PATCH 41/41] Updated small typo in the readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bf8cebb..15758cb 100644 --- a/README.md +++ b/README.md @@ -312,7 +312,7 @@ myAppModule.controller('MyController', function($scope) { ## Integrations - [firebase](http://codepen.io/thgreasi/pen/repEZg?editors=0010) - [ui.bootstrap.accordion](http://plnkr.co/edit/TGIeeEbbvJwpJ3WRqo2z?p=preview) -- [Angular Meterial](http://codepen.io/thgreasi/pen/NbyLVK) (thanks yenoh2) +- [Angular Material](http://codepen.io/thgreasi/pen/NbyLVK) (thanks yenoh2) - [Asynchronous loading jQuery+jQueryUI with crisbeto/angular-ui-sortable-loader](https://github.com/crisbeto/angular-ui-sortable-loader) ## Reporting Issues @@ -322,7 +322,7 @@ Feel free to edit any of them for your needs (don't forget to also update the li ## Testing -We use Karma and jshint to ensure the quality of the code. The easiest way to run these checks is to use grunt: +We use Karma and JSHint to ensure the quality of the code. The easiest way to run these checks is to use grunt: ```sh npm install -g grunt-cli