Skip to content
This repository was archived by the owner on Sep 8, 2020. It is now read-only.

chore: Merge V0.13.x dev into master #280

Merged
merged 19 commits into from
Oct 14, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2fb4240
feat(sortable): update local variable with active options
thgreasi Jul 8, 2014
104405b
feat(sortable): add workaround for horizontal lists
thgreasi Jul 8, 2014
830831c
test(sortable): add tests for horizontal lists workaround
thgreasi Jul 8, 2014
2e22b0e
docs(README): add section about floating workaround & example
thgreasi Jul 8, 2014
1d18029
fix(sortable): clear ui.item.sortable properties after drag stop
thgreasi Aug 31, 2014
14ae8da
test(sortable): add tests for ui.item.sortable proper destruction
thgreasi Aug 31, 2014
d777fef
refactor(sortable): replace for-in-hasOwnProperty with angular.forEach
thgreasi Sep 3, 2014
ff25513
feat(sortable): add extra properties to ui.item.sortable
thgreasi Sep 3, 2014
3a845c5
tests(sortable): add tests for the properties of ui.item.sortable
thgreasi Sep 4, 2014
54de466
Merge pull request #261 from thgreasi/extraProperties
thgreasi Sep 7, 2014
381ed62
tests: fix configuration of custom helper function + cancel() test
thgreasi Sep 7, 2014
06b506e
Merge pull request #262 from thgreasi/helperFuncTestFix
thgreasi Sep 7, 2014
1da4f7e
docs(README): change dynamic nested tree helper repo link
thgreasi Sep 18, 2014
28c545e
Merge pull request #272 from thgreasi/readmeDynamicDirective
thgreasi Sep 18, 2014
837f1a6
docs(API.md): add API.md explaining ui.item.sortable properties
thgreasi Oct 5, 2014
6fc6ffa
Merge pull request #276 from thgreasi/extraPropertiesDoc
thgreasi Oct 5, 2014
fb52727
chore: update bower.json to allow angular#1.3
thgreasi Oct 14, 2014
2a5f7c3
chore: increase version number to v0.13.0
thgreasi Oct 14, 2014
c819182
Merge pull request #279 from thgreasi/v0.13.x-dev
thgreasi Oct 14, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# ui.item.sortable API documentation

## Properties

