From 81748a58284d5825ad0779e51bb402072104cee0 Mon Sep 17 00:00:00 2001 From: Dan Dascalescu Date: Mon, 8 Dec 2014 00:10:56 -0800 Subject: [PATCH 1/2] Determine the correct target before onFilter Fix #156 and also returning correct indexes if a drag handle is present (#154). --- README.md | 7 ++++--- Sortable.js | 30 ++++++++++++++++-------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 9c27680..cb315c4 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. } @@ -187,12 +188,12 @@ For each element in the set, get the first element that matches the selector by var editableList = new Sortable(list, { filter: ".js-remove, .js-edit", onFilter: function (evt) { - var el = editableList.closest(evt.item); // list item + var el = editableList.closest(evt.target); // list item - if (editableList.closest(evt.item, ".js-remove")) { // Click on remove button + 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 + else if (editableList.closest(evt.item, ".js-edit")) { // Click on edit link // ... } } diff --git a/Sortable.js b/Sortable.js index f4f30d4..05cbf62 100644 --- a/Sortable.js +++ b/Sortable.js @@ -162,21 +162,28 @@ _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); + _dispatchEvent(el, 'filter', target, undefined, startIndex); return; // cancel dnd } } @@ -186,17 +193,11 @@ }); if (filter.length) { - _dispatchEvent(el, 'filter', target); + _dispatchEvent(originalTarget, 'filter', target, undefined, startIndex); 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') { @@ -695,7 +696,7 @@ } - function _globalDragOver(evt) { + function _globalDragOver(/**Event*/evt) { evt.dataTransfer.dropEffect = 'move'; evt.preventDefault(); } @@ -804,11 +805,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; From 846007e23796c65d5723045c61c181c0f55a5e09 Mon Sep 17 00:00:00 2001 From: RubaXa Date: Tue, 9 Dec 2014 00:35:01 +0300 Subject: [PATCH 2/2] #156: * filter-method --- README.md | 39 +++++++++++++++++++++++---------------- Sortable.js | 19 +++++++++++++------ index.html | 17 ++++++++--------- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index cb315c4..4916f5d 100644 --- a/README.md +++ b/README.md @@ -136,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) @@ -184,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.target); // 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 05cbf62..ef3637e 100644 --- a/Sortable.js +++ b/Sortable.js @@ -182,18 +182,22 @@ // Check filter if (typeof filter === 'function') { - if (filter.call(this, target, this)) { - _dispatchEvent(el, 'filter', target, undefined, startIndex); + 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(originalTarget, 'filter', target, undefined, startIndex); return; // cancel dnd } } @@ -670,7 +674,7 @@ } - function _closest(el, selector, ctx) { + function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) { if (selector === '*') { return el; } @@ -823,6 +827,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 c1dff70..dd52430 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: { @@ -297,7 +297,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); }, @@ -308,19 +308,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); } }); @@ -338,7 +337,7 @@ var editableList = new Sortable(editable, { [].forEach.call(multi.getElementsByClassName('tile__list'), function (el){ - new Sortable(el, { + Sortable.create(el, { group: 'photo', animation: 150 }); @@ -359,14 +358,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 });