From 070a98e41ca48b0142816644e17f8115e7181446 Mon Sep 17 00:00:00 2001 From: RubaXa Date: Sat, 2 Aug 2014 14:22:16 +0400 Subject: [PATCH] Fixes for #66: Clicking handle makes other non-handle elements draggable --- Sortable.js | 58 ++++++++++++++++++++++++++++--------------------- Sortable.min.js | 2 +- 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/Sortable.js b/Sortable.js index 917bacd..f2a3a65 100644 --- a/Sortable.js +++ b/Sortable.js @@ -77,11 +77,11 @@ options.ghostClass = options.ghostClass || 'sortable-ghost'; options.ignore = options.ignore || 'a, img'; - options.onAdd = _bind(this, options.onAdd || noop); - options.onUpdate = _bind(this, options.onUpdate || noop); - options.onRemove = _bind(this, options.onRemove || noop); - options.onStart = _bind(this, options.onStart || noop); - options.onEnd = _bind(this, options.onEnd || noop); + + // Define events + 'onAdd onUpdate onRemove onStart onEnd'.split(' ').forEach(function (name) { + options[name] = _bind(this, options[name] || noop); + }); // Export group name @@ -149,10 +149,16 @@ if( target && !dragEl && (target.parentNode === el) ){ tapEvt = evt; - target.draggable = true; + + rootEl = this.el; + dragEl = target; + nextEl = dragEl.nextSibling; + activeGroup = this.options.group; + + dragEl.draggable = true; // Disable "draggable" - Array.prototype.forEach.call(options.ignore.split(','), function (criteria) { + options.ignore.split(',').forEach(function (criteria) { _find(target, criteria.trim(), _disableDraggable); }); @@ -163,10 +169,14 @@ , clientX: touch.clientX , clientY: touch.clientY }; + this._onDragStart(tapEvt, true); evt.preventDefault(); } + _on(document, 'mouseup', this._onDrop); + _on(document, 'touchend', this._onDrop); + _on(document, 'touchcancel', this._onDrop); _on(this.el, 'dragstart', this._onDragStart); _on(this.el, 'dragend', this._onDrop); @@ -180,10 +190,12 @@ window.getSelection().removeAllRanges() } } catch (err){ } + + + dragEl.dispatchEvent(_createEvent('start', dragEl)); } }, - _emulateDragOver: function (){ if( touchEvt ){ _css(ghostEl, 'display', 'none'); @@ -241,24 +253,18 @@ _onDragStart: function (evt/**Event*/, isTouch/**Boolean*/){ - var - target = evt.target - , dataTransfer = evt.dataTransfer - ; + var dataTransfer = evt.dataTransfer; - rootEl = this.el; - dragEl = target; - nextEl = target.nextSibling; - activeGroup = this.options.group; + this._offUpEvents(); if( isTouch ){ var - rect = target.getBoundingClientRect() - , css = _css(target) + rect = dragEl.getBoundingClientRect() + , css = _css(dragEl) , ghostRect ; - ghostEl = target.cloneNode(true); + ghostEl = dragEl.cloneNode(true); _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10)); _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10)); @@ -284,12 +290,11 @@ } else { dataTransfer.effectAllowed = 'move'; - dataTransfer.setData('Text', target.textContent); + dataTransfer.setData('Text', dragEl.textContent); _on(document, 'drop', this._onDrop); } - dragEl.dispatchEvent(_createEvent('start', dragEl)); setTimeout(this._applyEffects); }, @@ -342,6 +347,12 @@ } }, + _offUpEvents: function () { + _off(document, 'mouseup', this._onDrop); + _off(document, 'touchmove', this._onTouchMove); + _off(document, 'touchend', this._onDrop); + _off(document, 'touchcancel', this._onDrop); + }, _onDrop: function (evt/**Event*/){ clearInterval(this._loopId); @@ -354,10 +365,7 @@ _off(this.el, 'dragstart', this._onDragStart); _off(this.el, 'selectstart', this._onTapStart); - _off(document, 'touchmove', this._onTouchMove); - _off(document, 'touchend', this._onDrop); - _off(document, 'touchcancel', this._onDrop); - + this._offUpEvents(); if( evt ){ evt.preventDefault(); diff --git a/Sortable.min.js b/Sortable.min.js index 4b4d403..72497ba 100644 --- a/Sortable.min.js +++ b/Sortable.min.js @@ -1,2 +1,2 @@ /*! Sortable 0.4.1 - MIT | git://github.com/rubaxa/Sortable.git */ -!function(a){"use strict";"function"==typeof define&&define.amd?define(a):"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=a():window.Sortable=a()}(function(){"use strict";function a(a,c){this.el=a,this.options=c=c||{},c.group=c.group||Math.random(),c.store=c.store||null,c.handle=c.handle||null,c.draggable=c.draggable||a.children[0]&&a.children[0].nodeName||(/[uo]l/i.test(a.nodeName)?"li":"*"),c.ghostClass=c.ghostClass||"sortable-ghost",c.ignore=c.ignore||"a, img",c.onAdd=b(this,c.onAdd||E),c.onUpdate=b(this,c.onUpdate||E),c.onRemove=b(this,c.onRemove||E),c.onStart=b(this,c.onStart||E),c.onEnd=b(this,c.onEnd||E),a[x]=c.group;for(var d in this)"_"===d.charAt(0)&&(this[d]=b(this,this[d]));e(a,"add",c.onAdd),e(a,"update",c.onUpdate),e(a,"remove",c.onRemove),e(a,"start",c.onStart),e(a,"stop",c.onEnd),e(a,"mousedown",this._onTapStart),e(a,"touchstart",this._onTapStart),B&&e(a,"selectstart",this._onTapStart),e(a,"dragover",this._onDragOver),e(a,"dragenter",this._onDragOver),G.push(this._onDragOver),c.store&&this.sort(c.store.get(this))}function b(a,b){var c=F.call(arguments,2);return b.bind?b.bind.apply(b,[a].concat(c)):function(){return b.apply(a,c.concat(F.call(arguments)))}}function c(a,b,c){if("*"===b)return a;if(a){c=c||z,b=b.split(".");var d=b.shift().toUpperCase(),e=new RegExp("\\s("+b.join("|")+")\\s","g");do if(!(""!==d&&a.nodeName!=d||b.length&&((" "+a.className+" ").match(e)||[]).length!=b.length))return a;while(a!==c&&(a=a.parentNode))}return null}function d(a){a.dataTransfer.dropEffect="move",a.preventDefault()}function e(a,b,c){a.addEventListener(b,c,!1)}function f(a,b,c){a.removeEventListener(b,c,!1)}function g(a,b,c){if(a)if(a.classList)a.classList[c?"add":"remove"](b);else{var d=(" "+a.className+" ").replace(/\s+/g," ").replace(" "+b+" ","");a.className=d+(c?" "+b:"")}}function h(a,b,c){if(a&&a.style){if(void 0===c)return z.defaultView&&z.defaultView.getComputedStyle?c=z.defaultView.getComputedStyle(a,""):a.currentStyle&&(c=a.currentStyle),void 0===b?c:c[b];a.style[b]=c+("string"==typeof c?"":"px")}}function i(a,b,c){if(a){var d=a.getElementsByTagName(b),e=0,f=d.length;if(c)for(;f>e;e++)c(d[e],e);return d}return[]}function j(a){return a.draggable=!1}function k(){C=!1}function l(a,b){var c=a.lastElementChild.getBoundingClientRect();return b.clientY-(c.top+c.height)>5}function m(a){for(var b=a.innerHTML+a.className+a.src,c=b.length,d=0;c--;)d+=b.charCodeAt(c);return d.toString(36)}var n,o,p,q,r,s,t,u,v,w,x="Sortable"+(new Date).getTime(),y=window,z=y.document,A=y.parseInt,B=!!z.createElement("div").dragDrop,C=!1,D=function(a,b){var c=z.createEvent("Event");return c.initEvent(a,!0,!0),c.item=b,c},E=function(){},F=[].slice,G=[];return a.prototype={constructor:a,_applyEffects:function(){g(n,this.options.ghostClass,!0)},_onTapStart:function(a){var b=a.touches&&a.touches[0],f=(b||a).target,g=this.options,h=this.el;if(g.handle&&(f=c(f,g.handle,h)),f=c(f,g.draggable,h),f&&"selectstart"==a.type&&"A"!=f.tagName&&"IMG"!=f.tagName&&f.dragDrop(),f&&!n&&f.parentNode===h){v=a,f.draggable=!0,Array.prototype.forEach.call(g.ignore.split(","),function(a){i(f,a.trim(),j)}),b&&(v={target:f,clientX:b.clientX,clientY:b.clientY},this._onDragStart(v,!0),a.preventDefault()),e(this.el,"dragstart",this._onDragStart),e(this.el,"dragend",this._onDrop),e(z,"dragover",d);try{z.selection?z.selection.empty():window.getSelection().removeAllRanges()}catch(k){}}},_emulateDragOver:function(){if(w){h(o,"display","none");var a=z.elementFromPoint(w.clientX,w.clientY),b=a,c=this.options.group,d=G.length;if(b)do{if(b[x]===c){for(;d--;)G[d]({clientX:w.clientX,clientY:w.clientY,target:a,rootEl:b});break}a=b}while(b=b.parentNode);h(o,"display","")}},_onTouchMove:function(a){if(v){var b=a.touches[0],c=b.clientX-v.clientX,d=b.clientY-v.clientY,e="translate3d("+c+"px,"+d+"px,0)";w=b,h(o,"webkitTransform",e),h(o,"mozTransform",e),h(o,"msTransform",e),h(o,"transform",e),a.preventDefault()}},_onDragStart:function(a,b){var c=a.target,d=a.dataTransfer;if(p=this.el,n=c,q=c.nextSibling,u=this.options.group,b){var f,g=c.getBoundingClientRect(),i=h(c);o=c.cloneNode(!0),h(o,"top",g.top-A(i.marginTop,10)),h(o,"left",g.left-A(i.marginLeft,10)),h(o,"width",g.width),h(o,"height",g.height),h(o,"opacity","0.8"),h(o,"position","fixed"),h(o,"zIndex","100000"),p.appendChild(o),f=o.getBoundingClientRect(),h(o,"width",2*g.width-f.width),h(o,"height",2*g.height-f.height),e(z,"touchmove",this._onTouchMove),e(z,"touchend",this._onDrop),e(z,"touchcancel",this._onDrop),this._loopId=setInterval(this._emulateDragOver,150)}else d.effectAllowed="move",d.setData("Text",c.textContent),e(z,"drop",this._onDrop);n.dispatchEvent(D("start",n)),setTimeout(this._applyEffects)},_onDragOver:function(a){if(!C&&u===this.options.group&&(void 0===a.rootEl||a.rootEl===this.el)){var b=this.el,d=c(a.target,this.options.draggable,b);if(0===b.children.length||b.children[0]===o||b===a.target&&l(b,a))b.appendChild(n);else if(d&&d!==n&&void 0!==d.parentNode[x]){r!==d&&(r=d,s=h(d),t=d.getBoundingClientRect());var e,f=t,g=f.right-f.left,i=f.bottom-f.top,j=/left|right|inline/.test(s.cssFloat+s.display),m=d.offsetWidth>n.offsetWidth,p=d.offsetHeight>n.offsetHeight,q=(j?(a.clientX-f.left)/g:(a.clientY-f.top)/i)>.5,v=d.nextElementSibling;C=!0,setTimeout(k,30),e=j?d.previousElementSibling===n&&!m||q&&m:v!==n&&!p||q&&p,e&&!v?b.appendChild(n):d.parentNode.insertBefore(n,e?v:d)}}},_onDrop:function(a){clearInterval(this._loopId),f(z,"drop",this._onDrop),f(z,"dragover",d),f(this.el,"dragend",this._onDrop),f(this.el,"dragstart",this._onDragStart),f(this.el,"selectstart",this._onTapStart),f(z,"touchmove",this._onTouchMove),f(z,"touchend",this._onDrop),f(z,"touchcancel",this._onDrop),a&&(a.preventDefault(),a.stopPropagation(),o&&o.parentNode.removeChild(o),n&&(j(n),g(n,this.options.ghostClass,!1),p.contains(n)?n.nextSibling!==q&&n.dispatchEvent(D("update",n)):(p.dispatchEvent(D("remove",n)),n.dispatchEvent(D("add",n))),n.dispatchEvent(D("stop",n))),p=n=o=q=v=w=r=s=u=null,this.options.store&&this.options.store.set(this))},toArray:function(){for(var a,b=[],c=this.el.children,d=0,e=c.length;e>d;d++)a=c[d],b.push(a.getAttribute("data-id")||m(a));return b},sort:function(a){var b={},c=this.el;this.toArray().forEach(function(a,d){b[a]=c.children[d]}),a.forEach(function(a){b[a]&&(c.removeChild(b[a]),c.appendChild(b[a]))})},destroy:function(){var a=this.el,b=this.options;f(a,"add",b.onAdd),f(a,"update",b.onUpdate),f(a,"remove",b.onRemove),f(a,"start",b.onStart),f(a,"stop",b.onEnd),f(a,"mousedown",this._onTapStart),f(a,"touchstart",this._onTapStart),f(a,"selectstart",this._onTapStart),f(a,"dragover",this._onDragOver),f(a,"dragenter",this._onDragOver),Array.prototype.forEach.call(a.querySelectorAll("[draggable]"),function(a){a.removeAttribute("draggable")}),G.splice(G.indexOf(this._onDragOver),1),this._onDrop(),this.el=null}},a.utils={on:e,off:f,css:h,find:i,bind:b,closest:c,toggleClass:g},a.version="0.4.1",a}); \ No newline at end of file +!function(a){"use strict";"function"==typeof define&&define.amd?define(a):"undefined"!=typeof module&&"undefined"!=typeof module.exports?module.exports=a():window.Sortable=a()}(function(){"use strict";function a(a,c){this.el=a,this.options=c=c||{},c.group=c.group||Math.random(),c.store=c.store||null,c.handle=c.handle||null,c.draggable=c.draggable||a.children[0]&&a.children[0].nodeName||(/[uo]l/i.test(a.nodeName)?"li":"*"),c.ghostClass=c.ghostClass||"sortable-ghost",c.ignore=c.ignore||"a, img","onAdd onUpdate onRemove onStart onEnd".split(" ").forEach(function(a){c[a]=b(this,c[a]||E)}),a[x]=c.group;for(var d in this)"_"===d.charAt(0)&&(this[d]=b(this,this[d]));e(a,"add",c.onAdd),e(a,"update",c.onUpdate),e(a,"remove",c.onRemove),e(a,"start",c.onStart),e(a,"stop",c.onEnd),e(a,"mousedown",this._onTapStart),e(a,"touchstart",this._onTapStart),B&&e(a,"selectstart",this._onTapStart),e(a,"dragover",this._onDragOver),e(a,"dragenter",this._onDragOver),G.push(this._onDragOver),c.store&&this.sort(c.store.get(this))}function b(a,b){var c=F.call(arguments,2);return b.bind?b.bind.apply(b,[a].concat(c)):function(){return b.apply(a,c.concat(F.call(arguments)))}}function c(a,b,c){if("*"===b)return a;if(a){c=c||z,b=b.split(".");var d=b.shift().toUpperCase(),e=new RegExp("\\s("+b.join("|")+")\\s","g");do if(!(""!==d&&a.nodeName!=d||b.length&&((" "+a.className+" ").match(e)||[]).length!=b.length))return a;while(a!==c&&(a=a.parentNode))}return null}function d(a){a.dataTransfer.dropEffect="move",a.preventDefault()}function e(a,b,c){a.addEventListener(b,c,!1)}function f(a,b,c){a.removeEventListener(b,c,!1)}function g(a,b,c){if(a)if(a.classList)a.classList[c?"add":"remove"](b);else{var d=(" "+a.className+" ").replace(/\s+/g," ").replace(" "+b+" ","");a.className=d+(c?" "+b:"")}}function h(a,b,c){if(a&&a.style){if(void 0===c)return z.defaultView&&z.defaultView.getComputedStyle?c=z.defaultView.getComputedStyle(a,""):a.currentStyle&&(c=a.currentStyle),void 0===b?c:c[b];a.style[b]=c+("string"==typeof c?"":"px")}}function i(a,b,c){if(a){var d=a.getElementsByTagName(b),e=0,f=d.length;if(c)for(;f>e;e++)c(d[e],e);return d}return[]}function j(a){return a.draggable=!1}function k(){C=!1}function l(a,b){var c=a.lastElementChild.getBoundingClientRect();return b.clientY-(c.top+c.height)>5}function m(a){for(var b=a.innerHTML+a.className+a.src,c=b.length,d=0;c--;)d+=b.charCodeAt(c);return d.toString(36)}var n,o,p,q,r,s,t,u,v,w,x="Sortable"+(new Date).getTime(),y=window,z=y.document,A=y.parseInt,B=!!z.createElement("div").dragDrop,C=!1,D=function(a,b){var c=z.createEvent("Event");return c.initEvent(a,!0,!0),c.item=b,c},E=function(){},F=[].slice,G=[];return a.prototype={constructor:a,_applyEffects:function(){g(n,this.options.ghostClass,!0)},_onTapStart:function(a){var b=a.touches&&a.touches[0],f=(b||a).target,g=this.options,h=this.el;if(g.handle&&(f=c(f,g.handle,h)),f=c(f,g.draggable,h),f&&"selectstart"==a.type&&"A"!=f.tagName&&"IMG"!=f.tagName&&f.dragDrop(),f&&!n&&f.parentNode===h){v=a,p=this.el,n=f,q=n.nextSibling,u=this.options.group,n.draggable=!0,g.ignore.split(",").forEach(function(a){i(f,a.trim(),j)}),b&&(v={target:f,clientX:b.clientX,clientY:b.clientY},this._onDragStart(v,!0),a.preventDefault()),e(z,"mouseup",this._onDrop),e(z,"touchend",this._onDrop),e(z,"touchcancel",this._onDrop),e(this.el,"dragstart",this._onDragStart),e(this.el,"dragend",this._onDrop),e(z,"dragover",d);try{z.selection?z.selection.empty():window.getSelection().removeAllRanges()}catch(k){}n.dispatchEvent(D("start",n))}},_emulateDragOver:function(){if(w){h(o,"display","none");var a=z.elementFromPoint(w.clientX,w.clientY),b=a,c=this.options.group,d=G.length;if(b)do{if(b[x]===c){for(;d--;)G[d]({clientX:w.clientX,clientY:w.clientY,target:a,rootEl:b});break}a=b}while(b=b.parentNode);h(o,"display","")}},_onTouchMove:function(a){if(v){var b=a.touches[0],c=b.clientX-v.clientX,d=b.clientY-v.clientY,e="translate3d("+c+"px,"+d+"px,0)";w=b,h(o,"webkitTransform",e),h(o,"mozTransform",e),h(o,"msTransform",e),h(o,"transform",e),a.preventDefault()}},_onDragStart:function(a,b){var c=a.dataTransfer;if(this._offUpEvents(),b){var d,f=n.getBoundingClientRect(),g=h(n);o=n.cloneNode(!0),h(o,"top",f.top-A(g.marginTop,10)),h(o,"left",f.left-A(g.marginLeft,10)),h(o,"width",f.width),h(o,"height",f.height),h(o,"opacity","0.8"),h(o,"position","fixed"),h(o,"zIndex","100000"),p.appendChild(o),d=o.getBoundingClientRect(),h(o,"width",2*f.width-d.width),h(o,"height",2*f.height-d.height),e(z,"touchmove",this._onTouchMove),e(z,"touchend",this._onDrop),e(z,"touchcancel",this._onDrop),this._loopId=setInterval(this._emulateDragOver,150)}else c.effectAllowed="move",c.setData("Text",n.textContent),e(z,"drop",this._onDrop);setTimeout(this._applyEffects)},_onDragOver:function(a){if(!C&&u===this.options.group&&(void 0===a.rootEl||a.rootEl===this.el)){var b=this.el,d=c(a.target,this.options.draggable,b);if(0===b.children.length||b.children[0]===o||b===a.target&&l(b,a))b.appendChild(n);else if(d&&d!==n&&void 0!==d.parentNode[x]){r!==d&&(r=d,s=h(d),t=d.getBoundingClientRect());var e,f=t,g=f.right-f.left,i=f.bottom-f.top,j=/left|right|inline/.test(s.cssFloat+s.display),m=d.offsetWidth>n.offsetWidth,p=d.offsetHeight>n.offsetHeight,q=(j?(a.clientX-f.left)/g:(a.clientY-f.top)/i)>.5,v=d.nextElementSibling;C=!0,setTimeout(k,30),e=j?d.previousElementSibling===n&&!m||q&&m:v!==n&&!p||q&&p,e&&!v?b.appendChild(n):d.parentNode.insertBefore(n,e?v:d)}}},_offUpEvents:function(){f(z,"mouseup",this._onDrop),f(z,"touchmove",this._onTouchMove),f(z,"touchend",this._onDrop),f(z,"touchcancel",this._onDrop)},_onDrop:function(a){clearInterval(this._loopId),f(z,"drop",this._onDrop),f(z,"dragover",d),f(this.el,"dragend",this._onDrop),f(this.el,"dragstart",this._onDragStart),f(this.el,"selectstart",this._onTapStart),this._offUpEvents(),a&&(a.preventDefault(),a.stopPropagation(),o&&o.parentNode.removeChild(o),n&&(j(n),g(n,this.options.ghostClass,!1),p.contains(n)?n.nextSibling!==q&&n.dispatchEvent(D("update",n)):(p.dispatchEvent(D("remove",n)),n.dispatchEvent(D("add",n))),n.dispatchEvent(D("stop",n))),p=n=o=q=v=w=r=s=u=null,this.options.store&&this.options.store.set(this))},toArray:function(){for(var a,b=[],c=this.el.children,d=0,e=c.length;e>d;d++)a=c[d],b.push(a.getAttribute("data-id")||m(a));return b},sort:function(a){var b={},c=this.el;this.toArray().forEach(function(a,d){b[a]=c.children[d]}),a.forEach(function(a){b[a]&&(c.removeChild(b[a]),c.appendChild(b[a]))})},destroy:function(){var a=this.el,b=this.options;f(a,"add",b.onAdd),f(a,"update",b.onUpdate),f(a,"remove",b.onRemove),f(a,"start",b.onStart),f(a,"stop",b.onEnd),f(a,"mousedown",this._onTapStart),f(a,"touchstart",this._onTapStart),f(a,"selectstart",this._onTapStart),f(a,"dragover",this._onDragOver),f(a,"dragenter",this._onDragOver),Array.prototype.forEach.call(a.querySelectorAll("[draggable]"),function(a){a.removeAttribute("draggable")}),G.splice(G.indexOf(this._onDragOver),1),this._onDrop(),this.el=null}},a.utils={on:e,off:f,css:h,find:i,bind:b,closest:c,toggleClass:g},a.version="0.4.1",a}); \ No newline at end of file