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/.travis.yml b/.travis.yml index 7900299..6d05475 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ language: node_js node_js: -- '0.10' +- '6' addons: - firefox: "latest" + firefox: "54.0.1" 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: diff --git a/API.md b/API.md index 7288f81..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:** @@ -58,3 +69,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) { + +}); +``` diff --git a/README.md b/README.md index f20543e..15758cb 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). @@ -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,60 @@ $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
' } }; }) - .controller('dummyController', function ($scope) { + .controller('dummyController', function($scope) { $scope.testItems = ['One', 'Two', 'Three']; });
`s. + +### 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. + +* **ui-sortable-start** +* **ui-sortable-activate** +* **ui-sortable-before-stop** +* **ui-sortable-update** +* **ui-sortable-remove** +* **ui-sortable-receive** +* **ui-sortable-deactivate** +* **ui-sortable-stop** + + + +Expression works on update event. +```html +
    +
  • {{ item }}
  • +
+``` + + +On update event callBackFunction1 if called before callBackFunction2. +```js +$scope.sortableOptions = { + 'update': callBackFunction2 +}; +``` +```html +
    +
  • {{ item }}
  • +
+``` -#### Canceling +### Canceling Inside the `update` callback, you can check the item that is dragged and cancel the sorting. @@ -209,7 +263,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) { @@ -235,6 +289,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) @@ -257,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 @@ -267,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 diff --git a/bower.json b/bower.json index 7200b2f..db20c0c 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-ui-sortable", - "version": "0.16.1", + "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 4820e84..9a61e8f 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,16 @@ { "name": "angular-ui-sortable", - "version": "0.16.1", + "version": "0.19.0", "description": "This directive allows you to jQueryUI Sortable.", "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", "license": "MIT", "homepage": "http://angular-ui.github.com", "main": "./src/sortable.js", - "dependencies": {}, + "dependencies": { + "angular": ">=1.2.x", + "jquery": ">=3.1.x", + "jquery-ui-dist": ">=1.12.x" + }, "devDependencies": { "angular-ui-publisher": "1.2.x", "grunt": "~0.4.x", @@ -18,6 +22,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,13 +36,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": {}, + "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" + ] } } diff --git a/src/sortable.js b/src/sortable.js index 6ee75db..ed0c482 100644 --- a/src/sortable.js +++ b/src/sortable.js @@ -3,29 +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', scope: { ngModel: '=', - uiSortable: '=' + uiSortable: '=', + ////Expression bindings from html. + create: '&uiSortableCreate', + // helper:'&uiSortableHelper', + start: '&uiSortableStart', + activate: '&uiSortableActivate', + // sort:'&uiSortableSort', + // change:'&uiSortableChange', + // over:'&uiSortableOver', + // out:'&uiSortableOut', + 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); @@ -40,18 +59,36 @@ 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; } + 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' ){ + if (key === 'stop') { // call apply after stop - value = combineCallbacks( - value, function() { scope.$apply(); }); + value = combineCallbacks(value, function() { + scope.$apply(); + }); value = combineCallbacks(value, afterStop); } @@ -69,7 +106,11 @@ 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 @@ -84,11 +125,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'; @@ -113,16 +154,43 @@ 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) { + 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; } @@ -138,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 @@ -156,34 +228,48 @@ 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) - // is placed last. - result = savedNodes.last(); + result = helper; } return result; } // thanks jquery-ui - function isFloating (item) { - return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display')); + function isFloating(item) { + return ( + /left|right/.test(item.css('float')) || + /inline|table-cell/.test(item.css('display')) + ); } function getElementContext(elementScopes, element) { @@ -203,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); } @@ -213,40 +300,60 @@ 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 = { - 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 = { 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) { @@ -254,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); } @@ -266,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); } }; @@ -291,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, @@ -308,12 +417,16 @@ 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. var placeholder = getPlaceholderElement(element); if (placeholder && placeholder.length) { - var excludes = getPlaceholderExcludesludes(element, placeholder); + var excludes = getPlaceholderExcludesludes( + element, + placeholder + ); savedNodes = savedNodes.not(excludes); } }; @@ -322,14 +435,21 @@ 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 - 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]'); + 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 @@ -343,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. @@ -356,7 +478,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; } @@ -364,11 +486,15 @@ 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()) { - scope.$apply(function () { - ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0, - ui.item.sortable.moved); + 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); } }; @@ -376,18 +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] + ); }); - } else if (!wasMoved && - !angular.equals(element.contents().toArray(), savedNodes.toArray())) { + scope.$emit('ui-sortable:moved', ui); + } 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 @@ -399,13 +533,16 @@ 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); } - // 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) { @@ -426,25 +563,47 @@ 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]; }); } }; - wrappers.helper = function (inner) { + // 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) { + return function(e, item) { var oldItemSortable = item.sortable; var index = getItemIndex(item); + item.sortable = { model: ngModel.$modelValue[index], index: index, source: element, sourceList: item.parent(), sourceModel: ngModel.$modelValue, - _restore: function () { + _restore: function() { angular.forEach(item.sortable, function(value, key) { item.sortable[key] = undefined; }); @@ -462,23 +621,31 @@ angular.module('ui.sortable', []) return inner; }; - scope.$watchCollection('uiSortable', function(newVal, oldVal) { - // 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); - - 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 { @@ -489,7 +656,7 @@ angular.module('ui.sortable', []) element.sortable(opts); } - function initIfEnabled () { + function initIfEnabled() { if (scope.uiSortable && scope.uiSortable.disabled) { return false; } @@ -506,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 new file mode 100644 index 0000000..f09f8ff --- /dev/null +++ b/test/sortable.e2e.callbacks.attr.spec.js @@ -0,0 +1,215 @@ +'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); + }); + }); +}); diff --git a/test/sortable.e2e.callbacks.spec.js b/test/sortable.e2e.callbacks.spec.js index 8506ea3..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) { @@ -156,18 +173,81 @@ 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; - 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) { @@ -218,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) { @@ -259,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) { @@ -302,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); @@ -326,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) { @@ -346,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) { @@ -402,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) { @@ -440,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 }); @@ -483,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; @@ -516,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 }); @@ -526,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 }); @@ -542,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 @@ -573,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(); @@ -601,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) { @@ -634,7 +734,7 @@ describe('uiSortable', function() { expect($rootScope.logs).toEqual(listContent(logsElement)); $rootScope.$digest(); - + $rootScope.$apply(function() { $rootScope.opts = {}; }); @@ -652,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 0b4b174..af7c91c 100644 --- a/test/sortable.e2e.directiveoptions.spec.js +++ b/test/sortable.e2e.directiveoptions.spec.js @@ -1,39 +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; - - 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; - })); + 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 = ''; - } - })); + if (!useExtraElements) { + beforeLiElement = afterLiElement = ''; + beforeTrElement = afterTrElement = ''; + } + }) + ); afterEach(function() { host.remove(); @@ -43,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 @@ -83,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 @@ -123,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' @@ -163,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' @@ -203,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, @@ -220,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 = {}; }); @@ -244,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() { @@ -281,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() { @@ -318,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() { @@ -357,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() { @@ -393,18 +451,187 @@ 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){ + [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 new file mode 100644 index 0000000..3aad70e --- /dev/null +++ b/test/sortable.e2e.events.spec.js @@ -0,0 +1,212 @@ +'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); + }); + }); +}); 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 874ba8c..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,55 +86,200 @@ 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(); }); }); - }); + it('should update model when sorting between drectly nested sortables', function() { + inject(function($compile, $rootScope) { + var elementTree, li1, li2; -}); \ No newline at end of file + 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(); + }); + }); + }); +}); 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 38721b4..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 { @@ -102,11 +124,13 @@ angular.module('ui.sortable.testHelper', []) extraElements: { beforeLiElement: '
                • extra element
                • ', afterLiElement: '
                • extra element
                • ', + beforeTrElement: '
                  extra element
                  extra element