diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..ffbb4f1a7 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,33 @@ +version: 2.0 +jobs: + build: + docker: + - image: circleci/node:10.16-browsers + steps: + - checkout + + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + - v1-dependencies- + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: npm run build:umd + + - run: + name: Compatibility Test + command: | + if [ -z "$CIRCLE_PR_NUMBER" ]; + then + npm run test:compat + fi + - run: npm run test + + - store_test_results: + path: /tmp/test-results diff --git a/.editorconfig b/.editorconfig index b0d7fd91b..09d275186 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,3 +10,6 @@ insert_final_newline = true [*.md] trim_trailing_whitespace = false + +[*.yml] +indent_style = space diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 000000000..53a033cfd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,73 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[bug] " +labels: "" +assignees: "" +--- + + + +**Describe the bug** + + + +**To Reproduce** +Steps to reproduce the behavior: + +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** + + + +**Information** + + + +Versions - Look in your `package.json` for this information: +sortablejs = ^x.x.x +@types/sortablejs = ^x.x.x + +**Additional context** +Add any other context about the problem here. + +**Reproduction** +codesandbox: + + diff --git a/.github/ISSUE_TEMPLATE/custom-template.md b/.github/ISSUE_TEMPLATE/custom-template.md new file mode 100644 index 000000000..14e2a2239 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom-template.md @@ -0,0 +1,48 @@ +--- +name: Custom issue template +about: Not a feature request or a bug report. Usually questions, queries or concerns +title: "" +labels: "" +assignees: "" +--- + +**Custom** + + + +**Reproduction** +codesandbox: + + diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 000000000..a0bbb57d0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,41 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[feature] " +labels: "" +assignees: "" +--- + + + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.gitignore b/.gitignore index 434cfa9b1..bb83eae77 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ mock.png .*.sw* .build* jquery.fn.* +.idea/ diff --git a/.jshintrc b/.jshintrc index 3f67a098b..ffbcc18f9 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,10 +1,11 @@ { - "strict": true, + "strict": false, "newcap": false, "node": true, "expr": true, "supernew": true, "laxbreak": true, + "esversion": 9, "white": true, "globals": { "define": true, diff --git a/.testcaferc.json b/.testcaferc.json new file mode 100644 index 000000000..58a061e62 --- /dev/null +++ b/.testcaferc.json @@ -0,0 +1,7 @@ +{ + "speed": 0.4, + "reporter": { + "name": "xunit", + "output": "/tmp/test-results/res.xml" + } +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 71bf61113..25c149014 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,22 +2,25 @@ ### Issue - 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?type=Issues&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. + 1. Try [master](https://github.com/SortableJS/Sortable/tree/master/)-branch, perhaps the problem has been solved; + 2. [Use the search](https://github.com/SortableJS/Sortable/search?type=Issues&q=problem), maybe already have an answer; + 3. If not found, create example on [jsbin.com (draft)](https://jsbin.com/kamiwez/edit?html,js,output) and describe the problem. --- ### Pull Request - 1. Before PR run `grunt`; - 2. Only into [dev](https://github.com/RubaXa/Sortable/tree/dev/)-branch. + 1. Only request to merge with the [master](https://github.com/SortableJS/Sortable/tree/master/)-branch. + 2. Only modify source files, **do not commit the resulting build** ### Setup - Pieced together from [gruntjs](http://gruntjs.com/getting-started) - - 1. Fork repo on [github](https://github.com) + 1. Fork the repo on [github](https://github.com) 2. Clone locally - 3. from local repro ```npm install``` - 4. Install grunt-cli globally ```sudo -H npm install -g grunt-cli``` + 3. Run `npm i` in the local repo + +### Building + + - For development, build the `./Sortable.js` file using the command `npm run build:umd:watch` + - To build everything and minify it, run `npm run build` + - Do not commit the resulting builds in any pull request – they will be generated at release diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100755 index 3ea8e9df7..000000000 --- a/Gruntfile.js +++ /dev/null @@ -1,88 +0,0 @@ -module.exports = function (grunt) { - 'use strict'; - - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - - version: { - js: { - src: ['<%= pkg.exportName %>.js', '*.json'] - }, - cdn: { - options: { - prefix: '(cdnjs\\.cloudflare\\.com\\/ajax\\/libs\\/Sortable|cdn\\.jsdelivr\\.net\\/sortable)\\/', - replace: '[0-9\\.]+' - }, - src: ['README.md'] - } - }, - - jshint: { - all: ['*.js', '!*.min.js'], - - options: { - jshintrc: true - } - }, - - uglify: { - options: { - banner: '/*! <%= pkg.exportName %> <%= pkg.version %> - <%= pkg.license %> | <%= pkg.repository.url %> */\n' - }, - dist: { - files: { - '<%= pkg.exportName %>.min.js': ['<%= pkg.exportName %>.js'] - } - }, - jquery: { - files: {} - } - }, - - jquery: {} - }); - - - grunt.registerTask('jquery', function (exportName, uglify) { - if (exportName == 'min') { - exportName = null; - uglify = 'min'; - } - - if (!exportName) { - exportName = 'sortable'; - } - - var fs = require('fs'), - filename = 'jquery.fn.' + exportName + '.js'; - - grunt.log.oklns(filename); - - fs.writeFileSync( - filename, - (fs.readFileSync('jquery.binding.js') + '') - .replace('$.fn.sortable', '$.fn.' + exportName) - .replace('/* CODE */', - (fs.readFileSync('Sortable.js') + '') - .replace(/^[\s\S]*?function[\s\S]*?(var[\s\S]+)\/\/\s+Export[\s\S]+/, '$1') - ) - ); - - if (uglify) { - var opts = {}; - - opts['jquery.fn.' + exportName + '.min.js'] = filename; - grunt.config.set('uglify.jquery.files', opts); - - grunt.task.run('uglify:jquery'); - } - }); - - - grunt.loadNpmTasks('grunt-version'); - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - - grunt.registerTask('tests', ['jshint']); - grunt.registerTask('default', ['tests', 'version', 'uglify:dist']); -}; diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index c0e68c984..000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ -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/LICENSE b/LICENSE new file mode 100644 index 000000000..91bffc2c9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 All contributors to Sortable + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 785db09d4..c95740711 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -# Sortable -Sortable is a minimalist JavaScript library for reorderable drag-and-drop lists. +# Sortable   [![Financial Contributors on Open Collective](https://opencollective.com/Sortable/all/badge.svg?label=financial+contributors)](https://opencollective.com/Sortable) [![CircleCI](https://circleci.com/gh/SortableJS/Sortable.svg?style=svg)](https://circleci.com/gh/SortableJS/Sortable) [![DeepScan grade](https://deepscan.io/api/teams/3901/projects/5666/branches/43977/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=3901&pid=5666&bid=43977) [![](https://data.jsdelivr.com/v1/package/npm/sortablejs/badge)](https://www.jsdelivr.com/package/npm/sortablejs) [![npm](https://img.shields.io/npm/v/sortablejs.svg)](https://www.npmjs.com/package/sortablejs) -Demo: http://rubaxa.github.io/Sortable/ +Sortable is a JavaScript library for reorderable drag-and-drop lists. +Demo: http://sortablejs.github.io/Sortable/ + +[](https://saucelabs.com/) ## Features @@ -11,22 +13,29 @@ Demo: http://rubaxa.github.io/Sortable/ * CSS animation when moving items * Supports drag handles *and selectable text* (better than voidberg's html5sortable) * Smart auto-scrolling + * Advanced swap detection + * Smooth animations + * [Multi-drag](https://github.com/SortableJS/Sortable/tree/master/plugins/MultiDrag) support + * Support for CSS transforms * Built using native HTML5 drag and drop API * Supports - * [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) - * [Vue](https://github.com/SortableJS/Vue.Draggable) + * [Meteor](https://github.com/SortableJS/meteor-sortablejs) + * Angular + * [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) + * [Vue](https://github.com/SortableJS/Vue.Draggable) + * [Ember](https://github.com/SortableJS/ember-sortablejs) * Supports any CSS library, e.g. [Bootstrap](#bs) * Simple API + * Support for [plugins](#plugins) * [CDN](#cdn) - * No jQuery (but there is [support](#jq)) + * No jQuery required (but there is [support](https://github.com/SortableJS/jquery-sortablejs)) + * Typescript definitions at `@types/sortablejs`
@@ -34,27 +43,54 @@ Demo: http://rubaxa.github.io/Sortable/ ### Articles - * [Sortable v1.0 — New capabilities](https://github.com/RubaXa/Sortable/wiki/Sortable-v1.0-—-New-capabilities/) (December 22, 2014) - * [Sorting with the help of HTML5 Drag'n'Drop API](https://github.com/RubaXa/Sortable/wiki/Sorting-with-the-help-of-HTML5-Drag'n'Drop-API/) (December 23, 2013) - + * [Dragging Multiple Items in Sortable](https://github.com/SortableJS/Sortable/wiki/Dragging-Multiple-Items-in-Sortable) (April 26, 2019) + * [Swap Thresholds and Direction](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction) (December 2, 2018) + * [Sortable v1.0 — New capabilities](https://github.com/SortableJS/Sortable/wiki/Sortable-v1.0-—-New-capabilities/) (December 22, 2014) + * [Sorting with the help of HTML5 Drag'n'Drop API](https://github.com/SortableJS/Sortable/wiki/Sorting-with-the-help-of-HTML5-Drag'n'Drop-API/) (December 23, 2013)
-### Install +### Getting Started -Via npm +Install with NPM: +```bash +npm install sortablejs --save +``` +Install with Bower: ```bash -$ npm install sortablejs --save +bower install --save sortablejs ``` -Via bower: +Import into your project: +```js +// Default SortableJS +import Sortable from 'sortablejs'; -```bash -$ bower install --save sortablejs +// Core SortableJS (without default plugins) +import Sortable from 'sortablejs/modular/sortable.core.esm.js'; + +// Complete SortableJS (with all plugins) +import Sortable from 'sortablejs/modular/sortable.complete.esm.js'; ``` -
+Cherrypick plugins: +```js +// Cherrypick extra plugins +import Sortable, { MultiDrag, Swap } from 'sortablejs'; + +Sortable.mount(new MultiDrag(), new Swap()); + + +// Cherrypick default plugins +import Sortable, { AutoScroll } from 'sortablejs/modular/sortable.core.esm.js'; + +Sortable.mount(new AutoScroll()); +``` + + +--- + ### Usage ```html @@ -70,7 +106,7 @@ var el = document.getElementById('items'); var sortable = Sortable.create(el); ``` -You can use any element for the list and its elements, not just `ul`/`li`. Here is an [example with `div`s](http://jsbin.com/luxero/2/edit?html,js,output). +You can use any element for the list and its elements, not just `ul`/`li`. Here is an [example with `div`s](https://jsbin.com/visimub/edit?html,js,output). --- @@ -79,30 +115,41 @@ You can use any element for the list and its elements, not just `ul`/`li`. Here ### Options ```js var sortable = new Sortable(el, { - group: "name", // or { name: "...", pull: [true, false, clone], put: [true, false, array] } + group: "name", // or { name: "...", pull: [true, false, 'clone', array], put: [true, false, array] } sort: true, // sorting inside list delay: 0, // time in milliseconds to define when the sorting should start + delayOnTouchOnly: false, // only delay if user is using touch + touchStartThreshold: 0, // px, how many pixels the point should move before cancelling a delayed drag event disabled: false, // Disables the sortable if set to true. store: null, // @see Store animation: 150, // ms, animation speed moving items when sorting, `0` — without animation + easing: "cubic-bezier(1, 0, 0, 1)", // Easing for animation. Defaults to null. See https://easings.net/ for examples. handle: ".my-handle", // Drag handle selector within list items filter: ".ignore-elements", // Selectors that do not lead to dragging (String or Function) + preventOnFilter: true, // Call `event.preventDefault()` when triggered `filter` draggable: ".item", // Specifies which items inside the element should be draggable + + dataIdAttr: 'data-id', // HTML attribute that is used by the `toArray()` method + ghostClass: "sortable-ghost", // Class name for the drop placeholder chosenClass: "sortable-chosen", // Class name for the chosen item dragClass: "sortable-drag", // Class name for the dragging item - dataIdAttr: 'data-id', + + swapThreshold: 1, // Threshold of the swap zone + invertSwap: false, // Will always use inverted swap zone if set to true + invertedSwapThreshold: 1, // Threshold of the inverted swap zone (will be set to swapThreshold value by default) + direction: 'horizontal', // Direction of Sortable (will be detected automatically if not given) 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 - fallbackTolerance: 0, // Specify in pixels how far the mouse should move before it's considered as a drag. - - scroll: true, // or HTMLElement - scrollFn: function(offsetX, offsetY, originalEvent) { ... }, // if you have custom scrollbar scrollFn may be used for autoscrolling - scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling. - scrollSpeed: 10, // px + fallbackTolerance: 0, // Specify in pixels how far the mouse should move before it's considered as a drag. + + dragoverBubble: false, + removeCloneOnHide: true, // Remove the clone element when it is not showing, rather than just hiding it + emptyInsertThreshold: 5, // px, distance mouse must be from empty sortable to insert drag element into it + setData: function (/** DataTransfer */dataTransfer, /** HTMLElement*/dragEl) { dataTransfer.setData('Text', dragEl.textContent); // `dataTransfer` object of HTML5 DragEvent @@ -113,6 +160,11 @@ var sortable = new Sortable(el, { evt.oldIndex; // element index within parent }, + // Element is unchosen + onUnchoose: function(/**Event*/evt) { + // same properties as onEnd + }, + // Element dragging started onStart: function (/**Event*/evt) { evt.oldIndex; // element index within parent @@ -120,31 +172,35 @@ var sortable = new Sortable(el, { // Element dragging ended onEnd: function (/**Event*/evt) { - evt.oldIndex; // element's old index within parent - evt.newIndex; // element's new index within parent + var itemEl = evt.item; // dragged HTMLElement + evt.to; // target list + evt.from; // previous list + evt.oldIndex; // element's old index within old parent + evt.newIndex; // element's new index within new parent + evt.oldDraggableIndex; // element's old index within old parent, only counting draggable elements + evt.newDraggableIndex; // element's new index within new parent, only counting draggable elements + evt.clone // the clone element + evt.pullMode; // when item is in another sortable: `"clone"` if cloning, `true` if moving }, // Element is dropped into the list from another list onAdd: function (/**Event*/evt) { - var itemEl = evt.item; // dragged HTMLElement - evt.from; // previous list - // + indexes from onEnd + // same properties as onEnd }, // Changed sorting within list onUpdate: function (/**Event*/evt) { - var itemEl = evt.item; // dragged HTMLElement - // + indexes from onEnd + // same properties as onEnd }, // Called by any change to the list (add / update / remove) onSort: function (/**Event*/evt) { - // same properties as onUpdate + // same properties as onEnd }, // Element is removed from the list into another list onRemove: function (/**Event*/evt) { - // same properties as onUpdate + // same properties as onEnd }, // Attempt to drag a filtered element @@ -154,19 +210,30 @@ var sortable = new Sortable(el, { // Event when you move an item in the list or between lists onMove: function (/**Event*/evt, /**Event*/originalEvent) { - // Example: http://jsbin.com/tuyafe/1/edit?js,output + // Example: https://jsbin.com/nawahef/edit?js,output evt.dragged; // dragged HTMLElement - evt.draggedRect; // TextRectangle {left, top, right и bottom} + evt.draggedRect; // DOMRect {left, top, right, bottom} evt.related; // HTMLElement on which have guided - evt.relatedRect; // TextRectangle + evt.relatedRect; // DOMRect + evt.willInsertAfter; // Boolean that is true if Sortable will insert drag element after target by default originalEvent.clientY; // mouse position // return false; — for cancel + // return -1; — insert before target + // return 1; — insert after target + // return true; — keep default insertion point based on the direction + // return void; — keep default insertion point based on the direction }, - + // Called when creating a clone of element onClone: function (/**Event*/evt) { var origEl = evt.item; var cloneEl = evt.clone; + }, + + // Called when dragging element changes position + onChange: function(/**Event*/evt) { + evt.newIndex // most likely why this event is used is to get the dragging element's current index + // same properties as onEnd } }); ``` @@ -180,21 +247,24 @@ To drag elements from one list into another, both lists must have the same `grou You can also define whether lists can give away, give and keep a copy (`clone`), and receive elements. * name: `String` — group name - * pull: `true|false|'clone'|function` — ability to move from the list. `clone` — copy the item, rather than move. - * put: `true|false|["foo", "bar"]|function` — whether elements can be added from other lists, or an array of group names from which elements can be taken. + * pull: `true|false|["foo", "bar"]|'clone'|function` — ability to move from the list. `clone` — copy the item, rather than move. Or an array of group names which the elements may be put in. Defaults to `true`. + * put: `true|false|["baz", "qux"]|function` — whether elements can be added from other lists, or an array of group names from which elements can be added. + * revertClone: `boolean` — revert cloned element to initial position after moving to a another list. + Demo: - - http://jsbin.com/naduvo/edit?js,output - - http://jsbin.com/rusuvot/edit?js,output — use of complex logic in the `pull` and` put` + - https://jsbin.com/hijetos/edit?js,output + - https://jsbin.com/nacoyah/edit?js,output — use of complex logic in the `pull` and` put` + - https://jsbin.com/bifuyab/edit?js,output — use `revertClone: true` --- #### `sort` option -Sorting inside list. +Allow sorting inside list. -Demo: http://jsbin.com/xizeh/2/edit?html,js,output +Demo: https://jsbin.com/jayedig/edit?js,output --- @@ -202,8 +272,84 @@ Demo: http://jsbin.com/xizeh/2/edit?html,js,output #### `delay` option Time in milliseconds to define when the sorting should start. +Unfortunately, due to browser restrictions, delaying is not possible on IE or Edge with native drag & drop. -Demo: http://jsbin.com/xizeh/4/edit?html,js,output +Demo: https://jsbin.com/zosiwah/edit?js,output + + +--- + + +#### `delayOnTouchOnly` option +Whether or not the delay should be applied only if the user is using touch (eg. on a mobile device). No delay will be applied in any other case. Defaults to `false`. + + +--- + + +#### `swapThreshold` option +Percentage of the target that the swap zone will take up, as a float between `0` and `1`. + +[Read more](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#swap-threshold) + +Demo: http://sortablejs.github.io/Sortable#thresholds + + +--- + + +#### `invertSwap` option +Set to `true` to set the swap zone to the sides of the target, for the effect of sorting "in between" items. + +[Read more](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#forcing-inverted-swap-zone) + +Demo: http://sortablejs.github.io/Sortable#thresholds + + +--- + + +#### `invertedSwapThreshold` option +Percentage of the target that the inverted swap zone will take up, as a float between `0` and `1`. If not given, will default to `swapThreshold`. + +[Read more](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#dealing-with-swap-glitching) + + +--- + + +#### `direction` option +Direction that the Sortable should sort in. Can be set to `'vertical'`, `'horizontal'`, or a function, which will be called whenever a target is dragged over. Must return `'vertical'` or `'horizontal'`. + +[Read more](https://github.com/SortableJS/Sortable/wiki/Swap-Thresholds-and-Direction#direction) + + +Example of direction detection for vertical list that includes full column and half column elements: + +```js +Sortable.create(el, { + direction: function(evt, target, dragEl) { + if (target !== null && target.className.includes('half-column') && dragEl.className.includes('half-column')) { + return 'horizontal'; + } + return 'vertical'; + } +}); +``` + + +--- + + +#### `touchStartThreshold` option +This option is similar to `fallbackTolerance` option. + +When the `delay` option is set, some phones with very sensitive touch displays like the Samsung Galaxy S8 will fire +unwanted touchmove events even when your finger is not moving, resulting in the sort not triggering. + +This option sets the minimum pointer movement that must occur before the delayed sorting is cancelled. + +Values between 3 to 5 are good. --- @@ -212,7 +358,7 @@ Demo: http://jsbin.com/xizeh/4/edit?html,js,output #### `disabled` options Disables the sortable if set to `true`. -Demo: http://jsbin.com/xiloqu/1/edit?html,js,output +Demo: https://jsbin.com/sewokud/edit?js,output ```js var sortable = Sortable.create(list); @@ -233,7 +379,7 @@ To make list items draggable, Sortable disables text selection by the user. That's not always desirable. To allow text selection, define a drag handler, which is an area of every list element that allows it to be dragged around. -Demo: http://jsbin.com/newize/1/edit?html,js,output +Demo: https://jsbin.com/numakuh/edit?html,js,output ```js Sortable.create(el, { @@ -286,7 +432,7 @@ Sortable.create(list, { #### `ghostClass` option Class name for the drop placeholder (default `sortable-ghost`). -Demo: http://jsbin.com/hunifu/1/edit?css,js,output +Demo: https://jsbin.com/henuyiw/edit?css,js,output ```css .ghost { @@ -307,7 +453,7 @@ Sortable.create(list, { #### `chosenClass` option Class name for the chosen item (default `sortable-chosen`). -Demo: http://jsbin.com/hunifu/edit?html,css,js,output +Demo: https://jsbin.com/hoqufox/edit?css,js,output ```css .chosen { @@ -333,7 +479,7 @@ This gives us the possibility to test the behaviour for older Browsers even in n On top of that, the Fallback always generates a copy of that DOM Element and appends the class `fallbackClass` defined in the options. This behaviour controls the look of this 'dragged' Element. -Demo: http://jsbin.com/pucurizace/edit?html,css,js,output +Demo: https://jsbin.com/sibiput/edit?html,css,js,output --- @@ -343,7 +489,7 @@ Demo: http://jsbin.com/pucurizace/edit?html,css,js,output Emulates the native drag threshold. Specify in pixels how far the mouse should move before it's considered as a drag. Useful if the items are also clickable like in a list of links. -When the user clicks inside a sortable element, it's not uncommon for your hand to move a little between the time you press and the time you release. +When the user clicks inside a sortable element, it's not uncommon for your hand to move a little between the time you press and the time you release. Dragging only starts if you move the pointer past a certain tolerance, so that you don't accidentally start dragging every time you click. 3 to 5 are probably good values. @@ -352,62 +498,71 @@ Dragging only starts if you move the pointer past a certain tolerance, so that y --- -#### `scroll` option -If set to `true`, the page (or sortable-area) scrolls when coming to an edge. +#### `dragoverBubble` option +If set to `true`, the dragover event will bubble to parent sortables. Works on both fallback and native dragover event. +By default, it is false, but Sortable will only stop bubbling the event once the element has been inserted into a parent Sortable, or *can* be inserted into a parent Sortable, but isn't at that specific time (due to animation, etc). -Demo: - - `window`: http://jsbin.com/boqugumiqi/1/edit?html,js,output - - `overflow: hidden`: http://jsbin.com/kohamakiwi/1/edit?html,js,output +Since 1.8.0, you will probably want to leave this option as false. Before 1.8.0, it may need to be `true` for nested sortables to work. --- -#### `scrollFn` option -Defines function that will be used for autoscrolling. el.scrollTop/el.scrollLeft is used by default. -Useful when you have custom scrollbar with dedicated scroll function. +#### `removeCloneOnHide` option +If set to `false`, the clone is hidden by having it's CSS `display` property set to `none`. +By default, this option is `true`, meaning Sortable will remove the cloned element from the DOM when it is supposed to be hidden. --- -#### `scrollSensitivity` option -Defines how near the mouse must be to an edge to start scrolling. +#### `emptyInsertThreshold` option +The distance (in pixels) the mouse must be from an empty sortable while dragging for the drag element to be inserted into that sortable. Defaults to `5`. Set to `0` to disable this feature. +Demo: https://jsbin.com/becavoj/edit?js,output ---- +An alternative to this option would be to set a padding on your list when it is empty. +For example: +```css +ul:empty { + padding-bottom: 20px; +} +``` -#### `scrollSpeed` option -The speed at which the window should scroll once the mouse pointer gets within the `scrollSensitivity` distance. +Warning: For `:empty` to work, it must have no node inside (even text one). +Demo: +https://jsbin.com/yunakeg/edit?html,css,js,output --- +### Event object ([demo](https://jsbin.com/fogujiv/edit?js,output)) - -### Event object ([demo](http://jsbin.com/xedusu/edit?js,output)) - - - to:`HTMLElement` — list, in which moved element. + - to:`HTMLElement` — list, in which moved element - from:`HTMLElement` — previous list - item:`HTMLElement` — dragged element - clone:`HTMLElement` - oldIndex:`Number|undefined` — old index within parent - newIndex:`Number|undefined` — new index within parent + - oldDraggableIndex: `Number|undefined` — old index within parent, only counting draggable elements + - newDraggableIndex: `Number|undefined` — new index within parent, only counting draggable elements + - pullMode:`String|Boolean|undefined` — Pull mode if dragging into another sortable (`"clone"`, `true`, or `false`), otherwise undefined #### `move` event object - to:`HTMLElement` - from:`HTMLElement` - dragged:`HTMLElement` - - draggedRect:` TextRectangle` + - draggedRect:`DOMRect` - related:`HTMLElement` — element on which have guided - - relatedRect:` TextRectangle` + - relatedRect:`DOMRect` + - willInsertAfter:`Boolean` — `true` if will element be inserted after target (or `false` if before) --- -### Method +### Methods ##### option(name:`String`[, value:`*`]):`*` @@ -415,7 +570,7 @@ Get or set the option. -##### closest(el:`String`[, selector:`HTMLElement`]):`HTMLElement|null` +##### closest(el:`HTMLElement`[, selector:`String`]):`HTMLElement|null` For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree. @@ -423,12 +578,12 @@ For each element in the set, get the first element that matches the selector by Serializes the sortable's item `data-id`'s (`dataIdAttr` option) into an array of string. -##### sort(order:`String[]`) +##### sort(order:`String[]`, useAnimation:`Boolean`) Sorts the elements according to the array. ```js var order = sortable.toArray(); -sortable.sort(order.reverse()); // apply +sortable.sort(order.reverse(), true); // apply ``` @@ -487,7 +642,7 @@ Sortable.create(el, { ### Bootstrap -Demo: http://jsbin.com/luxero/2/edit?html,js,output +Demo: https://jsbin.com/visimub/edit?html,js,output ```html @@ -495,12 +650,12 @@ Demo: http://jsbin.com/luxero/2/edit?html,js,output - +