diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index ef454ab..c0e68c9 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -3,3 +3,15 @@ Before you create a issue, check it:
1. Try [dev](https://github.com/RubaXa/Sortable/tree/dev/)-branch, perhaps the problem has been solved;
2. [Use the search](https://github.com/RubaXa/Sortable/search?q=problem), maybe already have an answer;
3. If not found, create example on [jsbin.com (draft)](http://jsbin.com/zunibaxada/1/edit?html,js,output) and describe the problem.
+
+Bindings:
+ - Angular
+ - 2.0+: https://github.com/SortableJS/angular-sortablejs/issues
+ - legacy: https://github.com/SortableJS/angular-legacy-sortablejs/issues
+ - React
+ - ES2015+: https://github.com/SortableJS/react-sortablejs/issues
+ - mixin: https://github.com/SortableJS/react-mixin-sortablejs/issues
+ - Polymer: https://github.com/SortableJS/polymer-sortablejs/issues
+ - Knockout: https://github.com/SortableJS/knockout-sortablejs/issues
+ - Meteor: https://github.com/SortableJS/meteor-sortablejs/issues
+
diff --git a/README.md b/README.md
index 639448f..cb7b035 100644
--- a/README.md
+++ b/README.md
@@ -13,9 +13,13 @@ Demo: http://rubaxa.github.io/Sortable/
* Smart auto-scrolling
* Built using native HTML5 drag and drop API
* Supports
- * [Meteor](https://github.com/SortableJS/meteor)
- * [AngularJS](#ng)
- * [React](#react)
+ * [Meteor](https://github.com/SortableJS/meteor-sortablejs)
+ * AngularJS
+ * [2.0+](https://github.com/SortableJS/angular-sortablejs)
+ * [1.*](https://github.com/SortableJS/angular-legacy-sortablejs)
+ * React
+ * [ES2015+](https://github.com/SortableJS/react-sortablejs)
+ * [Mixin](https://github.com/SortableJS/react-mixin-sortablejs)
* [Knockout](https://github.com/SortableJS/knockout-sortablejs)
* [Polymer](https://github.com/SortableJS/polymer-sortablejs)
* Supports any CSS library, e.g. [Bootstrap](#bs)
@@ -387,193 +391,6 @@ The speed at which the window should scroll once the mouse pointer gets within t
---
-
-### Support AngularJS
-Include [ng-sortable.js](ng-sortable.js)
-
-Demo: http://jsbin.com/naduvo/1/edit?html,js,output
-
-```html
-
-```
-
-
-```js
-angular.module('myApp', ['ng-sortable'])
- .controller('demo', ['$scope', function ($scope) {
- $scope.items = ['item 1', 'item 2'];
- $scope.foo = ['foo 1', '..'];
- $scope.bar = ['bar 1', '..'];
- $scope.barConfig = {
- group: 'foobar',
- animation: 150,
- onSort: function (/** ngSortEvent */evt){
- // @see https://github.com/RubaXa/Sortable/blob/master/ng-sortable.js#L18-L24
- }
- };
- }]);
-```
-
-
----
-
-
-
-### Support React
-Include [react-sortable-mixin.js](react-sortable-mixin.js).
-See [more options](react-sortable-mixin.js#L26).
-
-
-```jsx
-var SortableList = React.createClass({
- mixins: [SortableMixin],
-
- getInitialState: function() {
- return {
- items: ['Mixin', 'Sortable']
- };
- },
-
- handleSort: function (/** Event */evt) { /*..*/ },
-
- render: function() {
- return {
- this.state.items.map(function (text, i) {
- return - {text}
- })
- }
- }
-});
-
-ReactDOM.render(, document.body);
-
-
-//
-// Groups
-//
-var AllUsers = React.createClass({
- mixins: [SortableMixin],
-
- sortableOptions: {
- ref: "user",
- group: "shared",
- model: "users"
- },
-
- getInitialState: function() {
- return { users: ['Abbi', 'Adela', 'Bud', 'Cate', 'Davis', 'Eric'] };
- },
-
- render: function() {
- return (
-
Users
-
{
- this.state.users.map(function (text, i) {
- return - {text}
- })
- }
-
- );
- }
-});
-
-var ApprovedUsers = React.createClass({
- mixins: [SortableMixin],
- sortableOptions: { group: "shared" },
-
- getInitialState: function() {
- return { items: ['Hal', 'Judy'] };
- },
-
- render: function() {
- return {
- this.state.items.map(function (text, i) {
- return - {text}
- })
- }
- }
-});
-
-ReactDOM.render(, document.body);
-```
-
-### Support React ES2015 / TypeScript syntax
-As mixins are not supported in ES2015 / TypeScript syntax here is example of ES2015 ref based implementation.
-Using refs is the preferred (by facebook) "escape hatch" to underlaying DOM nodes: [React: The ref Callback Attribute](https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute)
-
-```js
-import * as React from "react";
-import Sortable from 'sortablejs';
-
-export class SortableExampleEsnext extends React.Component {
-
- sortableContainersDecorator = (componentBackingInstance) => {
- // check if backing instance not null
- if (componentBackingInstance) {
- let options = {
- handle: ".group-title" // Restricts sort start click/touch to the specified element
- };
- Sortable.create(componentBackingInstance, options);
- }
- };
-
- sortableGroupDecorator = (componentBackingInstance) => {
- // check if backing instance not null
- if (componentBackingInstance) {
- let options = {
- draggable: "div", // Specifies which items inside the element should be sortable
- group: "shared"
- };
- Sortable.create(componentBackingInstance, options);
- }
- };
-
- render() {
- return (
-
-
-
Group 1
-
-
Swap them around
-
Swap us around
-
Swap things around
-
Swap everything around
-
-
-
-
Group 2
-
-
Swap them around
-
Swap us around
-
Swap things around
-
Swap everything around
-
-
-
- );
- }
-}
-```
-
----
-
-
### Method
diff --git a/bower.json b/bower.json
index a21c6ec..cd27f02 100644
--- a/bower.json
+++ b/bower.json
@@ -1,9 +1,7 @@
{
"name": "Sortable",
"main": [
- "Sortable.js",
- "ng-sortable.js",
- "react-sortable-mixin.js"
+ "Sortable.js"
],
"homepage": "http://rubaxa.github.io/Sortable/",
"authors": [
diff --git a/ng-sortable.js b/ng-sortable.js
deleted file mode 100644
index d830675..0000000
--- a/ng-sortable.js
+++ /dev/null
@@ -1,210 +0,0 @@
-/**
- * @author RubaXa
- * @licence MIT
- */
-(function (factory) {
- 'use strict';
-
- if (typeof define === 'function' && define.amd) {
- define(['angular', './Sortable'], factory);
- }
- else if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
- require('angular');
- factory(angular, require('./Sortable'));
- module.exports = 'ng-sortable';
- }
- else if (window.angular && window.Sortable) {
- factory(angular, Sortable);
- }
-})(function (angular, Sortable) {
- 'use strict';
-
-
- /**
- * @typedef {Object} ngSortEvent
- * @property {*} model List item
- * @property {Object|Array} models List of items
- * @property {number} oldIndex before sort
- * @property {number} newIndex after sort
- */
-
- var expando = 'Sortable:ng-sortable';
-
- angular.module('ng-sortable', [])
- .constant('ngSortableVersion', '0.4.0')
- .constant('ngSortableConfig', {})
- .directive('ngSortable', ['$parse', 'ngSortableConfig', function ($parse, ngSortableConfig) {
- var removed,
- nextSibling;
-
- function getNgRepeatExpression(node) {
- return node.getAttribute('ng-repeat') || node.getAttribute('data-ng-repeat') || node.getAttribute('x-ng-repeat');
- }
-
- // Export
- return {
- restrict: 'AC',
- scope: { ngSortable: "=?" },
- priority: 1001,
- compile: function ($element, $attr) {
-
- var ngRepeat = [].filter.call($element[0].childNodes, function (node) {
- return node.nodeType === Node.ELEMENT_NODE && getNgRepeatExpression(node);
- })[0];
-
- if (!ngRepeat) {
- return;
- }
-
- var match = getNgRepeatExpression(ngRepeat)
- .match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
-
- if (!match) {
- return;
- }
-
- var rhs = match[2];
-
- return function postLink(scope, $el) {
- var itemsExpr = $parse(rhs);
- var getSource = function getSource() {
- return itemsExpr(scope.$parent) || [];
- };
-
-
- var el = $el[0],
- options = angular.extend(scope.ngSortable || {}, ngSortableConfig),
- watchers = [],
- offDestroy,
- sortable
- ;
-
- el[expando] = getSource;
-
- function _emitEvent(/**Event*/evt, /*Mixed*/item) {
- var name = 'on' + evt.type.charAt(0).toUpperCase() + evt.type.substr(1);
- var source = getSource();
-
- /* jshint expr:true */
- options[name] && options[name]({
- model: item || source[evt.newIndex],
- models: source,
- oldIndex: evt.oldIndex,
- newIndex: evt.newIndex,
- originalEvent: evt
- });
- }
-
-
- function _sync(/**Event*/evt) {
- var items = getSource();
-
- if (!items) {
- // Without ng-repeat
- return;
- }
-
- var oldIndex = evt.oldIndex,
- newIndex = evt.newIndex;
-
- if (el !== evt.from) {
- var prevItems = evt.from[expando]();
-
- removed = prevItems[oldIndex];
-
- if (evt.clone) {
- removed = angular.copy(removed);
- prevItems.splice(Sortable.utils.index(evt.clone, sortable.options.draggable), 0, prevItems.splice(oldIndex, 1)[0]);
- evt.from.removeChild(evt.clone);
- }
- else {
- prevItems.splice(oldIndex, 1);
- }
-
- items.splice(newIndex, 0, removed);
-
- evt.from.insertBefore(evt.item, nextSibling); // revert element
- }
- else {
- items.splice(newIndex, 0, items.splice(oldIndex, 1)[0]);
-
- // move ng-repeat comment node to right position
- if (nextSibling.nodeType === Node.COMMENT_NODE) {
- evt.from.insertBefore(nextSibling, evt.item.nextSibling);
- }
- }
-
- scope.$apply();
- }
-
- function _destroy() {
- offDestroy();
-
- angular.forEach(watchers, function (/** Function */unwatch) {
- unwatch();
- });
-
- sortable.destroy();
-
- el[expando] = null;
- el = null;
- watchers = null;
- sortable = null;
- nextSibling = null;
- }
-
-
- // Initialization
- sortable = Sortable.create(el, Object.keys(options).reduce(function (opts, name) {
- opts[name] = opts[name] || options[name];
- return opts;
- }, {
- onStart: function (/**Event*/evt) {
- nextSibling = evt.from === evt.item.parentNode ? evt.item.nextSibling : evt.clone.nextSibling;
- _emitEvent(evt);
- scope.$apply();
- },
- onEnd: function (/**Event*/evt) {
- _emitEvent(evt, removed);
- scope.$apply();
- },
- onAdd: function (/**Event*/evt) {
- _sync(evt);
- _emitEvent(evt, removed);
- scope.$apply();
- },
- onUpdate: function (/**Event*/evt) {
- _sync(evt);
- _emitEvent(evt);
- },
- onRemove: function (/**Event*/evt) {
- _emitEvent(evt, removed);
- },
- onSort: function (/**Event*/evt) {
- _emitEvent(evt);
- }
- }));
-
- // Create watchers for `options`
- angular.forEach([
- 'sort', 'disabled', 'draggable', 'handle', 'animation', 'group', 'ghostClass', 'filter',
- 'onStart', 'onEnd', 'onAdd', 'onUpdate', 'onRemove', 'onSort', 'onMove', 'onClone', 'setData'
- ], function (name) {
- watchers.push(scope.$watch('ngSortable.' + name, function (value) {
- if (value !== void 0) {
- options[name] = value;
-
- if (!/^on[A-Z]/.test(name)) {
- sortable.option(name, value);
- }
- }
- }));
- });
-
- offDestroy = scope.$on('$destroy', _destroy);
-
- }
- }
- };
- }]);
-});
diff --git a/react-sortable-mixin.js b/react-sortable-mixin.js
deleted file mode 100644
index 68792ea..0000000
--- a/react-sortable-mixin.js
+++ /dev/null
@@ -1,169 +0,0 @@
-/**
- * @author RubaXa
- * @licence MIT
- */
-
-(function (factory) {
- 'use strict';
-
- if (typeof module != 'undefined' && typeof module.exports != 'undefined') {
- module.exports = factory(require('./Sortable'));
- }
- else if (typeof define === 'function' && define.amd) {
- define(['./Sortable'], factory);
- }
- else {
- /* jshint sub:true */
- window['SortableMixin'] = factory(Sortable);
- }
-})(function (/** Sortable */Sortable) {
- 'use strict';
-
- var _nextSibling;
-
- var _activeComponent;
-
- var _defaultOptions = {
- ref: 'list',
- model: 'items',
-
- animation: 100,
- onStart: 'handleStart',
- onEnd: 'handleEnd',
- onAdd: 'handleAdd',
- onUpdate: 'handleUpdate',
- onRemove: 'handleRemove',
- onSort: 'handleSort',
- onFilter: 'handleFilter',
- onMove: 'handleMove',
- onClone: 'handleClone'
- };
-
-
- function _getModelName(component) {
- return component.sortableOptions && component.sortableOptions.model || _defaultOptions.model;
- }
-
-
- function _getModelItems(component) {
- var name = _getModelName(component),
- items = component.state && component.state[name] || component.props[name];
-
- return items.slice();
- }
-
-
- function _extend(dst, src) {
- for (var key in src) {
- if (src.hasOwnProperty(key)) {
- dst[key] = src[key];
- }
- }
-
- return dst;
- }
-
-
- /**
- * Simple and easy mixin-wrapper for rubaxa/Sortable library, in order to
- * make reorderable drag-and-drop lists on modern browsers and touch devices.
- *
- * @mixin
- */
- var SortableMixin = {
- sortableMixinVersion: '0.1.1',
-
-
- /**
- * @type {Sortable}
- * @private
- */
- _sortableInstance: null,
-
-
- componentDidMount: function () {
- var DOMNode, options = _extend(_extend({}, _defaultOptions), this.sortableOptions || {}),
- copyOptions = _extend({}, options),
-
- emitEvent = function (/** string */type, /** Event */evt) {
- var method = options[type];
- if (method && typeof method === "string") {
- method = this[method];
- }
- method && typeof method === "function" && method.call(this, evt, this._sortableInstance);
- }.bind(this);
-
-
- // Bind callbacks so that "this" refers to the component
- 'onStart onEnd onAdd onSort onUpdate onRemove onFilter onMove'.split(' ').forEach(function (/** string */name) {
- copyOptions[name] = function (evt) {
- if (name === 'onStart') {
- _nextSibling = evt.item.nextElementSibling;
- _activeComponent = this;
- }
- else if (name === 'onAdd' || name === 'onUpdate') {
- evt.from.insertBefore(evt.item, _nextSibling);
-
- var newState = {},
- remoteState = {},
- oldIndex = evt.oldIndex,
- newIndex = evt.newIndex,
- items = _getModelItems(this),
- remoteItems,
- item;
-
- if (name === 'onAdd') {
- remoteItems = _getModelItems(_activeComponent);
- item = remoteItems.splice(oldIndex, 1)[0];
- items.splice(newIndex, 0, item);
-
- remoteState[_getModelName(_activeComponent)] = remoteItems;
- }
- else {
- items.splice(newIndex, 0, items.splice(oldIndex, 1)[0]);
- }
-
- newState[_getModelName(this)] = items;
-
- if (copyOptions.stateHandler) {
- this[copyOptions.stateHandler](newState);
- } else {
- this.setState(newState);
- }
-
- (this !== _activeComponent) && _activeComponent.setState(remoteState);
- }
-
- setTimeout(function () {
- emitEvent(name, evt);
- }, 0);
- }.bind(this);
- }, this);
-
- DOMNode = typeof this.getDOMNode === 'function' ? (this.refs[options.ref] || this).getDOMNode() : this.refs[options.ref] || this;
-
- /** @namespace this.refs — http://facebook.github.io/react/docs/more-about-refs.html */
- this._sortableInstance = Sortable.create(DOMNode, copyOptions);
- },
-
- componentWillReceiveProps: function (nextProps) {
- var newState = {},
- modelName = _getModelName(this),
- items = nextProps[modelName];
-
- if (items) {
- newState[modelName] = items;
- this.setState(newState);
- }
- },
-
- componentWillUnmount: function () {
- this._sortableInstance.destroy();
- this._sortableInstance = null;
- }
- };
-
-
- // Export
- return SortableMixin;
-});