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

Commit

Permalink
Merge pull request #280 from angular-ui/v0.13.x-dev
Browse files Browse the repository at this point in the history
chore: merge V0.13.x dev into master
  • Loading branch information
thgreasi committed Oct 14, 2014
2 parents 57c5332 + c819182 commit 37c11b9
Show file tree
Hide file tree
Showing 10 changed files with 690 additions and 13 deletions.
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

0 comments on commit 37c11b9

Please sign in to comment.