diff --git a/README.md b/README.md index 9c27680..4916f5d 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ var sortable = new Sortable(el, { // same properties as onUpdate }, + // Attempt to drag a filtered element onFilter: function (/**Event*/evt) { var itemEl = evt.item; // HTMLElement receiving the `mousedown|tapstart` event. } @@ -135,6 +136,29 @@ You can also define whether lists can give away, give and keep a copy (`clone`), --- +#### `filter` option + + +```js +Sortable.create(list, { + filter: ".js-remove, .js-edit", + onFilter: function (evt) { + var item = el.item; + + if (Sortable.utils.is(evt.target, ".js-remove")) { // Click on remove button + el.parentNode.removeChild(el); // remove sortable item + } + else if (Sortable.utils.is(evt.target, ".js-edit")) { // Click on edit link + // ... + } + } +}) +``` + + +--- + + ### Support AngularJS Include [ng-sortable.js](ng-sortable.js) @@ -183,22 +207,6 @@ Get or set the option. ##### closest(el:`String`[, selector:`HTMLElement`]):`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. -```js -var editableList = new Sortable(list, { - filter: ".js-remove, .js-edit", - onFilter: function (evt) { - var el = editableList.closest(evt.item); // list item - - if (editableList.closest(evt.item, ".js-remove")) { // Click on remove button - el.parentNode.removeChild(el); // remove sortable item - } - else if (editableList.closest(evt.item, ".js-edit")) { // Click on edit link - // ... - } - } -}) -``` - ##### toArray():`String[]` Serializes the sortable's item `data-id`'s into an array of string. diff --git a/Sortable.js b/Sortable.js index 1ab3ef4..201df15 100644 --- a/Sortable.js +++ b/Sortable.js @@ -164,41 +164,46 @@ _onTapStart: function (/**Event|TouchEvent*/evt) { var touch = evt.touches && evt.touches[0], target = (touch || evt).target, + originalTarget = target, options = this.options, el = this.el, filter = options.filter; - // get the index of the dragged element within its parent - startIndex = _index(target); - if (evt.type === 'mousedown' && evt.button !== 0 || options.disabled) { return; // only left button or enabled } + if (options.handle) { + target = _closest(target, options.handle, el); + } + + target = _closest(target, options.draggable, el); + + // get the index of the dragged element within its parent + startIndex = _index(target); + // Check filter if (typeof filter === 'function') { - if (filter.call(this, target, this)) { - _dispatchEvent(el, 'filter', target); + if (filter.call(this, evt, target, this)) { + _dispatchEvent(originalTarget, 'filter', target, el, startIndex); return; // cancel dnd } } else if (filter) { - filter = filter.split(',').filter(function (criteria) { - return _closest(target, criteria.trim(), el); + filter = filter.split(',').some(function (criteria) { + criteria = _closest(originalTarget, criteria.trim(), el); + + if (criteria) { + _dispatchEvent(criteria, 'filter', target, el, startIndex); + return true; + } }); if (filter.length) { - _dispatchEvent(el, 'filter', target); return; // cancel dnd } } - if (options.handle) { - target = _closest(target, options.handle, el); - } - - target = _closest(target, options.draggable, el); - // IE 9 Support if (target && evt.type == 'selectstart') { if (target.tagName != 'A' && target.tagName != 'IMG') { @@ -673,7 +678,7 @@ } - function _closest(el, selector, ctx) { + function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) { if (selector === '*') { return el; } @@ -699,7 +704,7 @@ } - function _globalDragOver(evt) { + function _globalDragOver(/**Event*/evt) { evt.dataTransfer.dropEffect = 'move'; evt.preventDefault(); } @@ -808,11 +813,12 @@ /** * Returns the index of an element within its parent * @param el - * @returns {HTMLElement} + * @returns {number} + * @private */ function _index(/**HTMLElement*/el) { var index = 0; - while ((el = el.previousElementSibling)) { + while (el && (el = el.previousElementSibling)) { index++; } return index; @@ -825,6 +831,9 @@ css: _css, find: _find, bind: _bind, + is: function (el, selector) { + return !!_closest(el, selector, el); + }, closest: _closest, toggleClass: _toggleClass, dispatchEvent: _dispatchEvent, diff --git a/index.html b/index.html index 405d749..ce2590a 100644 --- a/index.html +++ b/index.html @@ -276,7 +276,7 @@ var editableList = new Sortable(editable, { } - new Sortable(foo, { + Sortable.create(foo, { group: "words", animation: 150, store: { @@ -298,7 +298,7 @@ var editableList = new Sortable(editable, { }); - new Sortable(bar, { + Sortable.create(bar, { group: "words", animation: 150, onAdd: function (evt){ console.log('onAdd.bar:', evt.item); }, @@ -309,19 +309,18 @@ var editableList = new Sortable(editable, { }); - new Sortable(multi, { + Sortable.create(multi, { animation: 150, draggable: '.tile', handle: '.tile__name' }); - var editableList = new Sortable(editable, { + var editableList = Sortable.create(editable, { animation: 150, filter: '.js-remove', onFilter: function (evt) { - var el = editableList.closest(evt.item); - el && el.parentNode.removeChild(el); + evt.item.parentNode.removeChild(evt.item); } }); @@ -339,7 +338,7 @@ var editableList = new Sortable(editable, { [].forEach.call(multi.getElementsByClassName('tile__list'), function (el){ - new Sortable(el, { + Sortable.create(el, { group: 'photo', animation: 150 }); @@ -360,14 +359,14 @@ var editableList = new Sortable(editable, { pull: false, put: true }].forEach(function (groupOpts, i) { - new Sortable(document.getElementById('advanced-' + (i + 1)), { + Sortable.create(document.getElementById('advanced-' + (i + 1)), { sort: (i != 1), group: groupOpts, animation: 150 }); }); - new Sortable(document.getElementById('handle-1'), { + Sortable.create(document.getElementById('handle-1'), { handle: '.drag-handle', animation: 150 });