### dropindex
Type: [Integer](http://api.jquery.com/Types/#Integer)
Holds the index of the drop target that the dragged item was dropped.


### droptarget
Type: [jQuery](http://api.jquery.com/Types/#jQuery)
Holds the ui-sortable element that the dragged item was dropped on.

### droptargetModel
Type: [Array](http://api.jquery.com/Types/#Array)
Holds the array that is specified by the `ng-model` attribute of the [`droptarget`](#droptarget) ui-sortable element.

### index
Type: [Integer](http://api.jquery.com/Types/#Integer)
Holds the original index of the item dragged.

### model
Type: [Object](http://api.jquery.com/Types/#Object)
Holds the JavaScript object that is used as the model of the dragged item, as specified by the ng-repeat of the [`source`](#source) ui-sortable element and the item's [`index`](#index).

### moved
Type: [Object](http://api.jquery.com/Types/#Object)/`undefined`
Holds the model of the dragged item only when a sorting happens between two connected ui-sortable elements.
In other words: `'moved' in ui.item.sortable` will return false only when a sorting is withing the same ui-sortable element ([`source`](#source) equals to the [`droptarget`](#droptarget)).

### received
Type: [Boolean](http://api.jquery.com/Types/#Boolean)
When sorting between two connected sortables, it will be set to true inside the `update` callback of the [`droptarget`](#droptarget).

### source
Type: [jQuery](http://api.jquery.com/Types/#jQuery)
Holds the ui-sortable element that the dragged item originated from.

### sourceModel
Type: [Array](http://api.jquery.com/Types/#Array)
Holds the array that is specified by the `ng-model` of the [`source`](#source) ui-sortable element.


## Methods

### cancel[()](http://api.jquery.com/Types/#Function)
Returns: Nothing
Can be called inside the `update` callback, in order to prevent/revert a sorting.
Should be used instead of the [jquery-ui-sortable cancel()](http://api.jqueryui.com/sortable/#method-cancel) method.

### isCanceled[()](http://api.jquery.com/Types/#Function)
Returns: [Boolean](http://api.jquery.com/Types/#Boolean)
Returns whether the current sorting is marked as canceled, by an earlier call to [`ui.item.sortable.cancel()`](#cancel).

### 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.
41 changes: 39 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ Apply the directive to your form elements:
* `ui-sortable` element should only contain one `ng-repeat` and not any other elements (above or below).
Otherwise the index matching of the generated DOM elements and the `ng-model`'s items will break.
**In other words: The items of `ng-model` must match the indexes of the generated DOM elements.**
* `ui-sortable` lists containing many 'types' of items can be implemented by using dynamic template loading [with ng-include](http://stackoverflow.com/questions/14607879/angularjs-load-dynamic-template-html-within-directive/14621927#14621927) or a [loader directive](https://gist.github.com/thgreasi/7152499c0e91973c4820), to determine how each model item should be rendered. Also take a look at the [Tree with dynamic template](http://codepen.io/thgreasi/pen/uyHFC) example.
* `ui-sortable` lists containing many 'types' of items can be implemented by using dynamic template loading [with ng-include](http://stackoverflow.com/questions/14607879/angularjs-load-dynamic-template-html-within-directive/14621927#14621927) or a [loader directive](https://github.com/thgreasi/tg-dynamic-directive), to determine how each model item should be rendered. Also take a look at the [Tree with dynamic template](http://codepen.io/thgreasi/pen/uyHFC) example.

### Options

All the [jQueryUI Sortable options](http://api.jqueryui.com/sortable/) can be passed through the directive.
All the [jQueryUI Sortable options](http://api.jqueryui.com/sortable/) can be passed through the directive.
Additionally, the `ui` argument of the available callbacks gets enriched with some extra properties as specified to the [API.md file](API.md#uiitemsortable-api-documentation).


```js
Expand All @@ -69,6 +70,41 @@ 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

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).
There is also a [known issue](bugs.jqueryui.com/ticket/7498) about initially empty horizontal lists.

To provide a solution/workaround (till jquery.ui.sortable.refresh() also tests the orientation or a more appropriate method is provided), ui-sortable directive provides a `ui-floating` option as an extra to the [jquery.ui.sortable options](http://api.jqueryui.com/sortable/).

```html
<ul ui-sortable="{ 'ui-floating': true }" ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
```

**OR**

```js
$scope.sortableOptions = {
'ui-floating': true
};
```
```html
<ul ui-sortable="sortableOptions" ng-model="items">
<li ng-repeat="item in items">{{ item }}</li>
</ul>
```


**ui-floating** (default: undefined)
Type: [Boolean](http://api.jquery.com/Types/#Boolean)/[String](http://api.jquery.com/Types/#String)/`undefined`
* **undefined**: Relies on jquery.ui to detect the list's orientation.
* **false**: Forces jquery.ui.sortable to detect the list as vertical.
* **true**: Forces jquery.ui.sortable to detect the list as horizontal.
* **"auto"**: Detects on each drag `start` if the element is floating or not.

#### Canceling

Inside the `update` callback, you can check the item that is dragged and cancel the sorting.
Expand Down Expand Up @@ -138,6 +174,7 @@ For more details about the events check the [jQueryUI API documentation](http://
- [Filtering](http://codepen.io/thgreasi/pen/mzGbq) ([details](https://github.com/angular-ui/ui-sortable/issues/113))
- [Ordering 1](http://codepen.io/thgreasi/pen/iKEHd) & [Ordering 2](http://plnkr.co/edit/XPUzJjdvwE0QWQ6py6mQ?p=preview) ([details](https://github.com/angular-ui/ui-sortable/issues/70))
- [Cloning](http://codepen.io/thgreasi/pen/qmvhG) ([details](https://github.com/angular-ui/ui-sortable/issues/139))
- [Horizontal List](http://codepen.io/thgreasi/pen/wsfjD)
- [Tree with dynamic template](http://codepen.io/thgreasi/pen/uyHFC)
- Canceling
- [Connected Lists With Max Size](http://codepen.io/thgreasi/pen/IdvFc)
Expand Down
6 changes: 3 additions & 3 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "angular-ui-sortable",
"version": "0.12.11",
"version": "0.13.0",
"description": "This directive allows you to jQueryUI Sortable.",
"author": "https://github.com/angular-ui/ui-sortable/graphs/contributors",
"license": "MIT",
Expand All @@ -16,11 +16,11 @@
"package.json"
],
"dependencies": {
"angular": "~1.2.x",
"angular": ">=1.2.x",
"jquery-ui": ">=1.9"
},
"devDependencies": {
"angular-mocks": "~1.2.x",
"angular-mocks": ">=1.2.x",
"jquery-simulate": "latest"
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "angular-ui-sortable",
"version": "0.12.11",
"version": "0.13.0",
"description": "This directive allows you to jQueryUI Sortable.",
"author": "https://github.com/angular-ui/ui-sortable/graphs/contributors",
"license": "MIT",
Expand Down
56 changes: 52 additions & 4 deletions src/sortable.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,22 @@ angular.module('ui.sortable', [])
return helperOption === 'clone' || (typeof helperOption === 'function' && ui.item.sortable.isCustomHelperUsed());
}

// thanks jquery-ui
function isFloating (item) {
return (/left|right/).test(item.css('float')) || (/inline|table-cell/).test(item.css('display'));
}

function afterStop(e, ui) {
ui.item.sortable._destroy();
}

var opts = {};

// directive specific options
var directiveOpts = {
'ui-floating': undefined
};

var callbacks = {
receive: null,
remove:null,
Expand All @@ -42,7 +56,7 @@ angular.module('ui.sortable', [])
helper: null
};

angular.extend(opts, uiSortableConfig, scope.$eval(attrs.uiSortable));
angular.extend(opts, directiveOpts, uiSortableConfig, scope.$eval(attrs.uiSortable));

if (!angular.element.fn || !angular.element.fn.jquery) {
$log.error('ui.sortable: jQuery should be included before AngularJS!');
Expand All @@ -65,9 +79,19 @@ angular.module('ui.sortable', [])
});

callbacks.start = function(e, ui) {
if (opts['ui-floating'] === 'auto') {
// since the drag has started, the element will be
// absolutely positioned, so we check its siblings
var siblings = ui.item.siblings();
angular.element(e.target).data('ui-sortable').floating = isFloating(siblings);
}

// Save the starting position of dragged item
ui.item.sortable = {
model: ngModel.$modelValue[ui.item.index()],
index: ui.item.index(),
source: ui.item.parent(),
sourceModel: ngModel.$modelValue,
cancel: function () {
ui.item.sortable._isCanceled = true;
},
Expand All @@ -78,7 +102,12 @@ angular.module('ui.sortable', [])
return !!ui.item.sortable._isCustomHelperUsed;
},
_isCanceled: false,
_isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed
_isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed,
_destroy: function () {
angular.forEach(ui.item.sortable, function(value, key) {
ui.item.sortable[key] = undefined;
});
}
};
};

Expand Down Expand Up @@ -119,7 +148,9 @@ angular.module('ui.sortable', [])
// the value will be overwritten with the old value
if(!ui.item.sortable.received) {
ui.item.sortable.dropindex = ui.item.index();
ui.item.sortable.droptarget = ui.item.parent();
var droptarget = ui.item.parent();
ui.item.sortable.droptarget = droptarget;
ui.item.sortable.droptargetModel = droptarget.scope().$eval(droptarget.attr('ng-model'));

// Cancel the sort (let ng-repeat do the sort for us)
// Don't cancel if this is the received list because it has
Expand Down Expand Up @@ -229,25 +260,42 @@ angular.module('ui.sortable', [])
// is still bound to the directive's element
if (!!element.data('ui-sortable')) {
angular.forEach(newVal, function(value, key) {
if(callbacks[key]) {
// if it's a custom option of the directive,
// handle it approprietly
if (key in directiveOpts) {
if (key === 'ui-floating' && (value === false || value === true)) {
element.data('ui-sortable').floating = value;
}

opts[key] = value;
return;
}

if (callbacks[key]) {
if( key === 'stop' ){
// call apply after stop
value = combineCallbacks(
value, function() { scope.$apply(); });

value = combineCallbacks(value, afterStop);
}
// wrap the callback
value = combineCallbacks(callbacks[key], value);
} else if (wrappers[key]) {
value = wrappers[key](value);
}

opts[key] = value;
element.sortable('option', key, value);
});
}
}, true);

angular.forEach(callbacks, function(value, key) {
opts[key] = combineCallbacks(value, opts[key]);
if( key === 'stop' ){
opts[key] = combineCallbacks(opts[key], afterStop);
}
});

} else {
Expand Down
Loading