diff --git a/src/angular-sortable-view.js b/src/angular-sortable-view.js index ff0241c..b4270f7 100644 --- a/src/angular-sortable-view.js +++ b/src/angular-sortable-view.js @@ -22,6 +22,8 @@ } var sortingInProgress; + var isDisabled = false; + var ROOTS_MAP = Object.create(null); // window.ROOTS_MAP = ROOTS_MAP; // for debug purposes @@ -56,6 +58,16 @@ return sortingInProgress; }; + if ($attrs.svDisabled) { + $scope.$watch($attrs.svDisabled, function(disabled) { + isDisabled = disabled === true; + }); + } + + this.isDisabled = function() { + return isDisabled; + }; + if($attrs.svGrid){ // sv-grid determined explicite isGrid = $attrs.svGrid === "true" ? true : $attrs.svGrid === "false" ? false : null; if(isGrid === null) @@ -353,12 +365,14 @@ return $scope.$index; } }; + var handle = $element; + $controllers[1].addToSortableElements(sortableElement); $scope.$on('$destroy', function(){ $controllers[1].removeFromSortableElements(sortableElement); + handle.off('mousedown touchstart', onMousedown); }); - var handle = $element; handle.on('mousedown touchstart', onMousedown); $scope.$watch('$ctrl.handle', function(customHandle){ if(customHandle){ @@ -390,7 +404,7 @@ function onMousedown(e){ touchFix(e); - if($controllers[1].sortingInProgress()) return; + if($controllers[1].isDisabled() || $controllers[1].sortingInProgress()) return; if(e.button != 0 && e.type === 'mousedown') return; moveExecuted = false; @@ -406,6 +420,7 @@ var target = $element; var clientRect = $element[0].getBoundingClientRect(); + var parentRect = getPositionedParentRect($element[0]); var clone; if(!helper) helper = $controllers[0].helper; @@ -444,6 +459,11 @@ targetLeft = containmentRect.left + body.scrollLeft; if(targetLeft + helperRect.width > containmentRect.left + body.scrollLeft + containmentRect.width) // right boundary targetLeft = containmentRect.left + body.scrollLeft + containmentRect.width - helperRect.width; + + if (parentRect) { + targetLeft -= parentRect.left; + targetTop -= parentRect.top; + } } this.style.left = targetLeft - body.scrollLeft + 'px'; this.style.top = targetTop - body.scrollTop + 'px'; @@ -465,19 +485,33 @@ }); // onMousemove(e); - function onMousemove(e){ - touchFix(e); + function onMousemove(moveEv){ + touchFix(moveEv); + var jiggle = Math.abs(moveEv.clientY - e.clientY) + + Math.abs(moveEv.clientX - e.clientX); + if (jiggle < 10) return; if(!moveExecuted){ $element.parent().prepend(clone); moveExecuted = true; } + $controllers[1].$moveUpdate(opts, { - x: e.clientX, - y: e.clientY, + x: moveEv.clientX, + y: moveEv.clientY, offset: pointerOffset }, clone, $element, placeholder, $controllers[0].getPart(), $scope.$index); } } + + function getPositionedParentRect(el) { + while (el !== document.documentElement) { + el = el.parentNode; + var cssPos = window.getComputedStyle(el, null).position; + if (cssPos != '' && cssPos != 'static') { + return el.getBoundingClientRect(); + } + } + } } }; }]); diff --git a/src/angular-sortable-view.min.js b/src/angular-sortable-view.min.js index 549a37c..780168e 100644 --- a/src/angular-sortable-view.min.js +++ b/src/angular-sortable-view.min.js @@ -2,4 +2,4 @@ Copyright Kamil Pękala http://github.com/kamilkp angular-sortable-view v0.0.13 2015/01/13 */ -!function(a,b){"use strict";function c(a){if(!("clientX"in a||"clientY"in a)){var b=a.touches||a.originalEvent.touches;b&&b.length&&(a.clientX=b[0].clientX,a.clientY=b[0].clientY),a.preventDefault()}}function d(a){if(a=a[0],a.previousElementSibling)return b.element(a.previousElementSibling);for(var c=a.previousSibling;null!=c&&1!=c.nodeType;)c=c.previousSibling;return b.element(c)}function e(a,b){var c=d(a);c.length>0?c.after(b):a.parent().prepend(b)}function f(a,c){return a instanceof b.element&&(a=a[0]),null!==i?a[i](c):void 0}var g=b.module("angular-sortable-view",[]);g.directive("svRoot",[function(){function a(a,b,c){return c?a.x-b.x<0:a.y-b.y<0}function b(a){return g[a]}function c(a){delete g[a]}var d,g=Object.create(null);return{restrict:"A",controller:["$scope","$attrs","$interpolate","$parse",function(h,i,j,k){var l=j(i.svRoot)(h)||h.$id;g[l]||(g[l]=[]);var m,n,o,p,q,r,s=!1,t=k(i.svOnSort);i.svOnStart=i.$$element[0].attributes["sv-on-start"],i.svOnStart=i.svOnStart&&i.svOnStart.value,i.svOnStop=i.$$element[0].attributes["sv-on-stop"],i.svOnStop=i.svOnStop&&i.svOnStop.value;var u=k(i.svOnStart),v=k(i.svOnStop);if(this.sortingInProgress=function(){return d},i.svGrid){if(s="true"===i.svGrid?!0:"false"===i.svGrid?!1:null,null===s)throw"Invalid value of sv-grid attribute"}else h.$watchCollection(function(){return b(l)},function(a){s=!1;var b=a.filter(function(a){return!a.container}).map(function(a){return{part:a.getPart().id,y:a.element[0].getBoundingClientRect().top}}),c=Object.create(null);b.forEach(function(a){c[a.part]?c[a.part].push(a.y):c[a.part]=[a.y]}),Object.keys(c).forEach(function(a){c[a].sort(),c[a].forEach(function(b,d){d0&&b===c[a][d+1]&&(s=!0)})})});this.$moveUpdate=function(c,g,i,j,k,t,v){var w=i[0].getBoundingClientRect();"element"===c.tolerance&&(g={x:~~(w.left+w.width/2),y:~~(w.top+w.height/2)}),d=!0,m=[],n||(k?(n=k.clone(),n.removeClass("ng-hide")):(n=j.clone(),n.addClass("sv-visibility-hidden"),n.addClass("sv-placeholder"),n.css({height:w.height+"px",width:w.width+"px"})),j.after(n),j.addClass("ng-hide"),q=j,o=c,p=i,u(h,{$helper:{element:p},$part:t.model(t.scope),$index:v,$item:t.model(t.scope)[v]}),h.$root&&h.$root.$$phase||h.$apply()),p[0].reposition({x:g.x+document.body.scrollLeft-g.offset.x*w.width,y:g.y+document.body.scrollTop-g.offset.y*w.height}),b(l).forEach(function(b){if(null==c.containment||f(b.element,c.containment)||f(b.element,c.containment+" *")){var d=b.element[0].getBoundingClientRect(),e={x:~~(d.left+d.width/2),y:~~(d.top+d.height/2)};b.container||!b.element[0].scrollHeight&&!b.element[0].scrollWidth||m.push({element:b.element,q:(e.x-g.x)*(e.x-g.x)+(e.y-g.y)*(e.y-g.y),view:b.getPart(),targetIndex:b.getIndex(),after:a(e,g,s)}),b.container&&!b.element[0].querySelector("[sv-element]:not(.sv-placeholder):not(.sv-source)")&&m.push({element:b.element,q:(e.x-g.x)*(e.x-g.x)+(e.y-g.y)*(e.y-g.y),view:b.getPart(),targetIndex:0,container:!0})}});var x=n[0].getBoundingClientRect(),y={x:~~(x.left+x.width/2),y:~~(x.top+x.height/2)};m.push({q:(y.x-g.x)*(y.x-g.x)+(y.y-g.y)*(y.y-g.y),element:n,placeholder:!0}),m.sort(function(a,b){return a.q-b.q}),m.forEach(function(a,b){0!==b||a.placeholder||a.container?0===b&&a.container?(r=a,a.element.append(n)):a.element.removeClass("sv-candidate"):(r=a,a.element.addClass("sv-candidate"),a.after?a.element.after(n):e(a.element,n))})},this.$drop=function(a,b,c){function e(){if(d=!1,n.remove(),p.remove(),q.removeClass("ng-hide"),m=void 0,n=void 0,c=void 0,p=void 0,q=void 0,v(h,{$part:a.model(a.scope),$index:b,$item:a.model(a.scope)[b]}),r){r.element.removeClass("sv-candidate");var e=a.model(a.scope).splice(b,1),f=r.targetIndex;r.view===a&&r.targetIndex>b&&f--,r.after&&f++,r.view.model(r.view.scope).splice(f,0,e[0]),(r.view!==a||b!==f)&&t(h,{$partTo:r.view.model(r.view.scope),$partFrom:a.model(a.scope),$item:e[0],$indexTo:f,$indexFrom:b})}r=void 0,h.$root&&h.$root.$$phase||h.$apply()}if(n)if(c.revert){var f=n[0].getBoundingClientRect(),g=p[0].getBoundingClientRect(),i=Math.sqrt(Math.pow(g.top-f.top,2)+Math.pow(g.left-f.left,2)),j=+c.revert*i/200;j=Math.min(j,+c.revert),["-webkit-","-moz-","-ms-","-o-",""].forEach(function(a){"undefined"!=typeof p[0].style[a+"transition"]&&(p[0].style[a+"transition"]="all "+j+"ms ease")}),setTimeout(e,j),p.css({top:f.top+document.body.scrollTop+"px",left:f.left+document.body.scrollLeft+"px"})}else e()},this.addToSortableElements=function(a){b(l).push(a)},this.removeFromSortableElements=function(a){var d=b(l),e=d.indexOf(a);e>-1&&(d.splice(e,1),0===d.length&&c(l))}}]}}]),g.directive("svPart",["$parse",function(a){return{restrict:"A",require:"^svRoot",controller:["$scope",function(a){a.$ctrl=this,this.getPart=function(){return a.part},this.$drop=function(b,c){a.$sortableRoot.$drop(a.part,b,c)}}],scope:!0,link:function(b,c,d,e){if(!d.svPart)throw new Error("no model provided");var f=a(d.svPart);if(!f.assign)throw new Error("model not assignable");b.part={id:b.$id,element:c,model:f,scope:b},b.$sortableRoot=e;var g={element:c,getPart:b.$ctrl.getPart,container:!0};e.addToSortableElements(g),b.$on("$destroy",function(){e.removeFromSortableElements(g)})}}}]),g.directive("svElement",["$parse",function(a){return{restrict:"A",require:["^svPart","^svRoot"],controller:["$scope",function(a){a.$ctrl=this}],link:function(d,e,f,g){function h(h){function i(a){c(a),n||(e.parent().prepend(q),n=!0),g[1].$moveUpdate(k,{x:a.clientX,y:a.clientY,offset:t},q,e,m,g[0].getPart(),d.$index)}if(c(h),!g[1].sortingInProgress()&&(0==h.button||"mousedown"!==h.type)){n=!1;var k=a(f.svElement)(d);if(k=b.extend({},{tolerance:"pointer",revert:200,containment:"html"},k),k.containment)var p=j.call(e,k.containment)[0].getBoundingClientRect();var q,r=e,s=e[0].getBoundingClientRect();l||(l=g[0].helper),m||(m=g[0].placeholder),l?(q=l.clone(),q.removeClass("ng-hide"),q.css({left:s.left+document.body.scrollLeft+"px",top:s.top+document.body.scrollTop+"px"}),r.addClass("sv-visibility-hidden")):(q=r.clone(),q.addClass("sv-helper").css({left:s.left+document.body.scrollLeft+"px",top:s.top+document.body.scrollTop+"px",width:s.width+"px"})),q[0].reposition=function(a){var b=a.x,c=a.y,d=q[0].getBoundingClientRect(),e=document.body;p&&(cp.top+e.scrollTop+p.height&&(c=p.top+e.scrollTop+p.height-d.height),bp.left+e.scrollLeft+p.width&&(b=p.left+e.scrollLeft+p.width-d.width)),this.style.left=b-e.scrollLeft+"px",this.style.top=c-e.scrollTop+"px"};var t={x:(h.clientX-s.left)/s.width,y:(h.clientY-s.top)/s.height};o.addClass("sv-sorting-in-progress"),o.on("mousemove touchmove",i).on("mouseup touchend touchcancel",function u(){o.off("mousemove touchmove",i),o.off("mouseup touchend touchcancel",u),o.removeClass("sv-sorting-in-progress"),n&&g[0].$drop(d.$index,k),e.removeClass("sv-visibility-hidden")})}}var i={element:e,getPart:g[0].getPart,getIndex:function(){return d.$index}};g[1].addToSortableElements(i),d.$on("$destroy",function(){g[1].removeFromSortableElements(i)});var k=e;k.on("mousedown touchstart",h),d.$watch("$ctrl.handle",function(a){a&&(k.off("mousedown touchstart",h),k=a,k.on("mousedown touchstart",h))});var l;d.$watch("$ctrl.helper",function(a){a&&(l=a)});var m;d.$watch("$ctrl.placeholder",function(a){a&&(m=a)});var n,o=(b.element(document.body),b.element(document.documentElement))}}}]),g.directive("svHandle",function(){return{require:"?^svElement",link:function(a,b,c,d){d&&(d.handle=b.add(d.handle))}}}),g.directive("svHelper",function(){return{require:["?^svPart","?^svElement"],link:function(a,b,c,d){b.addClass("sv-helper").addClass("ng-hide"),d[1]?d[1].helper=b:d[0]&&(d[0].helper=b)}}}),g.directive("svPlaceholder",function(){return{require:["?^svPart","?^svElement"],link:function(a,b,c,d){b.addClass("sv-placeholder").addClass("ng-hide"),d[1]?d[1].placeholder=b:d[0]&&(d[0].placeholder=b)}}}),b.element(document.head).append([""].join(""));var h=document.documentElement,i=h.matches?"matches":h.matchesSelector?"matchesSelector":h.webkitMatches?"webkitMatches":h.webkitMatchesSelector?"webkitMatchesSelector":h.msMatches?"msMatches":h.msMatchesSelector?"msMatchesSelector":h.mozMatches?"mozMatches":h.mozMatchesSelector?"mozMatchesSelector":null;if(null==i)throw"This browser doesn't support the HTMLElement.matches method";var j=b.element.prototype.closest||function(a){for(var c=this[0].parentNode;c!==document.documentElement&&!c[i](a);)c=c.parentNode;return c[i](a)?b.element(c):b.element()};"function"!=typeof b.element.prototype.add&&(b.element.prototype.add=function(a){var c,d=b.element();for(a=b.element(a),c=0;c0?c.after(b):a.parent().prepend(b)}function f(a,c){if(a instanceof b.element&&(a=a[0]),null!==i)return a[i](c)}var g=b.module("angular-sortable-view",[]);g.directive("svRoot",[function(){function a(a,b,c){return c?a.x-b.x<0:a.y-b.y<0}function b(a){return h[a]}function c(a){delete h[a]}var d,g=!1,h=Object.create(null);return{restrict:"A",controller:["$scope","$attrs","$interpolate","$parse",function(i,j,k,l){var m=k(j.svRoot)(i)||i.$id;h[m]||(h[m]=[]);var n,o,p,q,r,s,t=!1,u=l(j.svOnSort);j.svOnStart=j.$$element[0].attributes["sv-on-start"],j.svOnStart=j.svOnStart&&j.svOnStart.value,j.svOnStop=j.$$element[0].attributes["sv-on-stop"],j.svOnStop=j.svOnStop&&j.svOnStop.value;var v=l(j.svOnStart),w=l(j.svOnStop);if(this.sortingInProgress=function(){return d},j.svDisabled&&i.$watch(j.svDisabled,function(a){g=a===!0}),this.isDisabled=function(){return g},j.svGrid){if(t="true"===j.svGrid||"false"!==j.svGrid&&null,null===t)throw"Invalid value of sv-grid attribute"}else i.$watchCollection(function(){return b(m)},function(a){t=!1;var b=a.filter(function(a){return!a.container}).map(function(a){return{part:a.getPart().id,y:a.element[0].getBoundingClientRect().top}}),c=Object.create(null);b.forEach(function(a){c[a.part]?c[a.part].push(a.y):c[a.part]=[a.y]}),Object.keys(c).forEach(function(a){c[a].sort(),c[a].forEach(function(b,d){d0&&b===c[a][d+1]&&(t=!0)})})});this.$moveUpdate=function(c,g,h,j,k,l,u){var w=h[0].getBoundingClientRect();"element"===c.tolerance&&(g={x:~~(w.left+w.width/2),y:~~(w.top+w.height/2)}),d=!0,n=[],o||(k?(o=k.clone(),o.removeClass("ng-hide")):(o=j.clone(),o.addClass("sv-visibility-hidden"),o.addClass("sv-placeholder"),o.css({height:w.height+"px",width:w.width+"px"})),j.after(o),j.addClass("ng-hide"),r=j,p=c,q=h,v(i,{$helper:{element:q},$part:l.model(l.scope),$index:u,$item:l.model(l.scope)[u]}),i.$root&&i.$root.$$phase||i.$apply()),q[0].reposition({x:g.x+document.body.scrollLeft-g.offset.x*w.width,y:g.y+document.body.scrollTop-g.offset.y*w.height}),b(m).forEach(function(b,d){if(null==c.containment||f(b.element,c.containment)||f(b.element,c.containment+" *")){var e=b.element[0].getBoundingClientRect(),h={x:~~(e.left+e.width/2),y:~~(e.top+e.height/2)};b.container||!b.element[0].scrollHeight&&!b.element[0].scrollWidth||n.push({element:b.element,q:(h.x-g.x)*(h.x-g.x)+(h.y-g.y)*(h.y-g.y),view:b.getPart(),targetIndex:b.getIndex(),after:a(h,g,t)}),b.container&&!b.element[0].querySelector("[sv-element]:not(.sv-placeholder):not(.sv-source)")&&n.push({element:b.element,q:(h.x-g.x)*(h.x-g.x)+(h.y-g.y)*(h.y-g.y),view:b.getPart(),targetIndex:0,container:!0})}});var x=o[0].getBoundingClientRect(),y={x:~~(x.left+x.width/2),y:~~(x.top+x.height/2)};n.push({q:(y.x-g.x)*(y.x-g.x)+(y.y-g.y)*(y.y-g.y),element:o,placeholder:!0}),n.sort(function(a,b){return a.q-b.q}),n.forEach(function(a,b){0!==b||a.placeholder||a.container?0===b&&a.container?(s=a,a.element.append(o)):a.element.removeClass("sv-candidate"):(s=a,a.element.addClass("sv-candidate"),a.after?a.element.after(o):e(a.element,o))})},this.$drop=function(a,b,c){function e(){if(d=!1,o.remove(),q.remove(),r.removeClass("ng-hide"),n=void 0,o=void 0,c=void 0,q=void 0,r=void 0,w(i,{$part:a.model(a.scope),$index:b,$item:a.model(a.scope)[b]}),s){s.element.removeClass("sv-candidate");var e=a.model(a.scope).splice(b,1),f=s.targetIndex;s.view===a&&s.targetIndex>b&&f--,s.after&&f++,s.view.model(s.view.scope).splice(f,0,e[0]),s.view===a&&b===f||u(i,{$partTo:s.view.model(s.view.scope),$partFrom:a.model(a.scope),$item:e[0],$indexTo:f,$indexFrom:b})}s=void 0,i.$root&&i.$root.$$phase||i.$apply()}if(o)if(c.revert){var f=o[0].getBoundingClientRect(),g=q[0].getBoundingClientRect(),h=Math.sqrt(Math.pow(g.top-f.top,2)+Math.pow(g.left-f.left,2)),j=+c.revert*h/200;j=Math.min(j,+c.revert),["-webkit-","-moz-","-ms-","-o-",""].forEach(function(a){"undefined"!=typeof q[0].style[a+"transition"]&&(q[0].style[a+"transition"]="all "+j+"ms ease")}),setTimeout(e,j),q.css({top:f.top+document.body.scrollTop+"px",left:f.left+document.body.scrollLeft+"px"})}else e()},this.addToSortableElements=function(a){b(m).push(a)},this.removeFromSortableElements=function(a){var d=b(m),e=d.indexOf(a);e>-1&&(d.splice(e,1),0===d.length&&c(m))}}]}}]),g.directive("svPart",["$parse",function(a){return{restrict:"A",require:"^svRoot",controller:["$scope",function(a){a.$ctrl=this,this.getPart=function(){return a.part},this.$drop=function(b,c){a.$sortableRoot.$drop(a.part,b,c)}}],scope:!0,link:function(b,c,d,e){if(!d.svPart)throw new Error("no model provided");var f=a(d.svPart);if(!f.assign)throw new Error("model not assignable");b.part={id:b.$id,element:c,model:f,scope:b},b.$sortableRoot=e;var g={element:c,getPart:b.$ctrl.getPart,container:!0};e.addToSortableElements(g),b.$on("$destroy",function(){e.removeFromSortableElements(g)})}}}]),g.directive("svElement",["$parse",function(d){return{restrict:"A",require:["^svPart","^svRoot"],controller:["$scope",function(a){a.$ctrl=this}],link:function(e,f,g,h){function i(a){function i(b){c(b);var d=Math.abs(b.clientY-a.clientY)+Math.abs(b.clientX-a.clientX);d<10||(p||(f.parent().prepend(r),p=!0),h[1].$moveUpdate(l,{x:b.clientX,y:b.clientY,offset:v},r,f,o,h[0].getPart(),e.$index))}if(c(a),!(h[1].isDisabled()||h[1].sortingInProgress()||0!=a.button&&"mousedown"===a.type)){p=!1;var l=d(g.svElement)(e);if(l=b.extend({},{tolerance:"pointer",revert:200,containment:"html"},l),l.containment)var m=j.call(f,l.containment)[0].getBoundingClientRect();var r,s=f,t=f[0].getBoundingClientRect(),u=k(f[0]);n||(n=h[0].helper),o||(o=h[0].placeholder),n?(r=n.clone(),r.removeClass("ng-hide"),r.css({left:t.left+document.body.scrollLeft+"px",top:t.top+document.body.scrollTop+"px"}),s.addClass("sv-visibility-hidden")):(r=s.clone(),r.addClass("sv-helper").css({left:t.left+document.body.scrollLeft+"px",top:t.top+document.body.scrollTop+"px",width:t.width+"px"})),r[0].reposition=function(a){var b=a.x,c=a.y,d=r[0].getBoundingClientRect(),e=document.body;m&&(cm.top+e.scrollTop+m.height&&(c=m.top+e.scrollTop+m.height-d.height),bm.left+e.scrollLeft+m.width&&(b=m.left+e.scrollLeft+m.width-d.width),u&&(b-=u.left,c-=u.top)),this.style.left=b-e.scrollLeft+"px",this.style.top=c-e.scrollTop+"px"};var v={x:(a.clientX-t.left)/t.width,y:(a.clientY-t.top)/t.height};q.addClass("sv-sorting-in-progress"),q.on("mousemove touchmove",i).on("mouseup touchend touchcancel",function a(b){q.off("mousemove touchmove",i),q.off("mouseup touchend touchcancel",a),q.removeClass("sv-sorting-in-progress"),p&&h[0].$drop(e.$index,l),f.removeClass("sv-visibility-hidden")})}}function k(b){for(;b!==document.documentElement;){b=b.parentNode;var c=a.getComputedStyle(b,null).position;if(""!=c&&"static"!=c)return b.getBoundingClientRect()}}var l={element:f,getPart:h[0].getPart,getIndex:function(){return e.$index}},m=f;h[1].addToSortableElements(l),e.$on("$destroy",function(){h[1].removeFromSortableElements(l),m.off("mousedown touchstart",i)}),m.on("mousedown touchstart",i),e.$watch("$ctrl.handle",function(a){a&&(m.off("mousedown touchstart",i),m=a,m.on("mousedown touchstart",i))});var n;e.$watch("$ctrl.helper",function(a){a&&(n=a)});var o;e.$watch("$ctrl.placeholder",function(a){a&&(o=a)});var p,q=(b.element(document.body),b.element(document.documentElement))}}}]),g.directive("svHandle",function(){return{require:"?^svElement",link:function(a,b,c,d){d&&(d.handle=b.add(d.handle))}}}),g.directive("svHelper",function(){return{require:["?^svPart","?^svElement"],link:function(a,b,c,d){b.addClass("sv-helper").addClass("ng-hide"),d[1]?d[1].helper=b:d[0]&&(d[0].helper=b)}}}),g.directive("svPlaceholder",function(){return{require:["?^svPart","?^svElement"],link:function(a,b,c,d){b.addClass("sv-placeholder").addClass("ng-hide"),d[1]?d[1].placeholder=b:d[0]&&(d[0].placeholder=b)}}}),b.element(document.head).append([""].join(""));var h=document.documentElement,i=h.matches?"matches":h.matchesSelector?"matchesSelector":h.webkitMatches?"webkitMatches":h.webkitMatchesSelector?"webkitMatchesSelector":h.msMatches?"msMatches":h.msMatchesSelector?"msMatchesSelector":h.mozMatches?"mozMatches":h.mozMatchesSelector?"mozMatchesSelector":null;if(null==i)throw"This browser doesn't support the HTMLElement.matches method";var j=b.element.prototype.closest||function(a){for(var c=this[0].parentNode;c!==document.documentElement&&!c[i](a);)c=c.parentNode;return c[i](a)?b.element(c):b.element()};"function"!=typeof b.element.prototype.add&&(b.element.prototype.add=function(a){var c,d=b.element();for(a=b.element(a),c=0;c