Browse Source

+ master

pull/612/merge
Lebedev Konstantin 9 years ago
parent
commit
d7b0c87a03
  1. 94
      README.md
  2. 26
      Sortable.html
  3. 1
      bower.json
  4. 127
      knockout/example.html

94
README.md

@ -12,7 +12,7 @@ Demo: http://rubaxa.github.io/Sortable/
* Supports drag handles *and selectable text* (better than voidberg's html5sortable) * Supports drag handles *and selectable text* (better than voidberg's html5sortable)
* Smart auto-scrolling * Smart auto-scrolling
* Built using native HTML5 drag and drop API * Built using native HTML5 drag and drop API
* Supports [Meteor](https://github.com/SortableJS/meteor), [AngularJS](#ng), [React](#react) and [Polymer](#polymer) * Supports [Meteor](https://github.com/SortableJS/meteor), [AngularJS](#ng), [React](#react), [Knockout](https://github.com/SortableJS/knockout-sortablejs) and [Polymer](#polymer)
* Supports any CSS library, e.g. [Bootstrap](#bs) * Supports any CSS library, e.g. [Bootstrap](#bs)
* Simple API * Simple API
* [CDN](#cdn) * [CDN](#cdn)
@ -62,15 +62,16 @@ var sortable = new Sortable(el, {
animation: 150, // ms, animation speed moving items when sorting, `0` — without animation animation: 150, // ms, animation speed moving items when sorting, `0` — without animation
handle: ".my-handle", // Drag handle selector within list items handle: ".my-handle", // Drag handle selector within list items
filter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function) filter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function)
draggable: ".item", // Specifies which items inside the element should be sortable draggable: ".item", // Specifies which items inside the element should be draggable
ghostClass: "sortable-ghost", // Class name for the drop placeholder ghostClass: "sortable-ghost", // Class name for the drop placeholder
chosenClass: "sortable-chosen", // Class name for the chosen item chosenClass: "sortable-chosen", // Class name for the chosen item
dragClass: "sortable-drag", // Class name for the dragging item dragClass: "sortable-drag", // Class name for the dragging item
dataIdAttr: 'data-id', dataIdAttr: 'data-id',
forceFallback: false, // ignore the HTML5 DnD behaviour and force the fallback to kick in forceFallback: false, // ignore the HTML5 DnD behaviour and force the fallback to kick in
fallbackClass: "sortable-fallback" // Class name for the cloned DOM Element when using forceFallback
fallbackOnBody: false // Appends the cloned DOM Element into the Document's Body fallbackClass: "sortable-fallback", // Class name for the cloned DOM Element when using forceFallback
fallbackOnBody: false, // Appends the cloned DOM Element into the Document's Body
fallbackTolerance: 0 // Specify in pixels how far the mouse should move before it's considered as a drag. fallbackTolerance: 0 // Specify in pixels how far the mouse should move before it's considered as a drag.
scroll: true, // or HTMLElement scroll: true, // or HTMLElement
@ -507,33 +508,64 @@ ReactDOM.render(<div>
</div>, document.body); </div>, 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';
<a name="ko"></a>
### Support KnockoutJS export class SortableExampleEsnext extends React.Component {
Include [knockout-sortable.js](knockout-sortable.js)
sortableContainersDecorator = (componentBackingInstance) => {
```html // check if backing instance not null
<div data-bind="sortable: {foreach: yourObservableArray, options: {/* sortable options here */}}"> if (componentBackingInstance) {
<!-- optional item template here --> let options = {
</div> handle: ".group-title" // Restricts sort start click/touch to the specified element
};
<div data-bind="draggable: {foreach: yourObservableArray, options: {/* sortable options here */}}"> Sortable.create(componentBackingInstance, options);
<!-- optional item template here --> }
</div> };
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 (
<div className="container" ref={this.sortableContainersDecorator}>
<div className="group">
<h2 className="group-title">Group 1</h2>
<div className="group-list" ref={this.sortableGroupDecorator}>
<div>Swap them around</div>
<div>Swap us around</div>
<div>Swap things around</div>
<div>Swap everything around</div>
</div>
</div>
<div className="group">
<h2 className="group-title">Group 2</h2>
<div className="group-list" ref={this.sortableGroupDecorator}>
<div>Swap them around</div>
<div>Swap us around</div>
<div>Swap things around</div>
<div>Swap everything around</div>
</div>
</div>
</div>
);
}
}
``` ```
Using this bindingHandler sorts the observableArray when the user sorts the HTMLElements.
The sortable/draggable bindingHandlers supports the same syntax as Knockouts built in [template](http://knockoutjs.com/documentation/template-binding.html) binding except for the `data` option, meaning that you could supply the name of a template or specify a separate templateEngine. The difference between the sortable and draggable handlers is that the draggable has the sortable `group` option set to `{pull:'clone',put: false}` and the `sort` option set to false by default (overridable).
Other attributes are:
* options: an object that contains settings for the underlaying sortable, ie `group`,`handle`, events etc.
* collection: if your `foreach` array is a computed then you would supply the underlaying observableArray that you would like to sort here.
--- ---
<a name="polymer"></a> <a name="polymer"></a>
@ -546,7 +578,7 @@ Other attributes are:
<template is="dom-repeat" items={{names}}> <template is="dom-repeat" items={{names}}>
<div>{{item}}</div> <div>{{item}}</div>
</template> </template>
<sortable-js> </sortable-js>
``` ```
### Method ### Method
@ -607,7 +639,7 @@ Sortable.create(el, {
* @returns {Array} * @returns {Array}
*/ */
get: function (sortable) { get: function (sortable) {
var order = localStorage.getItem(sortable.options.group); var order = localStorage.getItem(sortable.options.group.name);
return order ? order.split('|') : []; return order ? order.split('|') : [];
}, },
@ -617,7 +649,7 @@ Sortable.create(el, {
*/ */
set: function (sortable) { set: function (sortable) {
var order = sortable.toArray(); var order = sortable.toArray();
localStorage.setItem(sortable.options.group, order.join('|')); localStorage.setItem(sortable.options.group.name, order.join('|'));
} }
} }
}) })

26
Sortable.html

@ -11,7 +11,7 @@
is: "sortable-js", is: "sortable-js",
properties: { properties: {
group : { type: String, value: function() { return Math.random() }, observer: "groupChanged" }, group : { type: String, value: function() { return Math.random(); }, observer: "groupChanged" },
sort : { type: Boolean, value: true, observer: "sortChanged" }, sort : { type: Boolean, value: true, observer: "sortChanged" },
disabled : { type: Boolean, value: false, observer: "disabledChanged" }, disabled : { type: Boolean, value: false, observer: "disabledChanged" },
store : { type: Object, value: null, observer: "storeChanged" }, store : { type: Object, value: null, observer: "storeChanged" },
@ -55,6 +55,18 @@
// <span>hello</span> // <span>hello</span>
// <template is="dom-if"> // <template is="dom-if">
// <tempalte is="dom-repeat"> // <tempalte is="dom-repeat">
this.initialize();
},
detached: function() {
this.destroy()
},
initialize: function() {
var templates = this.querySelectorAll("template[is='dom-repeat']") var templates = this.querySelectorAll("template[is='dom-repeat']")
var template = templates[templates.length-1] var template = templates[templates.length-1]
@ -66,7 +78,11 @@
var eventCallbacks = { var eventCallbacks = {
onUpdate: function (e) { onUpdate: function (e) {
if (template) { if (template) {
template.splice("items", e.newIndex, 0, template.splice("items", e.oldIndex, 1)[0]) if(manuallyHandleUpdateEvents) {
template.items.splice(e.newIndex, 0, template.items.splice(e.oldIndex, 1)[0]);
} else {
template.splice("items", e.newIndex, 0, template.splice("items", e.oldIndex, 1)[0])
}
} }
this.fire("update", e) this.fire("update", e)
}, },
@ -124,8 +140,10 @@
this.sortable = Sortable.create(this, options); this.sortable = Sortable.create(this, options);
}, },
detached: function() { destroy: function() {
this.sortable.destroy() if(this.sortable) {
this.sortable.destroy()
}
}, },
groupChanged : function(value) { this.sortable && this.sortable.option("group", value) }, groupChanged : function(value) { this.sortable && this.sortable.option("group", value) },

1
bower.json

@ -3,7 +3,6 @@
"main": [ "main": [
"Sortable.js", "Sortable.js",
"ng-sortable.js", "ng-sortable.js",
"knockout-sortable.js",
"react-sortable-mixin.js" "react-sortable-mixin.js"
], ],
"homepage": "http://rubaxa.github.io/Sortable/", "homepage": "http://rubaxa.github.io/Sortable/",

127
knockout/example.html

@ -1,127 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<style>
.grid {
font-size: 0;
}
.col-1_2 {
box-sizing:border-box;
display: inline-block;
padding: 0.5rem;
font-size: 1rem;
}
.col-1_2 {
width: 50%;
}
.mirror {
color: #ccc;
}
</style>
</head>
<body>
<div class="grid">
<div class="col-1_2">
<div class="grid">
<div class="col-1_2">
<h4>Sortable observable</h4>
<ul data-bind="sortable: {foreach: sortableObservableItems}">
<li data-bind="text: name"></li>
</ul>
</div>
<div class="col-1_2 mirror">
<h4>Sortable observable mirrored</h4>
<ul data-bind="foreach: sortableObservableItems">
<li data-bind="text: name"></li>
</ul>
</div>
</div>
</div>
<div class="col-1_2">
<div class="grid">
<div class="col-1_2">
<h4>Sortable computed</h4>
<ul data-bind="sortable: {foreach: sortableComputedItems, collection: underlayingSortableComputedItems}">
<li data-bind="text: name"></li>
</ul>
</div>
<div class="col-1_2 mirror">
<h4>Sortable underlaying computed</h4>
<ul data-bind="foreach: underlayingSortableComputedItems">
<li data-bind="text: name"></li>
</ul>
</div>
</div>
</div>
</div>
<div class="grid">
<div class="col-1_2">
<div class="grid">
<div class="col-1_2">
<h4>Draggable observable</h4>
<ul data-bind="draggable: {foreach: draggableObservableItems}">
<li data-bind="text: name"></li>
</ul>
</div>
<div class="col-1_2 mirror">
<h4>Draggable observable mirrored</h4>
<ul data-bind="foreach: draggableObservableItems">
<li data-bind="text: name"></li>
</ul>
</div>
</div>
</div>
<div class="col-1_2">
<div class="grid">
<div class="col-1_2">
<h4>Draggable computed</h4>
<ul data-bind="draggable: {foreach: draggableComputedItems, collection: underlayingDraggableComputedItems}">
<li data-bind="text: name"></li>
</ul>
</div>
<div class="col-1_2 mirror">
<h4>Draggable computed mirrored</h4>
<ul data-bind="foreach: draggableComputedItems">
<li data-bind="text: name"></li>
</ul>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="../Sortable.js"></script>
<script src="../knockout-sortable.js"></script>
<script>
var sortableComputedItems = [{ name: 'Sortable computed 1' }, { name: 'Filtered computed 2' }, { name: 'Sortable computed 3' }, { name: 'Filtered computed 4' }, { name: 'Sortable computed 5' }, { name: 'Filtered computed 6' }];
var sortableObservableItems = [{ name: 'Sortable observable 1' }, { name: 'Sortable observable 2' }, { name: 'Sortable observable 3' }];
var draggableComputedItems = [{ name: 'Draggable computed 1' }, { name: 'Draggable computed 2' }, { name: 'Draggable computed 3' }];
var draggableObservableItems = [{ name: 'Draggable observable 1' }, { name: 'Draggable observable 2' }, { name: 'Draggable observable 3' }];
var vm = {
underlayingSortableComputedItems: ko.observableArray(sortableComputedItems),
sortableObservableItems: ko.observableArray(sortableObservableItems),
underlayingDraggableComputedItems: ko.observableArray(draggableComputedItems),
draggableObservableItems: ko.observableArray(draggableObservableItems)
}
vm.sortableComputedItems = ko.computed(function () {
return vm.underlayingSortableComputedItems()
.filter(function (item) {
return item.name.indexOf('Filtered') < 0;
});
});
vm.draggableComputedItems = ko.computed(function () { return vm.underlayingDraggableComputedItems(); });
ko.applyBindings(vm);
</script>
</body>
</html>
Loading…
Cancel
Save