Browse Source

Merge branch 'react' into dev

pull/296/head
RubaXa 10 years ago
parent
commit
5cae94c900
  1. 88
      README.md
  2. 4
      index.html
  3. 5
      package.json
  4. 147
      react-sortable-mixin.js
  5. 37
      st/app.js

88
README.md

@ -12,7 +12,7 @@ Demo: http://rubaxa.github.io/Sortable/
* Supports drag handles *and selectable text* (better than voidberg's html5sortable)
* Smart auto-scrolling
* Built using native HTML5 drag and drop API
* Supports [Meteor](meteor/README.md) and [AngularJS](#ng)
* Supports [Meteor](meteor/README.md), [AngularJS](#ng) and [React](#react)
* Supports any CSS library, e.g. [Bootstrap](#bs)
* Simple API
* [CDN](#cdn)
@ -300,6 +300,92 @@ angular.module('myApp', ['ng-sortable'])
---
<a name="react"></a>
### 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 <ul>{
this.state.items.map(function (text) {
return <li>{text}</li>
})
}</ul>
}
});
React.render(<SortableList />, 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 (
<h1>Users</h1>
<ul ref="users">{
this.state.users.map(function (text) {
return <li>{text}</li>
})
}</ul>
);
}
});
var ApprovedUsers = React.createClass({
mixins: [SortableMixin],
sortableOptions: { group: "shared" },
getInitialState: function() {
return { items: ['Hal', 'Judy']; };
},
render: function() {
return <ul>{
this.state.items.map(function (text) {
return <li>{text}</li>
})
}</ul>
}
});
React.render(<div>
<AllUsers/>
<hr/>
<ApprovedUsers/>
</div>, document.body);
```
---
### Method

4
index.html

@ -7,8 +7,8 @@
<title>Sortable. No jQuery.</title>
<meta name="keywords" content="sortable, reorder, list, javascript, html5, drag and drop, dnd, animation, groups, angular, ng-sortable, effects, rubaxa"/>
<meta name="description" content="Sortable - is a minimalist JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery. Supports Meteor and AngularJS and any CSS library, e.g. Bootstrap."/>
<meta name="keywords" content="sortable, reorder, list, javascript, html5, drag and drop, dnd, animation, groups, angular, ng-sortable, react, mixin, effects, rubaxa"/>
<meta name="description" content="Sortable - is a minimalist JavaScript library for reorderable drag-and-drop lists on modern browsers and touch devices. No jQuery. Supports Meteor, AngularJS, React and any CSS library, e.g. Bootstrap."/>
<meta name="viewport" content="width=device-width, initial-scale=0.5"/>
<link href="//rubaxa.github.io/Ply/ply.css" rel="stylesheet" type="text/css"/>

5
package.json

@ -23,8 +23,11 @@
"sortable",
"reorder",
"drag",
"meteor",
"angular",
"ng-srotable",
"angular"
"react",
"mixin"
],
"author": "Konstantin Lebedev <ibnRubaXa@gmail.com>",
"license": "MIT",

147
react-sortable-mixin.js vendored

@ -0,0 +1,147 @@
/**
* @author RubaXa <trash@rubaxa.org>
* @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'
};
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.0',
/**
* @type {Sortable}
* @private
*/
_sortableInstance: null,
componentDidMount: function () {
var options = _extend(_extend({}, _defaultOptions), this.sortableOptions || {}),
copyOptions = _extend({}, options),
emitEvent = function (/** string */type, /** Event */evt) {
var method = this[options[type]];
method && method.call(this, evt, this._sortableInstance);
}.bind(this);
// Bind callbacks so that "this" refers to the component
'onStart onEnd onAdd onSort onUpdate onRemove onFilter'.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;
this.setState(newState);
(this !== _activeComponent) && _activeComponent.setState(remoteState);
}
setTimeout(function () {
emitEvent(name, evt);
}, 0);
}.bind(this);
}, this);
/** @namespace this.refs — http://facebook.github.io/react/docs/more-about-refs.html */
this._sortableInstance = Sortable.create((this.refs[options.ref] || this).getDOMNode(), copyOptions);
},
componentWillUnmount: function () {
this._sortableInstance.destroy();
this._sortableInstance = null;
}
};
// Export
return SortableMixin;
});

37
st/app.js

@ -1,5 +1,41 @@
(function () {
'use strict';
var byId = function (id) { return document.getElementById(id); },
loadScripts = function (desc, callback) {
var deps = [], key, idx = 0;
for (key in desc) {
deps.push(key);
}
(function _next() {
var pid,
name = deps[idx],
script = document.createElement('script');
script.type = 'text/javascript';
script.src = desc[deps[idx]];
pid = setInterval(function () {
if (window[name]) {
clearTimeout(pid);
deps[idx++] = window[name];
if (deps[idx]) {
_next();
} else {
callback.apply(null, deps);
}
}
}, 30);
document.getElementsByTagName('head')[0].appendChild(script);
})()
},
console = window.console;
@ -162,6 +198,7 @@
})();
// Background
document.addEventListener("DOMContentLoaded", function () {
function setNoiseBackground(el, width, height, opacity) {

Loading…
Cancel
Save