Comparing version 0.2.0 to 0.3.0
/*! | ||
* Muuri v0.2.0 | ||
* Muuri v0.3.0 | ||
* https://github.com/haltu/muuri | ||
@@ -24,2 +24,3 @@ * Copyright (c) 2015, Haltu Oy | ||
*/ | ||
!function(t,e){var i="Muuri",n="function"==typeof jQuery?jQuery.Velocity:t.Velocity,r=t.Hammer;t[i]=e(t,n,r)}(this,function(t,e,n,r){"use strict";function o(){}function s(t){var e=this,i=[],n=!!t.fillGaps,r=!!t.horizontal,o=!!t.alignRight,a=!!t.alignBottom;if(e.width=Math.round(e.width),e.height=Math.round(e.height),r?(e.setWidth=!0,e.width=0):(e.setHeight=!0,e.height=0),e.items.length){for(var l=0;l<e.items.length;l++){var h=e.items[l],u=s.getSlot(e,i,h._width,h._height,!r,n);r?e.width=Math.max(e.width,u.left+u.width):e.height=Math.max(e.height,u.top+u.height),e.slots[h._id]=u}if(o||a)for(var f in e.slots){var u=e.slots[f];o&&(u.left=e.width-(u.left+u.width)),a&&(u.top=e.height-(u.top+u.height))}}}function a(e){var i=this,n=i._settings=m({},a.defaultSettings,e||{});if(!document.body.contains(n.container))throw new Error("Container must be an existing DOM element");i._element=n.container,y(n.container,n.containerClass),i._id=++k,i._animQueue="muuri-"+i._id,i._emitter=new o,i._itemShow="function"==typeof n.show?n.show():M(n.show,!0),i._itemHide="function"==typeof n.hide?n.hide():M(n.hide),i._items=[];for(var r=0,s=n.items.length;r<s;r++)i._items[i._items.length]=new a.Item(i,n.items[r]);if(n.layoutOnResize||0===n.layoutOnResize){var l=d(function(){i.refresh(),i.layout()},n.layoutOnResize);i._resizeHandler=function(){l()},t.addEventListener("resize",i._resizeHandler)}n.layoutOnInit&&i.layout(!0)}function l(t,e,i){var n=t[e];t[e]=t[i],t[i]=n}function h(t,e,i){t.splice(i,0,t.splice(e,1)[0])}function u(t){for(var e=[],i=0,n=t.length;i<n;i++)e.indexOf(t[i])===-1&&(e[e.length]=t[i]);return e}function f(t){return"object"==typeof t&&"[object Object]"===Object.prototype.toString.call(t)}function m(t){for(var e=Array.prototype.slice.call(arguments,1),i=0;i<e.length;i++){var n=e[i];for(var r in n)n.hasOwnProperty(r)&&(f(t[r])&&f(n[r])?m(t[r],n[r]):t[r]=n[r])}return t}function d(e,i){var n,o="cancel",s="finish";return function(a){n!==r&&(n=t.clearTimeout(n),a===s&&e()),a!==o&&a!==s&&(n=t.setTimeout(function(){n=r,e()},i))}}function c(t,e){var i=null,n={left:t.left-e.left,right:e.left+e.width-(t.left+t.width),top:t.top-e.top,bottom:e.top+e.height-(t.top+t.height)},r=Math.max(t.width+Math.min(n.left,0)+Math.min(n.right,0),0),o=Math.max(t.height+Math.min(n.top,0)+Math.min(n.bottom,0),0),s=r>0&&o>0;return s&&(i={},i.width=r,i.height=o,i.left=t.left+Math.abs(Math.min(n.left,0)),i.right=i.left+i.width,i.top=t.top+Math.abs(Math.min(n.top,0)),i.bottom=i.top+i.height),i}function _(e,i){return t.getComputedStyle(e,null).getPropertyValue(i)}function g(t,e){for(var i in e)t.style[i]=e[i]}function p(t,i){for(var n in i)e.hook(t,n,i[n])}function v(t,e){return(" "+t.className).indexOf(" "+e)>-1}function y(t,e){t.classList?t.classList.add(e):v(t,e)&&(t.className+=" "+e)}function w(t,e){t.classList?t.classList.remove(e):v(t,e)&&(t.className=(" "+t.className+" ").replace(" "+e+" "," ").trim())}function C(e,i,n){var o=e.getBoundingClientRect()[i],s="height"===i,a=s?"Height":"Width",l="inner"+a,h="client"+a,u=s?"top":"left",f=s?"bottom":"right";if(n){var m=parseFloat(_(e,"margin-"+u)),d=parseFloat(_(e,"margin-"+f));o+=m>0?m:0,o+=d>0?d:0}else{var c,g;e===document.documentElement?o-=t[l]-document.documentElement[h]:(c=parseFloat(_(e,"border-"+u+"-width")),g=parseFloat(_(e,"border-"+f+"-width")),o-=Math.round(o)-e[h]-c-g),o-=c!==r?c:parseFloat(_(e,"border-"+u+"-width")),o-=g!==r?g:parseFloat(_(e,"border-"+f+"-width"))}return o}function b(e){var i=0,n=0,r=parseFloat(t.pageXOffset),o=parseFloat(t.pageYOffset);if(e.self===t.self)i=r,n=o;else if(e!==document){var s=e.getBoundingClientRect();i+=s.left+r+parseFloat(_(e,"border-left-width")),n+=s.top+o+parseFloat(_(e,"border-top-width"))}return{left:i,top:n}}function D(e){var i="fixed"===_(e,"position");if(i&&rt)return t;var n=e===document.documentElement||e===t?document:e.parentElement||null;if(i){for(;n&&n!==document&&!x(n);)n=n.parentElement||document;return n===document?t:n}for(;n&&n!==document&&"static"===_(n,"position")&&!x(n);)n=n.parentElement||document;return n}function x(t){var e=_(t,nt.style),i=_(t,"display");return"none"!==e&&"inline"!==i&&"none"!==i}function S(t,e){var i=b(e),n=b(D(t)||doc);return n.left-=Math.abs(Math.min(parseFloat(_(t,"margin-left")),0)),n.top-=Math.abs(Math.min(parseFloat(_(t,"margin-top")),0)),{left:i.left-n.left,top:i.top-n.top}}function R(e){var i=[],n=/(auto|scroll)/,r=e.parentNode;if(rt){if("fixed"===_(e,"position"))return i;for(;r&&r!==document&&r!==document.documentElement;)n.test(_(r,"overflow")+_(r,"overflow-y")+_(r,"overflow-x"))&&(i[i.length]=r),r="fixed"===_(r,"position")?null:r.parentNode;null!==r&&(i[i.length]=t)}else{for(;r&&r!==document;)"fixed"!==_(e,"position")||x(r)?(n.test(_(r,"overflow")+_(r,"overflow-y")+_(r,"overflow-x"))&&(i[i.length]=r),e=r,r=r.parentNode):r=r.parentNode;i.length&&i[i.length-1]===document.documentElement&&(i[i.length-1]=t)}return i}function I(t,e){var i=c(t,e);if(!i)return 0;var n={width:t.width,height:t.height,left:0,top:0},r={width:e.width,height:e.height,left:0,top:0},o=c(n,r);return i.width*i.height/(o.width*o.height)*100}function O(t,e,i){return{type:t,event:e,currentLeft:i.left,currentTop:i.top,gridLeft:i.gridX,gridTop:i.gridY}}function X(t,e,i){this.isResolved||(this.isResolved=!0,i(t))}function Y(t){if(!t.elementStyles){var e=["width","height","padding","margin"];t.elementStyles={};for(var i=0;i<4;i++){var n=e[i],r=t.element.style[n];t.elementStyles[n]=r||""}for(var i=0;i<4;i++){var n=e[i];t.element.style[n]=_(t.element,n)}}}function L(t){if(t.elementStyles)for(var e in t.elementStyles)t.element.style[e]=t.elementStyles[e]}function E(t,e,i,n,r){i=t.get(i),r="function"==typeof n?n:r;var o=i.length;if(o){var s="show"===e,a=s?A:W,l=s?j:B,h=n===!0,u=[],f=!1,m=[];t._emitter.emit(a,i);for(var d=0,c=i.length;d<c;d++){var _=i[d];(s&&!_._active||!s&&_._active)&&(f=!0,s&&(_._noLayoutAnimation=!0,m[m.length]=_)),_["_"+e](h,function(e,i){e||(u[u.length]=i),--o<1&&("function"==typeof r&&r(u),t._emitter.emit(l,u))})}f&&(m.length&&t.refresh(m),t.layout())}else"function"==typeof r&&r(i)}function M(t,i){var n=t&&t.duration||0,r=t&&t.easing||"ease-out";if(n){var o=i?{opacity:1,scale:1}:{opacity:0,scale:.5};return{start:function(t,i,s){i?p(t._child,o):(e(t._child,o,{duration:n,easing:r,queue:t._muuri._animQueue,complete:s}),e.Utilities.dequeue(t._child,t._muuri._animQueue))},stop:function(t){e(t._child,"stop",t._muuri._animQueue)}}}return{start:P,stop:P}}function Q(t,e,i){for(var n=t.splice(0,t.length),r=0,o=n.length;r<o;r++)n[r](e,i)}if(!document.body)throw Error("Muuri needs access to document.body to work.");var k=0,P=function(){},F="function"==typeof t.requestAnimationFrame?t.requestAnimationFrame:null,H="refresh",N="synchronize",T="layoutstart",z="layoutend",A="showstart",j="showend",W="hidestart",B="hideend",q="move",V="swap",U="add",G="remove",Z="dragstart",J="dragmove",K="dragscroll",$="dragend",tt="releasestart",et="releaseend",it="destroy",nt=function(){for(var t=["transform","WebkitTransform","MozTransform","OTransform","msTransform"],e=0;e<t.length;e++)if(document.documentElement.style[t[e]]!==r){var i=t[e],n=i.toLowerCase().split("transform")[0];return{prefix:n,prop:i,style:n?"-"+n+"-transform":i}}return null}(),rt=function(){if(!nt)return!0;var t,e,i=document.body,n=document.createElement("div"),r=document.createElement("div");return g(n,{display:"block",visibility:"hidden",position:"absolute",width:"1px",height:"1px",left:"1px",top:"0",margin:"0"}),g(r,{display:"block",position:"fixed",width:"1px",height:"1px",left:"0",top:"0",margin:"0"}),n.appendChild(r),i.appendChild(n),t=r.getBoundingClientRect().left,n.style[nt.prop]="translateZ(0)",e=r.getBoundingClientRect().left,i.removeChild(n),e===t}();return o.prototype.on=function(t,e){var i=this._events=this._events||{},n=i[t]||[];return n[n.length]=e,i[t]=n,this},o.prototype.off=function(t,e){var n=this._events=this._events||{},r=n[t]||[],o=r.length;if(o)for(;o--;)e===r[i]&&r.splice(o,1);return this},o.prototype.emit=function(t,e,i,n){var r=this._events=this._events||{},o=r[t]||[],s=o.length;if(s){var a=arguments.length-1;o=o.concat();for(var l=0;l<s;l++)0===a?o[l]():1===a?o[l](e):2===a?o[l](e,i):o[l](e,i,n)}return this},s.getSlot=function(t,e,i,n,r,o){var a,l,h,u,f,m=e[0]||[],d=[],c={left:null,top:null,width:i,height:n};for(a=0;a<m.length;a++)if(h=m[a],c.width<=h.width&&c.height<=h.height){c.left=h.left,c.top=h.top;break}for(null===c.left&&(c.left=r?0:t.width,c.top=r?t.height:0,o||(f=!0)),r&&c.top+c.height>t.height&&(c.left>0&&(d[d.length]={left:0,top:t.height,width:c.left,height:1/0}),c.left+c.width<t.width&&(d[d.length]={left:c.left+c.width,top:t.height,width:t.width-c.left-c.width,height:1/0}),t.height=c.top+c.height),!r&&c.left+c.width>t.width&&(c.top>0&&(d[d.length]={left:t.width,top:0,width:1/0,height:c.top}),c.top+c.height<t.height&&(d[d.length]={left:t.width,top:c.top+c.height,width:1/0,height:t.height-c.top-c.height}),t.width=c.left+c.width),a=o?0:f?m.length:a;a<m.length;a++)for(u=s.splitRect(m[a],c),l=0;l<u.length;l++)h=u[l],h.width>0&&h.height>0&&(r&&h.top<t.height||!r&&h.left<t.width)&&(d[d.length]=h);return s.purgeSlots(d).sort(r?s.sortRectsTopLeft:s.sortRectsLeftTop),e[0]=d,c},s.sortRectsTopLeft=function(t,e){return t.top<e.top?-1:t.top>e.top?1:t.left<e.left?-1:t.left>e.left?1:0},s.sortRectsLeftTop=function(t,e){return t.left<e.left?-1:t.left>e.left?1:t.top<e.top?-1:t.top>e.top?1:0},s.isRectWithinRect=function(t,e){return t.left>=e.left&&t.top>=e.top&&t.left+t.width<=e.left+e.width&&t.top+t.height<=e.top+e.height},s.purgeSlots=function(t){for(var e=t.length;e--;)for(var i=t[e],n=t.length;n--;){var r=t[n];if(e!==n&&s.isRectWithinRect(i,r)){t.splice(e,1);break}}return t},s.splitRect=function(t,e){var i=[],n=!(e.left>t.left+t.width||e.left+e.width<t.left||e.top>t.top+t.height||e.top+e.height<t.top);return n?(t.left<e.left&&(i[i.length]={left:t.left,top:t.top,width:e.left-t.left,height:t.height}),t.left+t.width>e.left+e.width&&(i[i.length]={left:e.left+e.width,top:t.top,width:t.left+t.width-(e.left+e.width),height:t.height}),t.top<e.top&&(i[i.length]={left:t.left,top:t.top,width:t.width,height:e.top-t.top}),t.top+t.height>e.top+e.height&&(i[i.length]={left:t.left,top:e.top+e.height,width:t.width,height:t.top+t.height-(e.top+e.height)})):i[0]=t,i},a.prototype._getItem=function(t){if(t){if(t instanceof a.Item)return t._muuri===this?t:null;if("number"==typeof t)return t=t>-1?t:this._items.length+t,this._items[t]||null;for(var e=null,i=0,n=this._items.length;i<n;i++){var r=this._items[i];if(r._element===t){e=r;break}}return e}return this._items[0]||null},a.prototype.on=function(t,e){return this._emitter.on(t,e),this},a.prototype.off=function(t,e){return this._emitter.off(t,e),this},a.prototype.refresh=function(t){t=t?this.get(t):this.get("active");for(var e=0,i=t.length;e<i;e++)t[e]._refresh();this._emitter.emit(H,t)},a.prototype.get=function(t,e){var i=t&&"string"!=typeof t;if(e=i?e:t,e="string"==typeof e?e:null,t=i?[].concat(t):null,e||t){for(var n=t||this._items,r=[],o="active"===e,s="inactive"===e,a=0,l=n.length;a<l;a++){var h=i?this._getItem(n[a]):n[a];h&&(!e||o&&h._active||s&&!h._active)&&(r[r.length]=h)}return r}return this._items.concat()},a.prototype.add=function(t,e){var i=[],n=!1;t=[].concat(t);for(var r=0,o=this._items.length;r<o;r++){var s=this._items[r],e=t.indexOf(s._element);e>-1&&t.splice(e,1)}if(!t.length)return i;for(var r=0,o=t.length;r<o;r++){var s=new a.Item(this,t[r]);i[i.length]=s,s._active&&(n=!0,s._noLayoutAnimation=!0)}return e=e<0?this._items.length-e+1:e,this._items.splice.apply(this._items,[e,0].concat(i)),n&&this.layout(),this._emitter.emit(U,i),i},a.prototype.remove=function(t,e){var i=[],n=!1;t=this.get(t);for(var r=0,o=t.length;r<o;r++){var s=t[r];s._active&&(n=!0),i[i.length]=s._destroy(e)}return n&&this.layout(),this._emitter.emit(G,i),i},a.prototype.synchronize=function(){for(var t=0,e=this._items.length;t<e;t++){var i=this._items[t];i._element.parentNode===this._element&&this._element.appendChild(i._element)}this._emitter.emit(N)},a.prototype.layout=function(t,e){var i=this,n=i._emitter,e="function"==typeof t?t:e,r=t===!0,o=new a.Layout(i),s=-1,l=o.items.length,h=[],u=function(t,i){t||(h[h.length]=i),++s===l&&("function"==typeof e&&e(h,o),n.emit(z,h,o))};if(n.emit(T,o.items,o),o.setHeight&&g(i._element,{height:o.height+"px"}),o.setWidth&&g(i._element,{width:o.width+"px"}),l)for(var f=0,m=o.items.length;f<m;f++){var d=o.items[f],c=o.slots[d._id];d._left=c.left,d._top=c.top,d._drag.active?u(!1,d):d._layout(r,u)}else u(!0)},a.prototype.show=function(t,e,i){E(this,"show",t,e,i)},a.prototype.hide=function(t,e,i){E(this,"hide",t,e,i)},a.prototype.indexOf=function(t){if("number"==typeof t)return t<=this._items.length-1?t:null;if(t instanceof a.Item){var e=this._items.indexOf(t);return e>-1?e:null}for(var e=null,i=0,n=this._items.length;i<n;i++)if(this._items[i]._element===t){e=i;break}return e},a.prototype.move=function(t,e){t=this._getItem(t),e=this._getItem(e),t&&e&&t!==e&&(h(this._items,this._items.indexOf(t),this._items.indexOf(e)),this._emitter.emit(q,t,e))},a.prototype.swap=function(t,e){t=this._getItem(t),e=this._getItem(e),t&&e&&t!==e&&(l(this._items,this._items.indexOf(t),this._items.indexOf(e)),this._emitter.emit(V,t,e))},a.prototype.destroy=function(){this._resizeHandler&&t.removeEventListener("resize",this._resizeHandler);for(var e=this._items.concat(),i=0,n=e.length;i<n;i++)e[i]._destroy();w(this._element,this._settings.containerClass),g(this._element,{height:""}),this._emitter.emit(it);var r=this._emitter._events;if(r)for(var o=Object.keys(this._emitter._events),i=0,n=o.length;i<n;i++)r[o[i]].length=0;for(var s=Object.keys(this).concat(Object.keys(a.prototype)),i=0;i<s.length;i++)this[s[i]]=null},a.Item=function(t,e){if(e.contains(t._element))throw new Error("Item element must not be a parent of the grid container element");e.parentNode!==t._element&&t._element.appendChild(e);var i=t._settings,n="none"===_(e,"display");this._id=++k,this._muuri=t,this._element=e,this._child=e.children[0],y(e,i.itemClass),this._active=!n,this._positioning=!1,this._hidden=n,this._hiding=!1,this._showing=!1,this._visibiliyQueue=[],this._layoutQueue=[],p(this._element,{left:"0",top:"0",translateX:"0px",translateY:"0px"}),y(e,n?i.hiddenClass:i.shownClass),p(this._child,{scale:n?0:1,opacity:n?0:1}),n||g(this._element,{display:"block"}),this._refresh(),this._left=0,this._top=0,this._drag={active:!1},this._release={active:!1},t._settings.dragEnabled&&this._initDrag()},a.Item.prototype.inspect=function(){return{element:this._element,width:this._width,height:this._height,left:this._left,top:this._top,active:this._active,positioning:this._positioning,dragging:this._drag.active,releasing:this._release.active,visibility:this._hiding?"hiding":this._showing?"showing":this._hidden?"hidden":"shown"}},a.Item.prototype._initDrag=function(){var t=this,e=t._muuri._settings,i=t._hammer=new n.Manager(t._element);i.add(new n.Pan({event:"drag",pointers:1,threshold:0,direction:n.DIRECTION_ALL})),i.add(new n.Press({event:"draginit",pointers:1,threshold:100,time:0})),i.set({touchAction:"none"}),t._resetReleaseData();var r=t._drag;t._resetDragData(),r.checkOverlap=d(function(){r.active&&t._checkOverlap()},e.dragSortInterval);var o=!1;r.predicate="function"==typeof e.dragPredicate?e.dragPredicate:X,r.predicateData={},r.isPredicateResolved=function(){return o},r.resolvePredicate=function(e){o||"draginitup"===e.type||"dragend"===e.type||"dragcancel"===e.type||(o=!0,t._onDragStart(e))},r.onScroll=function(e){F?F(function(){t._onDragScroll(e)}):t._onDragScroll(e)},i.on("draginit",function(e){r.predicateData={},o=!1,r.predicate.call(r.predicateData,e,t,r.resolvePredicate)}).on("dragstart dragmove",function(e){o&&r.active&&t._onDragMove(e),r.predicate.call(r.predicateData,e,t,r.resolvePredicate)}).on("dragend dragcancel draginitup",function(e){o&&r.active&&t._onDragEnd(e),r.predicate.call(r.predicateData,e,t,r.resolvePredicate)})},a.Item.prototype._resetDragData=function(){var t=this._drag;t.active=!1,t.start=null,t.move=null,t.element=null,t.elemWidth=0,t.elemHeight=0,t.elementStyles=null,t.scrollParents=[],t.left=0,t.top=0,t.gridX=0,t.gridY=0,t.elemClientX=0,t.elemClientY=0,t.containerDiffX=0,t.containerDiffY=0},a.Item.prototype._onDragStart=function(t){var i=this._drag,n=this._muuri._settings,r=this._release.active;if(this._active){this._positioning&&this._stopLayout(),r&&(i.elementStyles=this._release.elementStyles,w(this._element,n.releasingClass),this._resetReleaseData()),i.active=!0,i.start=t,i.move=t,i.element=this._element,i.elemWidth=this._width,i.elemHeight=this._height;var o=parseFloat(e.hook(i.element,"translateX"))||0,s=parseFloat(e.hook(i.element,"translateY"))||0,a=this._muuri._element,l=n.dragContainer;if(i.left=i.gridX=o,i.top=i.gridY=s,l&&l!==a)if(i.element.parentNode===l){var h=S(i.element,a);i.containerDiffX=h.left,i.containerDiffY=h.top,i.gridX=o-i.containerDiffX,i.gridY=s-i.containerDiffY}else{Y(i),l.appendChild(i.element);var h=S(i.element,a);i.containerDiffX=h.left,i.containerDiffY=h.top,i.left=o+i.containerDiffX,i.top=s+i.containerDiffY,p(i.element,{translateX:i.left+"px",translateY:i.top+"px"})}var f=i.element.getBoundingClientRect();i.elemClientX=f.left,i.elemClientY=f.top,i.scrollParents=R(i.element),l&&l!==a&&(i.scrollParents=u(i.scrollParents.concat(R(a))));for(var m=0,d=i.scrollParents.length;m<d;m++)i.scrollParents[m].addEventListener("scroll",i.onScroll);y(i.element,n.draggingClass),this._muuri._emitter.emit(Z,this,O("dragstart",t,i))}},a.Item.prototype._onDragMove=function(t){var e=this._drag,i=this._muuri._settings;if(!this._active)return void this._resetDrag();var n=t.deltaX-e.move.deltaX,r=t.deltaY-e.move.deltaY;e.move=t,e.left+=n,e.top+=r,e.gridX+=n,e.gridY+=r,e.elemClientX+=n,e.elemClientY+=r,p(e.element,{translateX:e.left+"px",translateY:e.top+"px"}),i.dragSort&&e.checkOverlap(),this._muuri._emitter.emit(J,this,O("dragmove",t,e))},a.Item.prototype._onDragScroll=function(t){var e=this._drag,i=this._muuri._settings,n=this._muuri._element,r=i.dragContainer,o=e.element.getBoundingClientRect(),s=e.elemClientX-o.left,a=e.elemClientY-o.top;if(r&&r!==n){var l=S(e.element,n);e.containerDiffX=l.left,e.containerDiffY=l.top}e.left+=s,e.top+=a,e.gridX=e.left-e.containerDiffX,e.gridY=e.top-e.containerDiffY,p(e.element,{translateX:e.left+"px",translateY:e.top+"px"}),i.dragSort&&e.checkOverlap(),this._muuri._emitter.emit(K,this,O("dragscroll",t,e))},a.Item.prototype._onDragEnd=function(t){var e=this._drag,i=this._muuri._settings,n=this._release;if(!this._active)return void this._resetDrag();i.dragSort&&e.checkOverlap("finish");for(var r=0,o=e.scrollParents.length;r<o;r++)e.scrollParents[r].removeEventListener("scroll",e.onScroll);w(e.element,i.draggingClass),e.active=!1,this._muuri._emitter.emit($,this,O("dragend",t,e)),n.containerDiffX=e.containerDiffX,n.containerDiffY=e.containerDiffY,n.element=e.element,n.elementStyles=e.elementStyles,this._resetDragData(),this._startRelease()},a.Item.prototype._resetDrag=function(t){for(var e=this._drag,i=this._muuri._settings,n=0,r=e.scrollParents.length;n<r;n++)e.scrollParents[n].removeEventListener("scroll",e.onScroll);e.checkOverlap("cancel"),w(e.element,i.draggingClass),L(e),this._resetDragData()},a.Item.prototype._resetReleaseData=function(){var t=this._release;t.active=!1,t.positioningStarted=!1,t.containerDiffX=0,t.containerDiffY=0,t.element=null,t.elementStyles=null},a.Item.prototype._startRelease=function(){var t=this._muuri._settings,e=this._release;e.active=!0,y(e.element,t.releasingClass),this._muuri._emitter.emit(tt,this),this._layout(!1)},a.Item.prototype._endRelease=function(){var t=this._muuri._settings,e=this._release;w(e.element,t.releasingClass),e.element.parentNode!==this._muuri._element&&(this._muuri._element.appendChild(e.element),p(e.element,{translateX:this._left+"px",translateY:this._top+"px"})),L(e),this._resetReleaseData(),this._muuri._emitter.emit(et,this)},a.Item.prototype._checkOverlap=function(){for(var t=this._muuri._settings,e=t.dragSortTolerance,i=t.dragSortAction,n=this._muuri._items,r=null,o=0,s={width:this._drag.elemWidth,height:this._drag.elemHeight,left:this._drag.gridX,top:this._drag.gridY},a=0,u=n.length;a<u;a++){var f=n[a];if(f===this)o=a;else if(f._active){var m=I(s,{width:f._width,height:f._height,left:f._left,top:f._top});(!r||m>r.score)&&(r={item:f,score:m,index:a})}}r&&r.score>=e&&("swap"===i?(l(n,o,r.index),this._muuri._emitter.emit(V,this,r.item)):(h(n,o,r.index),this._muuri._emitter.emit(q,this,r.item)),this._muuri.layout())},a.Item.prototype._stopLayout=function(){var t=this._muuri._settings;this._positioning&&(e(this._element,"stop",this._muuri._animQueue),w(this._element,t.positioningClass),this._positioning=!1,Q(this._layoutQueue,!0,this))},a.Item.prototype._refresh=function(){this._hidden||(this._width=Math.round(C(this._element,"width",!0)),this._height=Math.round(C(this._element,"height",!0)))},a.Item.prototype._layout=function(t,i){var n=this,r=n._muuri._settings,o=n._release,s=o.active&&o.positioningStarted===!1,a=s?r.dragReleaseDuration:r.positionDuration,l=s?r.dragReleaseEasing:r.positionEasing,h=t!==!0&&!n._noLayoutAnimation&&a>0,u=n._positioning,f=function(){w(n._element,r.positioningClass),n._positioning=!1,o.active&&n._endRelease(),Q(n._layoutQueue,!1,n)};n._stopLayout(),"function"==typeof i&&(n._layoutQueue[n._layoutQueue.length]=i),s&&(o.positioningStarted=!0);var m=n._release.active?n._release.containerDiffX:0,d=n._release.active?n._release.containerDiffY:0;if(h){var c=(parseFloat(e.hook(n._element,"translateX"))||0)-m,_=(parseFloat(e.hook(n._element,"translateY"))||0)-d;if(n._left===c&&n._top===_)return void f();n._positioning=!0,u||y(n._element,r.positioningClass),e(n._element,{translateX:n._left+m,translateY:n._top+d},{duration:a,easing:l,complete:f,queue:n._muuri._animQueue}),e.Utilities.dequeue(n._element,n._muuri._animQueue)}else n._noLayoutAnimation&&(n._noLayoutAnimation=!1),p(n._element,{translateX:n._left+m+"px",translateY:n._top+d+"px"}),f()},a.Item.prototype._show=function(t,e){var i=this,n=i._muuri._settings;if(i._hidden||i._showing)if(i._hidden){i._hiding;i._muuri._itemHide.stop(i),i._active=!0,i._hidden=!1,i._showing=i._hiding=!1,y(i._element,n.shownClass),w(i._element,n.hiddenClass),g(i._element,{display:"block"}),Q(i._visibiliyQueue,!0,i),i._showing=!0,"function"==typeof e&&(i._visibiliyQueue[i._visibiliyQueue.length]=e),i._muuri._itemShow.start(i,t,function(){Q(i._visibiliyQueue,!1,i)})}else"function"==typeof e&&(i._visibiliyQueue[i._visibiliyQueue.length]=e);else"function"==typeof e&&e(!1,i)},a.Item.prototype._hide=function(t,e){var i=this,n=i._muuri._settings;if(i._hidden&&!i._hiding)"function"==typeof e&&e(!1,i);else if(i._hidden)"function"==typeof e&&(i._visibiliyQueue[i._visibiliyQueue.length]=e);else{i._showing;i._muuri._itemShow.stop(i),i._active=!1,i._hidden=!0,i._showing=i._hiding=!1,y(i._element,n.hiddenClass),w(i._element,n.shownClass),Q(i._visibiliyQueue,!0,i),i._hiding=!0,"function"==typeof e&&(i._visibiliyQueue[i._visibiliyQueue.length]=e),i._muuri._itemHide.start(i,t,function(){g(i._element,{display:"none"}),Q(i._visibiliyQueue,!1,i)})}},a.Item.prototype._destroy=function(t){var e=(this._muuri,this._muuri._settings),i=this._element,n=this._muuri._items.indexOf(this);this._stopLayout(),this._muuri._itemShow.stop(this),this._muuri._itemHide.stop(this),this._release.active&&(i.parentNode!==this._muuri._element&&this._muuri._element.appendChild(i),this._resetReleaseData()),this._drag.active&&(i.parentNode!==this._muuri._element&&this._muuri._element.appendChild(i),this._resetDrag()),this._hammer&&this._hammer.destroy(),i.removeAttribute("style"),this._child.removeAttribute("style"),Q(this._visibiliyQueue,!0,this),w(i,e.positioningClass),w(i,e.draggingClass),w(i,e.releasingClass),w(i,e.itemClass),w(i,e.shownClass),w(i,e.hiddenClass),n>-1&&this._muuri._items.splice(n,1),t&&i.parentNode.removeChild(i);for(var r=Object.keys(this).concat(Object.keys(a.Item.prototype)),o=0;o<r.length;o++)this[r[o]]=null},a.Layout=function(t,e){var i=t._settings.layout;if(this.muuri=t,this.items=e?e.concat():t.get("active"),this.slots={},this.width=0,this.height=0,this.setWidth=!1,this.setHeight=!1,this.width=C(t._element,"width"),this.height=C(t._element,"height"),"function"==typeof i)i.call(this);else{var n="string"==typeof i,r=n?i:i[0];if("function"!=typeof a.Layout.methods[r])throw new Error('Layout method "'+method+'" does not exist.');typeof a.Layout.methods[r].call(this,n?{}:i[1])}},a.Layout.methods={firstFit:s},a.defaultSettings={container:null,items:[],positionDuration:300,positionEasing:"ease-out",show:{duration:300,easing:"ease-out"},hide:{duration:300,easing:"ease-out"},layout:"firstFit",layoutOnResize:100,layoutOnInit:!0,dragEnabled:!1,dragContainer:null,dragPredicate:null,dragSort:!0,dragSortInterval:50,dragSortTolerance:50,dragSortAction:"move",dragReleaseDuration:300,dragReleaseEasing:"ease-out",containerClass:"muuri",itemClass:"muuri-item",shownClass:"muuri-shown",hiddenClass:"muuri-hidden",positioningClass:"muuri-positioning",draggingClass:"muuri-dragging",releasingClass:"muuri-releasing"},a}); | ||
!function(t,e){var i,n;if("function"==typeof define&&define.amd)define(function(r){return i=r.defined&&r.defined("velocity")?r("velocity"):void 0,n=r.defined&&r.defined("hammer")?r("hammer"):void 0,e(t,"Muuri",i,n)});else if("object"==typeof module&&module.exports){try{i=require("velocity-animate")}catch(t){}try{n=require("hammerjs")}catch(t){}module.exports=e(t,"Muuri",i,n)}else i=t.Velocity||t.jQuery.Velocity,n=t.Hammer,t.Muuri=e(t,"Muuri",i,n)}(this,function(t,e,i,n,r){"use strict";function o(e,i){var n,r,s,a,l=this;if(e=l._element=typeof e===lt?et.querySelectorAll(e)[0]:e,!et.body.contains(e))throw new ot("Container element must be an existing DOM element");n=l._settings=tt(o.defaultOptions,i),l._id=++_t,ht[l._id]=l,l._isDestroyed=!1,l._layout=null,l._emitter=new o.Emitter,l._setSortGroups(n.dragSortGroup),l._sortConnections=n.dragSortWith&&n.dragSortWith.length?[].concat(n.dragSortWith):null,l._itemShowHandler=typeof n.showAnimation===at?n.showAnimation(n.showDuration,n.showEasing,n.visibleStyles):U("show",n.showDuration,n.showEasing,n.visibleStyles),l._itemHideHandler=typeof n.hideAnimation===at?n.hideAnimation(n.hideDuration,n.hideEasing,n.hiddenStyles):U("hide",n.hideDuration,n.hideEasing,n.hiddenStyles),E(e,n.containerClass),l._items=[],r=n.items,typeof r===lt?Y(l._element.children).forEach(function(t){("*"===r||pt(t,r))&&l._items.push(new o.Item(l,t))}):(nt.isArray(r)||D(r))&&(l._items=Y(r).map(function(t){return new o.Item(l,t)})),a=n.layoutOnResize,a=!0===a?0:typeof a===dt?a:-1,a>=0&&(s=C(function(){l.refreshItems().layout()},a),l._resizeHandler=function(){s()},t.addEventListener("resize",l._resizeHandler)),n.layoutOnInit&&l.layout(!0)}function s(t,e){var i,n=this,r=t._settings;n._id=++_t,ft[n._id]=n,n._isDestroyed=!1,e.parentNode!==t._element&&t._element.appendChild(e),E(e,r.itemClass),i="none"===b(e,"display"),E(e,i?r.itemHiddenClass:r.itemVisibleClass),n._gridId=t._id,n._element=e,n._child=e.children[0],n._animate=new o.ItemAnimate(n,e),n._animateChild=new o.ItemAnimate(n,n._child),n._isDefaultAnimate=n._animate instanceof f,n._isActive=!i,n._isPositioning=!1,n._isHidden=i,n._isHiding=!1,n._isShowing=!1,n._visibilityQueue=[],n._layoutQueue=[],n._left=0,n._top=0,I(e,{left:"0",top:"0",transform:"translateX(0px) translateY(0px)",display:i?"none":"block"}),n._refreshDimensions()._refreshSortData(),i?t._itemHideHandler.start(n,!0):t._itemShowHandler.start(n,!0),n._migrate=new o.ItemMigrate(n),n._release=new o.ItemRelease(n),n._drag=r.dragEnabled?new o.ItemDrag(n):null}function a(t,e){e=e?e.concat():t.getItems("active"),t._refreshDimensions();var i=this,n=t._settings.layout,r=t._width-t._border.left-t._border.right-t._padding.left-t._padding.right,o=t._height-t._border.top-t._border.bottom-t._padding.top-t._padding.bottom,s=typeof n===at?n(e,r,o):l(e,r,o,v(n)?n:{});i.items=e,i.slots=s.slots,i.setWidth=s.setWidth||!1,i.setHeight=s.setHeight||!1,i.width=s.width,i.height=s.height}function l(t,e,i,n){var r,o,s,a,l=!!n.fillGaps,h=!!n.horizontal,f=!!n.alignRight,u=!!n.alignBottom,g={slots:{},width:h?0:e,height:h?i:0,setWidth:h,setHeight:!h},_=[];if(!t.length)return g;for(a=0;a<t.length;a++)s=t[a],o=d(g,_,s._outerWidth,s._outerHeight,!h,l),h?g.width=rt.max(g.width,o.left+o.width):g.height=rt.max(g.height,o.top+o.height),g.slots[s._id]=o;if(f||u)for(r=it.keys(g.slots),a=0;a<r.length;a++)o=g.slots[r[a]],f&&(o.left=g.width-(o.left+o.width)),u&&(o.top=g.height-(o.top+o.height));return g}function d(t,e,i,n,r,o){var s,a,l,d,h,f=e[0]||[],u=[],g={left:null,top:null,width:i,height:n};for(d=0;d<f.length;d++)if(s=f[d],g.width<=s.width&&g.height<=s.height){g.left=s.left,g.top=s.top;break}for(null===g.left&&(g.left=r?0:t.width,g.top=r?t.height:0,o||(l=!0)),r&&g.top+g.height>t.height&&(g.left>0&&(u[u.length]={left:0,top:t.height,width:g.left,height:1/0}),g.left+g.width<t.width&&(u[u.length]={left:g.left+g.width,top:t.height,width:t.width-g.left-g.width,height:1/0}),t.height=g.top+g.height),!r&&g.left+g.width>t.width&&(g.top>0&&(u[u.length]={left:t.width,top:0,width:1/0,height:g.top}),g.top+g.height<t.height&&(u[u.length]={left:t.width,top:g.top+g.height,width:1/0,height:t.height-g.top-g.height}),t.width=g.left+g.width),d=o?0:l?f.length:d;d<f.length;d++)for(a=F(f[d],g),h=0;h<a.length;h++)s=a[h],s.width>0&&s.height>0&&(r&&s.top<t.height||!r&&s.left<t.width)&&(u[u.length]=s);return e[0]=V(u).sort(r?N:M),g}function h(){this._events={},this._isDestroyed=!1}function f(t,i){this._element=i,this._queue=e+"-"+ ++_t,this._isAnimating=!1,this._isDestroyed=!1}function u(t){var e=this;e._itemId=t._id,e._isDestroyed=!1,e.isActive=!1,e.container=!1,e.containerDiffX=0,e.containerDiffY=0}function g(t){var e=this;e._itemId=t._id,e._isDestroyed=!1,e.isActive=!1,e.isPositioningStarted=!1,e.containerDiffX=0,e.containerDiffY=0}function _(t){if(!n)throw ot("["+e+"] required dependency Hammer is not defined.");var i,r=this,o=t._element,s=t.getGrid(),a=s._settings,l=typeof a.dragStartPredicate===at?a.dragStartPredicate:_.defaultStartPredicate,d=0;r._itemId=t._id,r._gridId=s._id,r._hammer=i=new n.Manager(o),r._isDestroyed=!1,r._isMigrating=!1,r._data={},r.reset(),r._checkSortOverlap=C(function(){r._data.isActive&&r.checkOverlap()},a.dragSortInterval),r._sortPredicate=typeof a.dragSortPredicate===at?a.dragSortPredicate:_.defaultSortPredicate,r._scrollHandler=function(t){r.onScroll(t)},i.add(new n.Pan({event:"drag",pointers:1,threshold:0,direction:n.DIRECTION_ALL})),i.add(new n.Press({event:"draginit",pointers:1,threshold:1e3,time:0})),v(a.dragHammerSettings)&&i.set(a.dragHammerSettings),i.on("draginit dragstart dragmove",function(t){var e;0===d?(e=l(r.getItem(),t),!0===e?(d=1,r.onStart(t)):!1===e&&(d=2)):1===d&&r._data.isActive&&r.onMove(t)}).on("dragend dragcancel draginitup",function(t){var e=1===d;l(r.getItem(),t),d=0,e&&r._data.isActive&&r.onEnd(t)}),o.addEventListener("dragstart",$,!1)}function p(t,e){var i=t.length,n=i-1;return e>n?n:e<0?rt.max(i+e,0):e}function c(t,e,i){if(!(t.length<2)){var n,r=p(t,e),o=p(t,i);r!==o&&(n=t[r],t[r]=t[o],t[o]=n)}}function m(t,e,i){if(!(t.length<2)){var n=p(t,e),r=p(t,i);n!==r&&t.splice(r,0,t.splice(n,1)[0])}}function y(t){var e,i=[],n=t.length;if(n)for(i[0]=t[0],e=1;e<n;e++)i.indexOf(t[e])<0&&(i[i.length]=t[e]);return i}function v(t){return"object"==typeof t&&"[object Object]"===it.prototype.toString.call(t)}function D(t){var e=it.prototype.toString.call(t);return"[object HTMLCollection]"===e||"[object NodeList]"===e}function w(t,e){return it.keys(e).forEach(function(i){var n=v(e[i]);v(t[i])&&n?(t[i]=w({},t[i]),t[i]=w(t[i],e[i])):t[i]=n?w({},e[i]):nt.isArray(e[i])?e[i].concat():e[i]}),t}function S(t,e,i){var n=typeof i===dt?i:-1;t.splice.apply(t,[n<0?t.length-n+1:n,0].concat(e))}function C(e,i){var n;return i>0?function(o){n!==r&&(n=t.clearTimeout(n),"finish"===o&&e()),"cancel"!==o&&"finish"!==o&&(n=t.setTimeout(function(){n=r,e()},i))}:function(t){"cancel"!==t&&e()}}function b(e,i){return t.getComputedStyle(e,null).getPropertyValue("transform"===i?ct.styleName||i:i)}function A(t,e){return parseFloat(b(t,e))||0}function x(t,e){return parseFloat((b(t,"transform")||"").replace("matrix(","").split(",")["x"===e?4:5])||0}function I(t,e){var i,n,r,o=it.keys(e);for(r=0;r<o.length;r++)i=o[r],n=e[i],t.style["transform"===i&&ct?ct.propName:i]=n}function H(t,e){var n,r=it.keys(e);for(n=0;n<r.length;n++)i.hook(t,r[n],e[r[n]])}function E(t,e){t.classList?t.classList.add(e):pt(t,"."+e)||(t.className+=" "+e)}function X(t,e){t.classList?t.classList.remove(e):pt(t,"."+e)&&(t.className=(" "+t.className+" ").replace(" "+e+" "," ").trim())}function Y(t){return[].slice.call(t)}function G(t,e,i){if(t===e)return{left:0,top:0};i&&(t=k(t,!0),e=k(e,!0));var n=P(t),r=P(e);return{left:r.left-n.left,top:r.top-n.top}}function P(e){var i,n={left:0,top:0};return e===et?n:(n.left=t.pageXOffset||0,n.top=t.pageYOffset||0,e.self===t.self?n:(i=e.getBoundingClientRect(),n.left+=i.left+A(e,"border-left-width"),n.top+=i.top+A(e,"border-top-width"),n))}function k(t,e){for(var i=(e?t:t.parentElement)||et;i&&i!==et&&"static"===b(i,"position")&&!R(i);)i=i.parentElement||et;return i}function O(e){var i=[],n=/(auto|scroll)/,r=e.parentNode;if(mt){if("fixed"===b(e,"position"))return i;for(;r&&r!==et&&r!==et.documentElement;)n.test(b(r,"overflow")+b(r,"overflow-y")+b(r,"overflow-x"))&&(i[i.length]=r),r="fixed"===b(r,"position")?null:r.parentNode;null!==r&&(i[i.length]=t)}else{for(;r&&r!==et;)"fixed"!==b(e,"position")||R(r)?(n.test(b(r,"overflow")+b(r,"overflow-y")+b(r,"overflow-x"))&&(i[i.length]=r),e=r,r=r.parentNode):r=r.parentNode;i[i.length-1]===et.documentElement?i[i.length-1]=t:i[i.length]=t}return i}function R(t){var e=b(t,"transform"),i=b(t,"display");return"none"!==e&&"inline"!==i&&"none"!==i}function L(t,e){return!(t.left+t.width<=e.left||e.left+e.width<=t.left||t.top+t.height<=e.top||e.top+e.height<=t.top)}function N(t,e){return t.top-e.top||t.left-e.left}function M(t,e){return t.left-e.left||t.top-e.top}function z(t,e){return t.left>=e.left&&t.top>=e.top&&t.left+t.width<=e.left+e.width&&t.top+t.height<=e.top+e.height}function F(t,e){var i=[];return L(t,e)?(t.left<e.left&&(i[i.length]={left:t.left,top:t.top,width:e.left-t.left,height:t.height}),t.left+t.width>e.left+e.width&&(i[i.length]={left:e.left+e.width,top:t.top,width:t.left+t.width-(e.left+e.width),height:t.height}),t.top<e.top&&(i[i.length]={left:t.left,top:t.top,width:t.width,height:e.top-t.top}),t.top+t.height>e.top+e.height&&(i[i.length]={left:t.left,top:e.top+e.height,width:t.width,height:t.top+t.height-(e.top+e.height)}),i):[{left:t.left,top:t.top,width:t.width,height:t.height}]}function V(t){for(var e,i,n,r=t.length;r--;)for(i=t[r],e=t.length;e--;)if(n=t[e],r!==e&&z(i,n)){t.splice(r,1);break}return t}function W(t,e){return L(t,e)?(rt.min(t.left+t.width,e.left+e.width)-rt.max(t.left,e.left))*(rt.min(t.top+t.height,e.top+e.height)-rt.max(t.top,e.top))/(rt.min(t.width,e.width)*rt.min(t.height,e.height))*100:0}function B(t){var e,i={};for(e=0;e<t.length;e++)i[t[e]._id]=e;return i}function Q(t,e,i,n){var r=n[t._id],o=n[e._id];return i?o-r:r-o}function q(t,e,i,n){var r,o,s,a,l,d=0;for(l=0;l<n.length;l++)if(r=n[l][0],o=n[l][1],s=(t._sortData?t:t._refreshSortData())._sortData[r],a=(e._sortData?e:e._refreshSortData())._sortData[r],0!==(d="desc"===o||!o&&i?a<s?-1:a>s?1:0:s<a?-1:s>a?1:0))return d;return d}function j(t,e){var i,n,r,o=[],s=t.concat();for(r=0;r<e.length;r++)i=e[r],(n=s.indexOf(i))>-1&&(o.push(i),s.splice(n,1));return nt.prototype.splice.apply(t,[0,t.length].concat(o).concat(s)),t}function T(t,e,i,n){var o,s,a=t.getItems(i),l=n||{},d=!0===l.instant,h=l.onFinish,f=l.layout?l.layout:l.layout===r,u=a.length,g="show"===e,_=g?yt:Dt,p=g?vt:wt,c=!1,m=[],y=[],v=[];for(s=0;s<a.length;s++)o=a[s],(g?o._isHidden||o._isHiding||o._isShowing&&d:!o._isHidden||o._isShowing||o._isHiding&&d)&&(m[m.length]=o);if(u=m.length){for(t._emit(_,m.concat()),s=0;s<m.length;s++)o=m[s],(g&&!o._isActive||!g&&o._isActive)&&(c=!0),g&&!o._isActive&&(o._skipNextLayoutAnimation=!0,v[v.length]=o),o["_"+e](d,function(e,i){e||(y[y.length]=i),--u<1&&(typeof h===at&&h(y.concat()),t._emit(p,y.concat()))});c&&(v.length&&t.refreshItems(v),f&&t.layout("instant"===f,typeof f===at?f:r))}else typeof h===at&&h(m);return t}function U(t,e,i,n){e=parseInt(e)||0,i=i||"ease",n=v(n)?n:null;var r=e>0;return{start:function(t,o,s){r&&n?o?((t._isDefaultAnimate?H:I)(t._child,n),s&&s()):t._animateChild.start(null,n,{duration:e,easing:i,onFinish:s}):s&&s()},stop:function(t){t._animateChild.stop()}}}function J(t,e,i){var n,r,o,s=null,a=e._getSortConnections(!0),l=-1;for(o=0;o<a.length;o++)r=a[o],r._refreshDimensions(),(n=W(t,{width:r._width,height:r._height,left:r._left,top:r._top}))>i&&n>l&&(l=n,s=r);return s}function K(t,e,i){var n,r=t.splice(0,t.length);for(n=0;n<r.length;n++)r[n](e,i)}function Z(t,e){var i;return"inactive"===e?!t.isActive():"hidden"===e?!t.isVisible():(i="is"+e.charAt(0).toUpperCase()+e.slice(1),typeof t[i]===at&&t[i]())}function $(t){t.preventDefault&&t.preventDefault()}function tt(t,e){var i=w({},t);return i=e?w(i,e):i,i.visibleStyles=(e||{}).visibleStyles||(t||{}).visibleStyles,i.hiddenStyles=(e||{}).hiddenStyles||(t||{}).hiddenStyles,i}var et=t.document,it=t.Object,nt=t.Array,rt=t.Math,ot=t.Error,st=t.Element,at="function",lt="string",dt="number",ht={},ft={},ut={},gt=function(){},_t=0,pt=function(){var t=st.prototype,e=t.matches||t.matchesSelector||t.webkitMatchesSelector||t.mozMatchesSelector||t.msMatchesSelector||t.oMatchesSelector;return function(t,i){return e.call(t,i)}}(),ct=function(t){var e,i,n,o=et.documentElement,s=t.charAt(0).toUpperCase()+t.slice(1),a=["","Webkit","Moz","O","ms"];for(n=0;n<a.length;n++)if(e=a[n],i=e?e+s:t,o.style[i]!==r)return e=e.toLowerCase(),{prefix:e,propName:i,styleName:e?"-"+e+"-"+t:t};return null}("transform"),mt=function(){if(!ct)return!0;var t,e,i=et.createElement("div"),n=et.createElement("div");return I(i,{display:"block",visibility:"hidden",position:"absolute",width:"1px",height:"1px",left:"1px",top:"0",margin:"0",transform:"none"}),I(n,{display:"block",position:"fixed",width:"1px",height:"1px",left:"0",top:"0",margin:"0",transform:"none"}),i.appendChild(n),et.body.appendChild(i),t=n.getBoundingClientRect().left,i.style[ct.propName]="scaleX(1)",e=n.getBoundingClientRect().left,et.body.removeChild(i),e===t}(),yt="showStart",vt="showEnd",Dt="hideStart",wt="hideEnd";return o.Item=s,o.ItemDrag=_,o.ItemRelease=g,o.ItemMigrate=u,o.ItemAnimate=f,o.Layout=a,o.Emitter=h,o.defaultOptions={items:"*",showDuration:300,showEasing:"ease",hideDuration:300,hideEasing:"ease",showAnimation:null,hideAnimation:null,visibleStyles:{opacity:1,scale:1},hiddenStyles:{opacity:0,scale:.5},layout:{fillGaps:!1,horizontal:!1,alignRight:!1,alignBottom:!1},layoutOnResize:100,layoutOnInit:!0,layoutDuration:300,layoutEasing:"ease",sortData:null,dragEnabled:!1,dragContainer:null,dragStartPredicate:{distance:0,delay:0,handle:!1},dragSort:!0,dragSortInterval:100,dragSortPredicate:{threshold:50,action:"move"},dragSortGroup:null,dragSortWith:null,dragReleaseDuration:300,dragReleaseEasing:"ease",dragHammerSettings:{touchAction:"none"},containerClass:"muuri",itemClass:"muuri-item",itemVisibleClass:"muuri-item-shown",itemHiddenClass:"muuri-item-hidden",itemPositioningClass:"muuri-item-positioning",itemDraggingClass:"muuri-item-dragging",itemReleasingClass:"muuri-item-releasing"},o.prototype.on=function(t,e){return this._isDestroyed||this._emitter.on(t,e),this},o.prototype.once=function(t,e){return this._isDestroyed||this._emitter.once(t,e),this},o.prototype.off=function(t,e){return this._isDestroyed||this._emitter.off(t,e),this},o.prototype.getElement=function(){return this._element},o.prototype.getItems=function(t,e){var i,n,r=this,o=0===t||t&&typeof t!==lt,s=o?D(t)?Y(t):[].concat(t):null,a=o?e:t,l=[];if(r._isDestroyed)return l;if((a=typeof a===lt?a:null)||s){for(s=s||r._items,n=0;n<s.length;n++)!(i=o?r._getItem(s[n]):s[n])||a&&!Z(i,a)||(l[l.length]=i);return l}return l.concat(r._items)},o.prototype.refreshItems=function(t){var e,i,n=this;if(!n._isDestroyed)for(e=n.getItems(t||"active"),i=0;i<e.length;i++)e[i]._refreshDimensions();return n},o.prototype.refreshSortData=function(t){var e,i,n=this;if(!n._isDestroyed)for(e=n.getItems(t),i=0;i<e.length;i++)e[i]._refreshSortData();return n},o.prototype.synchronize=function(){var t,e,i,n=this,r=n._element,o=n._items;if(n._isDestroyed)return n;if(o.length){for(i=0;i<o.length;i++)e=o[i]._element,e.parentNode===r&&(t=t||et.createDocumentFragment(),t.appendChild(e));t&&r.appendChild(t)}return n._emit("synchronize"),n},o.prototype.layout=function(t,e){function i(){--g<=0&&(typeof f===at&&f(h._layout!==n,r.concat()),h._layout===n&&h._emit("layoutEnd",r.concat()))}var n,r,s,a,l,d,h=this,f=typeof t===at?t:e,u=!0===t,g=0;if(h._isDestroyed)return h;if(n=h._layout=new o.Layout(h),r=n.items.concat(),g=r.length,h._emit("layoutStart",r.concat()),(n.setWidth||n.setHeight)&&(s="border-box"===b(h._element,"box-sizing"),n.setHeight&&I(h._element,{height:(s?n.height+h._padding.top+h._padding.bottom+h._border.top+h._border.bottom:n.height)+"px"}),n.setWidth&&I(h._element,{width:(s?n.width+h._padding.left+h._padding.right+h._border.left+h._border.right:n.width)+"px"})),!r.length)return i(),h;for(d=0;d<r.length;d++)a=r[d],l=n.slots[a._id],a._left=l.left+h._padding.left,a._top=l.top+h._padding.top,a.isDragging()?i():a._layout(u,i);return h},o.prototype.add=function(t,e){var i,n,s,a=this,l=[].concat(t),d=e||{},h=d.layout?d.layout:d.layout===r,f=[],u=a._items,g=!1;if(a._isDestroyed)return[];for(s=0;s<u.length;s++)(i=l.indexOf(u[s]._element))>-1&&l.splice(i,1);if(!l.length)return f;for(s=0;s<l.length;s++)n=new o.Item(a,l[s]),f[f.length]=n,n._isActive&&(g=!0,n._skipNextLayoutAnimation=!0);return S(u,f,d.index),a._emit("add",f.concat()),g&&h&&a.layout("instant"===h,typeof h===at?h:r),f},o.prototype.remove=function(t,e){var i,n,o,s=this,a=e||{},l=a.layout?a.layout:a.layout===r,d=!1;if(s._isDestroyed)return[];for(i=s.getItems(t),o=0;o<i.length;o++)n=i[o],n._isActive&&(d=!0),n._destroy(a.removeElements);return s._emit("remove",i.concat()),d&&l&&s.layout("instant"===l,typeof l===at?l:r),i},o.prototype.show=function(t,e){return this._isDestroyed?this:T(this,"show",t,e)},o.prototype.hide=function(t,e){return this._isDestroyed?this:T(this,"hide",t,e)},o.prototype.filter=function(t,e){var i,n,o,s=this,a=s._items,l=typeof t,d=l===lt,h=l===at,f=e||{},u=!0===f.instant,g=f.layout?f.layout:f.layout===r,_=typeof f.onFinish===at?f.onFinish:null,p=[],c=[],m=-1;if(s._isDestroyed||!a.length)return s;if(i=_?function(){++m&&_(p.concat(),c.concat())}:gt,h||d)for(o=0;o<a.length;o++)n=a[o],(h?t(n):pt(n._element,t))?p.push(n):c.push(n);return p.length?s.show(p,{instant:u,onFinish:i,layout:!1}):i(),c.length?s.hide(c,{instant:u,onFinish:i,layout:!1}):i(),(p.length||c.length)&&(s._emit("filter",p.concat(),c.concat()),g&&s.layout("instant"===g,typeof g===at?g:r)),s},o.prototype.sort=function(t,e){var i,n,o=this,s=o._items,a=e||{},l=!!a.descending,d=a.layout?a.layout:a.layout===r;if(o._isDestroyed||s.length<2)return o;if(i=s.concat(),typeof t===at)s.sort(function(e,r){var o=t(e,r);return(l&&0!==o?-o:o)||Q(e,r,l,n||(n=B(i)))});else if(typeof t===lt)t=t.trim().split(" ").map(function(t){return t.split(":")}),s.sort(function(e,r){return q(e,r,l,t)||Q(e,r,l,n||(n=B(i)))});else{if(!nt.isArray(t))return o;j(s,t),l&&s.reverse()}return o._emit("sort",s.concat(),i),d&&o.layout("instant"===d,typeof d===at?d:r),o},o.prototype.move=function(t,e,i){var n,o,s,a,l=this,d=l._items,h=i||{},f=h.layout?h.layout:h.layout===r,u="swap"===h.action,g=u?"swap":"move";return l._isDestroyed||d.length<2?l:(n=l._getItem(t),o=l._getItem(e),n&&o&&n!==o&&(s=d.indexOf(n),a=d.indexOf(o),(u?c:m)(d,s,a),l._emit("move",{item:n,fromIndex:s,toIndex:a,action:g}),f&&l.layout("instant"===f,typeof f===at?f:r)),l)},o.prototype.send=function(t,e,i,n){if(this._isDestroyed||e._isDestroyed||this===e)return this;var o=this,s=e,a=n||{},l=a.appendTo||et.body,d=a.layoutSender?a.layoutSender:a.layoutSender===r,h=a.layoutReceiver?a.layoutReceiver:a.layoutReceiver===r;return(t=o._getItem(t))?(t._migrate.start(s,i,l),t._migrate.isActive&&t.isActive()&&(d&&o.layout("instant"===d,typeof d===at?d:r),h&&s.layout("instant"===h,typeof h===at?h:r)),o):o},o.prototype.destroy=function(e){var i,n=this,o=n._element,s=n._items.concat();if(n._isDestroyed)return n;for(n._resizeHandler&&t.removeEventListener("resize",n._resizeHandler),i=0;i<s.length;i++)s[i]._destroy(e);return n._unsetSortGroups(),X(o,n._settings.containerClass),I(o,{height:""}),n._emit("destroy"),n._emitter.destroy(),ht[n._id]=r,n._isDestroyed=!0,n},o.prototype._getItem=function(t){var e,i,n,r,o=this;if(o._isDestroyed||!t)return o._items[0]||null;if(t instanceof s)return t._gridId===o._id?t:null;if(typeof t===dt)return e=t>-1?t:o._items.length+t,o._items[e]||null;for(i=null,r=0;r<o._items.length;r++)if(n=o._items[r],n._element===t){i=n;break}return i},o.prototype._emit=function(){return this._isDestroyed||this._emitter.emit.apply(this._emitter,arguments),this},o.prototype._refreshDimensions=function(){var t,e=this,i=this.getElement(),n=i.getBoundingClientRect(),r=["left","right","top","bottom"];for(e._width=rt.round(n.width),e._height=rt.round(n.height),e._left=rt.round(n.left),e._top=rt.round(n.top),e._padding={},e._border={},t=0;t<r.length;t++)e._padding[r[t]]=rt.round(A(i,"padding-"+r[t])),e._border[r[t]]=rt.round(A(i,"border-"+r[t]+"-width"));return e},o.prototype._setSortGroups=function(t){var e=this,i=[];return e._sortGroups=null,[].concat(t).forEach(function(t){"string"==typeof t&&i.indexOf(t)<0&&(i.push(t),ut[t]||(ut[t]=[]),ut[t].push(e._id))}),i.length&&(e._sortGroups=i),e},o.prototype._unsetSortGroups=function(){var t,e,i,n=this,r=n._sortGroups;if(r){for(e=0;e<r.length;e++)for(t=ut[r[e]],i=0;i<t.length;i++)if(t[i]===n._id){t.splice(i,1);break}n._sortGroups=null}return n},o.prototype._getSortConnections=function(t){var e,i,n,r,o=this,s=t?[o]:[],a=o._sortConnections;if(o._isDestroyed)return s;if(a&&a.length)for(r=0;r<a.length;r++)if((e=ut[a[r]])&&e.length)for(n=0;n<e.length;n++)(i=ht[e[n]])!==o&&s.indexOf(i)<0&&s.push(i);return s},s.prototype.getGrid=function(){return ht[this._gridId]},s.prototype.getElement=function(){return this._element},s.prototype.getWidth=function(){return this._width},s.prototype.getHeight=function(){return this._height},s.prototype.getMargin=function(){return{left:this._margin.left,right:this._margin.right,top:this._margin.top,bottom:this._margin.bottom}},s.prototype.getPosition=function(){return{left:this._left,top:this._top}},s.prototype.isActive=function(){return this._isActive},s.prototype.isVisible=function(){return!this._isHidden},s.prototype.isShowing=function(){return this._isShowing},s.prototype.isHiding=function(){return this._isHiding},s.prototype.isPositioning=function(){return this._isPositioning},s.prototype.isDragging=function(){return!!this._drag&&this._drag._data.isActive},s.prototype.isReleasing=function(){return this._release.isActive},s.prototype._stopLayout=function(t){var e=this;return e._isDestroyed||!e._isPositioning?e:(e._animate.stop(),X(e._element,e.getGrid()._settings.itemPositioningClass),e._isPositioning=!1,t&&K(e._layoutQueue,!0,e),e)},s.prototype._refreshDimensions=function(){var t,e,i,n,r,o,s=this;if(s._isDestroyed||s._isHidden)return s;for(t=s._element,i=["left","right","top","bottom"],r=s._margin=s._margin||{},o=0;o<4;o++)n=rt.round(A(t,"margin-"+i[o])),r[i[o]]=n>0?n:0;return e=t.getBoundingClientRect(),s._width=rt.round(e.width),s._height=rt.round(e.height),s._outerWidth=s._width+r.left+r.right,s._outerHeight=s._height+r.top+r.bottom,s},s.prototype._refreshSortData=function(){var t,e,i=this;return i._isDestroyed||(t={},e=i.getGrid()._settings.sortData,e&&it.keys(e).forEach(function(n){t[n]=e[n](i,i._element)}),i._sortData=t),i},s.prototype._layout=function(t,e){var n,r,o,s,a,l,d,h,f,u,g=this,_=g._element,p=g._isPositioning,c=g._migrate,m=g._release,y=m.isActive&&!1===m.isPositioningStarted;if(g._isDestroyed)return g;if(n=g.getGrid(),r=n._settings,o=y?r.dragReleaseDuration:r.layoutDuration,s=y?r.dragReleaseEasing:r.layoutEasing,a=!t&&!g._skipNextLayoutAnimation&&o>0,u=function(){g._isPositioning&&(g._isPositioning=!1,X(_,r.itemPositioningClass)),m.isActive&&m.stop(),c.isActive&&c.stop(),K(g._layoutQueue,!1,g)},p&&K(g._layoutQueue,!0,g),y&&(m.isPositioningStarted=!0),typeof e===at&&(g._layoutQueue[g._layoutQueue.length]=e),l=m.isActive?m.containerDiffX:c.isActive?c.containerDiffX:0,d=m.isActive?m.containerDiffY:c.isActive?c.containerDiffY:0,a){if(p&&g._isDefaultAnimate?(h=parseFloat(i.hook(_,"translateX"))-l,f=parseFloat(i.hook(_,"translateY"))-d):(h=x(_,"x")-l,f=x(_,"y")-d),g._left===h&&g._top===f)return g._stopLayout(),void u();p||(g._isPositioning=!0,E(_,r.itemPositioningClass)),g._animate.start({translateX:h+l+"px",translateY:f+d+"px"},{translateX:g._left+l,translateY:g._top+d},{duration:o,easing:s,onFinish:u})}else g._stopLayout(),g._skipNextLayoutAnimation=!1,m.isActive&&_.parentNode!==n._element&&c.isActive&&c.container!==n._element||I(_,{transform:"translateX("+(g._left+l)+"px) translateY("+(g._top+d)+"px)"}),u();return g},s.prototype._show=function(t,e){var i,n,r=this,o=r._element,s=r._visibilityQueue,a=typeof e===at?e:null;return r._isDestroyed?r:(i=r.getGrid(),n=i._settings,r._isShowing?t?(i._itemShowHandler.stop(r),K(s,!0,r),a&&(s[s.length]=a),i._itemShowHandler.start(r,t,function(){r._isShowing=!1,K(s,!1,r)})):a&&(s[s.length]=a):r._isHidden?(r._isHiding&&i._itemHideHandler.stop(r),r._isActive=r._isShowing=!0,r._isHidden=r._isHiding=!1,E(o,n.itemVisibleClass),X(o,n.itemHiddenClass),I(o,{display:"block"}),K(s,!0,r),a&&(s[s.length]=a),i._itemShowHandler.start(r,t,function(){r._isShowing=!1,K(s,!1,r)})):a&&a(!1,r),r)},s.prototype._hide=function(t,e){var i,n,r=this,o=r._element,s=r._visibilityQueue,a=typeof e===at?e:null;return r._isDestroyed?r:(i=r.getGrid(),n=i._settings,r._isHiding?t?(i._itemHideHandler.stop(r),K(s,!0,r),a&&(s[s.length]=a),i._itemHideHandler.start(r,t,function(){r._isHiding=!1,I(o,{display:"none"}),K(s,!1,r)})):a&&(s[s.length]=a):r._isHidden?a&&a(!1,r):(r._isShowing&&i._itemShowHandler.stop(r),r._isHidden=r._isHiding=!0,r._isActive=r._isShowing=!1,E(o,n.itemHiddenClass),X(o,n.itemVisibleClass),K(s,!0,r),typeof a===at&&(s[s.length]=a),i._itemHideHandler.start(r,t,function(){r._isHiding=!1,I(o,{display:"none"}),K(s,!1,r)})),r)},s.prototype._destroy=function(t){var e,i,n,o=this,s=o._element;return o._isDestroyed?o:(e=o.getGrid(),i=e._settings,n=e._items.indexOf(o),o._release.destroy(),o._migrate.destroy(),o._stopLayout(!0),e._itemShowHandler.stop(o),e._itemHideHandler.stop(o),o._drag&&o._drag.destroy(),o._animate.destroy(),o._animateChild.destroy(),s.removeAttribute("style"),o._child.removeAttribute("style"),K(o._visibilityQueue,!0,o),X(s,i.itemPositioningClass),X(s,i.itemDraggingClass),X(s,i.itemReleasingClass),X(s,i.itemClass),X(s,i.itemVisibleClass),X(s,i.itemHiddenClass),n>-1&&e._items.splice(n,1),t&&s.parentNode.removeChild(s),ft[o._id]=r,o._isActive=o._isPositioning=o._isHiding=o._isShowing=!1,o._isDestroyed=o._isHidden=!0,o)},h.prototype.on=function(t,e){if(this._isDestroyed)return this;var i=this._events[t]||[];return i[i.length]=e,this._events[t]=i,this},h.prototype.once=function(t,e){var i=this;return this.on(t,function n(){i.off(t,n),e.apply(null,arguments)})},h.prototype.off=function(t,e){if(this._isDestroyed)return this;for(var i=this._events[t]||[],n=i.length;n--;)e===i[n]&&i.splice(n,1);return this},h.prototype.emit=function(t,e,i,n){if(this._isDestroyed)return this;var r,o=this._events[t]||[],s=o.length,a=arguments.length-1;if(s)for(o=o.concat(),r=0;r<s;r++)0===a?o[r]():1===a?o[r](e):2===a?o[r](e,i):o[r](e,i,n);return this},h.prototype.destroy=function(){if(this._isDestroyed)return this;var t,e=it.keys(this._events);for(t=0;t<e.length;t++)this._events[e[t]]=null;return this._isDestroyed=!0,this},f.prototype.start=function(t,e,n){if(!this._isDestroyed){var r=this,o=r._element,s=n||{},a=typeof s.onFinish===at?s.onFinish:null,l={duration:s.duration||300,easing:s.easing||"ease",queue:r._queue};r._isAnimating&&r.stop(),t&&H(o,t),r._isAnimating=!0,a&&(l.complete=function(){a()}),i(o,e,l),i.Utilities.dequeue(o,r._queue)}},f.prototype.stop=function(){!this._isDestroyed&&this._isAnimating&&(this._isAnimating=!1,i(this._element,"stop",this._queue))},f.prototype.destroy=function(){this._isDestroyed||(this.stop(),this._element=null,this._isDestroyed=!0)},u.prototype.destroy=function(){var t=this;return t._isDestroyed||(t.stop(!0),t._isDestroyed=!0),t},u.prototype.getItem=function(){return ft[this._itemId]||null},u.prototype.start=function(t,e,i){var n,r,s,a,l,d,h,u,g,_,p,c,m,y,v=this;return v._isDestroyed?v:(n=v.getItem(),r=n.getElement(),s=n.isVisible(),a=n.getGrid(),l=a._settings,d=t._settings,h=t.getElement(),_=i||et.body,u=a._items.indexOf(n),null===(g=typeof e===dt?e:t._items.indexOf(t._getItem(e)))?v:(n.isPositioning()&&n._stopLayout(!0),v.isActive&&v.stop(!0),n.isReleasing()&&n._release.stop(!0),a._itemShowHandler.stop(n),a._itemHideHandler.stop(n),n._drag&&n._drag.destroy(),n._animate.destroy(),n._animateChild.destroy(),K(n._visibilityQueue,!0,n),X(r,l.itemClass),X(r,l.itemVisibleClass),X(r,l.itemHiddenClass),E(r,d.itemClass),E(r,s?d.itemVisibleClass:d.itemHiddenClass),a._items.splice(u,1),S(t._items,n,g),n._gridId=t._id,n._animate=new o.ItemAnimate(n,r),n._animateChild=new o.ItemAnimate(n,n._child),n._isDefaultAnimate=n._animate instanceof f,p=r.parentNode,_!==p&&(_.appendChild(r),c=G(_,p,!0),m=x(r,"x")+c.left,y=x(r,"y")+c.top,I(r,{transform:"translateX("+m+"px) translateY("+y+"px)"})),I(r,{display:s?"block":"hidden"}),n._refreshDimensions()._refreshSortData(),n._child.removeAttribute("style"),s?t._itemShowHandler.start(n,!0):t._itemHideHandler.start(n,!0),n._drag=d.dragEnabled?new o.ItemDrag(n):null,c=G(_,h,!0),v.isActive=!0,v.container=_,v.containerDiffX=c.left,v.containerDiffY=c.top,a._emit("send",{item:n,fromGrid:a,fromIndex:u,toGrid:t,toIndex:g}),t._emit("receive",{item:n,fromGrid:a,fromIndex:u,toGrid:t,toIndex:g}),v))},u.prototype.stop=function(t){var e,i,n,r,o,s,a=this;return a._isDestroyed||!a.isActive?a:(e=a.getItem(),i=e.getElement(),n=e.getGrid(),r=n.getElement(),a.container!==r&&(o=t?x(i,"x")-a.containerDiffX:e._left,s=t?x(i,"y")-a.containerDiffY:e._top,r.appendChild(i),I(i,{transform:"translateX("+o+"px) translateY("+s+"px)"})),a.isActive=!1,a.container=null,a.containerDiffX=0,a.containerDiffY=0,a)},g.prototype.destroy=function(){var t=this;return t._isDestroyed||(t.stop(!0),t._isDestroyed=!0),t},g.prototype.getItem=function(){return ft[this._itemId]||null},g.prototype.reset=function(){var t,e=this;return e._isDestroyed||(t=e.getItem(),X(t.getElement(),t.getGrid()._settings.itemReleasingClass),e.isActive=!1,e.isPositioningStarted=!1,e.containerDiffX=0,e.containerDiffY=0),e},g.prototype.start=function(){var t,e,i,n=this;return n._isDestroyed||n.isActive?n:(t=n.getItem(),e=t.getElement(),i=t.getGrid(),n.isActive=!0,E(e,i._settings.itemReleasingClass),i._emit("dragReleaseStart",t),t._layout(!1),n)},g.prototype.stop=function(t){var e,i,n,r,o,s,a,l,d=this;return d._isDestroyed||!d.isActive?d:(e=d.getItem(),i=e.getElement(),n=e.getGrid(),r=n.getElement(),o=d.containerDiffX,s=d.containerDiffY,d.reset(),i.parentNode!==r&&(a=t?x(i,"x")-o:e._left,l=t?x(i,"y")-s:e._top,r.appendChild(i),I(i,{transform:"translateX("+a+"px) translateY("+l+"px)"})),t||n._emit("dragReleaseEnd",e),d)},_.defaultStartPredicate=function(e,i){var n,r,o,s=e.getElement(),a=e._drag,l=a.getGrid(),d=l._settings.dragStartPredicate||{},h=rt.abs(d.distance)||0,f=rt.abs(d.delay)||0,u="string"==typeof d.handle&&d.handle;if(!i.isFinal){if(u&&!pt(i.srcEvent.target,u))return!1;if(i.distance<h||i.deltaTime<f)return;return!0}n="a"===s.tagName.toLowerCase(),r=s.getAttribute("href"),o=s.getAttribute("target"),n&&r&&rt.abs(i.deltaX)<2&&rt.abs(i.deltaY)<2&&i.deltaTime<200&&(o&&"_self"!==o?t.open(r,o):t.location.href=r)},_.defaultSortPredicate=function(t){var e,i,n,r,o,s=t._drag,a=s._data,l=s.getGrid(),d=l._settings.dragSortPredicate||{},h=d.threshold||50,f=d.action||"move",u={width:t._width,height:t._height,left:rt.round(a.elementClientX),top:rt.round(a.elementClientY)},g=J(u,l,h),_=0,p=0,c=-1;if(!g)return!1;for(g===l?(u.left=rt.round(a.gridX)+t._margin.left,u.top=rt.round(a.gridY)+t._margin.top):(_=g._left+g._border.left+g._padding.left,p=g._top+g._border.top+g._padding.top),o=0;o<g._items.length;o++)n=g._items[o],n._isActive&&n!==t&&(i=!0,(r=W(u,{width:n._width,height:n._height,left:rt.round(n._left)+n._margin.left+_,top:rt.round(n._top)+n._margin.top+p}))>c&&(e=o,c=r));return c<h&&t.getGrid()!==g&&(e=i?-1:0,c=1/0),c>=h&&{grid:g,index:e,action:f}},_.prototype.destroy=function(){var t=this;return t._isDestroyed||(t.stop(),t._hammer.destroy(),t.getItem()._element.removeEventListener("dragstart",$,!1),t._isDestroyed=!0),t},_.prototype.getItem=function(){return ft[this._itemId]||null},_.prototype.getGrid=function(){return ht[this._gridId]||null}, | ||
_.prototype.reset=function(){var t=this,e=t._data;return e.isActive=!1,e.container=null,e.containingBlock=null,e.startEvent=null,e.currentEvent=null,e.scrollers=[],e.left=0,e.top=0,e.gridX=0,e.gridY=0,e.elementClientX=0,e.elementClientY=0,e.containerDiffX=0,e.containerDiffY=0,t},_.prototype.checkOverlap=function(){var t,e,i,n,r,o=this,s=o.getItem(),a=o._sortPredicate(s,o._data.currentEvent);return v(a)&&typeof a.index===dt?(t=s.getGrid(),e=t._items.indexOf(s),i=a.grid||t,n=a.index,r="swap"===a.action?"swap":"move",t===i?(n=p(t._items,n),e!==n&&(("swap"===r?c:m)(t._items,e,n),t._emit("move",{item:s,fromIndex:e,toIndex:n,action:r}),t.layout())):(s._gridId=i._id,o._isMigrating=s._gridId!==o._gridId,t._items.splice(e,1),S(i._items,s,n),n=i._items.indexOf(s),s._sortData=null,t._emit("send",{item:s,fromGrid:t,fromIndex:e,toGrid:i,toIndex:n}),i._emit("receive",{item:s,fromGrid:t,fromIndex:e,toGrid:i,toIndex:n}),t.layout(),i.layout()),o):o},_.prototype.finishMigration=function(){var t,e,i,n=this,r=n.getItem(),s=r._release,a=r.getElement(),l=r.getGrid(),d=l.getElement(),h=l._settings,u=h.dragContainer||d,g=n.getGrid()._settings,_=a.parentNode;return n._isMigrating=!1,n.destroy(),r._animate.destroy(),r._animateChild.destroy(),X(a,g.itemClass),X(a,g.itemVisibleClass),X(a,g.itemHiddenClass),E(a,h.itemClass),E(a,h.itemVisibleClass),r._animate=new o.ItemAnimate(r,a),r._animateChild=new o.ItemAnimate(r,r._child),r._isDefaultAnimate=r._animate instanceof f,u!==_&&(u.appendChild(a),i=G(_,u,!0),t=x(a,"x")+i.left,e=x(a,"y")+i.top,I(a,{transform:"translateX("+t+"px) translateY("+e+"px)"})),r._refreshDimensions()._refreshSortData(),r._child.removeAttribute("style"),l._itemShowHandler.start(r,!0),r._drag=h.dragEnabled?new o.ItemDrag(r):null,i=G(u,d,!0),s.containerDiffX=i.left,s.containerDiffY=i.top,s.start(),n},_.prototype.stop=function(){var t,e,i,n=this,r=n._data;if(!r.isActive)return n;if(n._isMigrating)return void n.finishMigration(r.currentEvent);for(t=n.getItem()._element,e=n.getGrid(),i=0;i<r.scrollers.length;i++)r.scrollers[i].removeEventListener("scroll",n._scrollHandler);return n._checkSortOverlap("cancel"),t.parentNode!==e._element&&(e._element.appendChild(t),I(t,{transform:"translateX("+r.gridX+"px) translateY("+r.gridY+"px)"})),X(t,e._settings.itemDraggingClass),n.reset(),n},_.prototype.onStart=function(t){var e,i,n,r,o,s,a,l,d,h,f,u,g,_,p=this,c=p.getItem();if(c._isActive){for(e=c._element,i=p.getGrid(),n=i._settings,r=p._data,o=c._release,c.isPositioning()&&c._stopLayout(!0),c._migrate.isActive&&c._migrate.stop(!0),c.isReleasing()&&o.reset(),r.isActive=!0,r.startEvent=r.currentEvent=t,s=x(e,"x"),a=x(e,"y"),l=i._element,r.container=d=n.dragContainer||l,r.containingBlock=h=k(d,!0),r.left=r.gridX=s,r.top=r.gridY=a,d!==l&&(g=e.parentNode===d,g||d.appendChild(e),f=G(h,l),r.containerDiffX=f.left,r.containerDiffY=f.top,g?(r.gridX=s-r.containerDiffX,r.gridY=a-r.containerDiffY):(r.left=s+r.containerDiffX,r.top=a+r.containerDiffY,I(e,{transform:"translateX("+r.left+"px) translateY("+r.top+"px)"}))),u=e.getBoundingClientRect(),r.elementClientX=u.left,r.elementClientY=u.top,r.scrollers=O(e),d!==l&&(r.scrollers=y(r.scrollers.concat(l).concat(O(l)))),_=0;_<r.scrollers.length;_++)r.scrollers[_].addEventListener("scroll",p._scrollHandler);return E(e,n.itemDraggingClass),i._emit("dragStart",c,t),p}},_.prototype.onMove=function(t){var e,i,n,r,o,s,a=this,l=a.getItem();return l._isActive?(e=l._element,i=a.getGrid(),n=i._settings,r=a._data,o=t.deltaX-r.currentEvent.deltaX,s=t.deltaY-r.currentEvent.deltaY,r.currentEvent=t,r.left+=o,r.top+=s,r.gridX+=o,r.gridY+=s,r.elementClientX+=o,r.elementClientY+=s,I(e,{transform:"translateX("+r.left+"px) translateY("+r.top+"px)"}),n.dragSort&&a._checkSortOverlap(),i._emit("dragMove",l,t),a):void a.stop()},_.prototype.onScroll=function(t){var e,i=this,n=i.getItem(),r=n._element,o=i.getGrid(),s=o._settings,a=i._data,l=o._element,d=r.getBoundingClientRect(),h=a.elementClientX-d.left,f=a.elementClientY-d.top;return a.container!==l&&(e=G(a.containingBlock,l),a.containerDiffX=e.left,a.containerDiffY=e.top),a.left+=h,a.top+=f,a.gridX=a.left-a.containerDiffX,a.gridY=a.top-a.containerDiffY,I(r,{transform:"translateX("+a.left+"px) translateY("+a.top+"px)"}),s.dragSort&&i._checkSortOverlap(),o._emit("dragScroll",n,t),i},_.prototype.onEnd=function(t){var e,i=this,n=i.getItem(),r=n._element,o=i.getGrid(),s=o._settings,a=i._data,l=n._release;if(!n._isActive)return void i.stop();for(s.dragSort&&i._checkSortOverlap("finish"),e=0;e<a.scrollers.length;e++)a.scrollers[e].removeEventListener("scroll",i._scrollHandler);return X(r,s.itemDraggingClass),l.containerDiffX=a.containerDiffX,l.containerDiffY=a.containerDiffY,i.reset(),o._emit("dragEnd",n,t),i._isMigrating?i.finishMigration():l.start(),i},o}); |
{ | ||
"name": "muuri", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "Responsive, sortable, filterable and draggable grid layouts.", | ||
@@ -16,4 +16,5 @@ "keywords": [ | ||
"author": { | ||
"name": "Haltu Oy", | ||
"url" : "http://www.haltu.fi/" | ||
"name": "Niklas Rämö", | ||
"email": "inramo@gmail.com", | ||
"url": "https://github.com/niklasramo" | ||
}, | ||
@@ -24,23 +25,38 @@ "repository": { | ||
}, | ||
"main": "./muuri.js", | ||
"main": "muuri.js", | ||
"files": [ | ||
"muuri.js", | ||
"muuri.min.js" | ||
], | ||
"scripts": { | ||
"test": "gulp" | ||
}, | ||
"optionalDependencies": { | ||
"hammerjs": "^2.0.0", | ||
"velocity-animate": "^1.2.0" | ||
}, | ||
"devDependencies": { | ||
"dotenv": "^2.0.0", | ||
"dotenv": "^4.0.0", | ||
"gulp": "^3.9.1", | ||
"gulp-jscs": "^3.0.0", | ||
"gulp-eslint": "^3.0.1", | ||
"gulp-rename": "^1.2.2", | ||
"gulp-size": "^2.1.0", | ||
"gulp-uglify": "^1.5.3", | ||
"gulp-util": "^3.0.7", | ||
"karma": "^1.3.0", | ||
"karma-coverage": "^1.1.1", | ||
"karma-qunit": "^1.2.0", | ||
"karma-sauce-launcher": "^1.0.0", | ||
"gulp-uglify": "^2.1.0", | ||
"gulp-util": "^3.0.8", | ||
"hammer-simulator": "^0.0.1", | ||
"hammerjs": "^2.0.8", | ||
"jquery": "^3.2.1", | ||
"karma": "^1.5.0", | ||
"karma-chrome-launcher": "^2.0.0", | ||
"karma-firefox-launcher": "^1.0.1", | ||
"karma-qunit": "^1.2.1", | ||
"karma-sauce-launcher": "^1.1.0", | ||
"karma-story-reporter": "^0.3.1", | ||
"qunitjs": "^1.23.1", | ||
"rimraf": "^2.5.4", | ||
"run-sequence": "^1.2.2" | ||
"mezr": "^0.6.1", | ||
"prosthetic-hand": "^1.3.1", | ||
"qunitjs": "^2.2.0", | ||
"rimraf": "^2.6.1", | ||
"run-sequence": "^1.2.2", | ||
"velocity-animate": "^1.5.0" | ||
} | ||
} |
2029
README.md
@@ -5,49 +5,16 @@ # Muuri | ||
Muuri's layout system allows positioning the grid items within the container in pretty much any way imaginable. The default "First Fit" bin packing layout algorithm generates similar layouts as [Packery](https://github.com/metafizzy/packery) and [Masonry](http://masonry.desandro.com/). The implementation is heavily based on the "maxrects" approach as described by Jukka Jylänki in his research [A Thousand Ways to Pack the Bin](http://clb.demon.fi/files/RectangleBinPack.pdf). However, you can also provide your own layout algorithm to position the items in any way you want. | ||
Muuri's layout system allows positioning the grid items pretty much any way imaginable. The default "First Fit" bin packing layout algorithm generates similar layouts as [Packery](https://github.com/metafizzy/packery) and [Masonry](http://masonry.desandro.com/). The implementation is heavily based on the "maxrects" approach as described by Jukka Jylänki in his research [A Thousand Ways to Pack the Bin](http://clb.demon.fi/files/RectangleBinPack.pdf). However, you can also provide your own layout algorithm to position the items in any way you want. | ||
Muuri uses [Velocity](https://github.com/julianshapiro/velocity) for animating the grid items (positioining/showing/hiding) and [Hammer.js](https://github.com/hammerjs/hammer.js) for handling the dragging. Hammer.js is an optional dependency that is only required if dragging is enabled, but Velocity is a hard dependency. | ||
Muuri uses [Velocity](http://velocityjs.org/) for animating the grid items (positioining/showing/hiding) and [Hammer.js](http://hammerjs.github.io/) for handling the dragging. And if you're wondering about the name of the library "muuri" is Finnish meaning a wall. | ||
And if you're wondering about the name of the library "muuri" is Finnish meaning a wall. | ||
**A word of warning.** Muuri is currently under active development and might be still a bit rough on the edges so production use is not recommended just yet. But when did that ever stop you ;) | ||
## Table of contents | ||
* [Getting started](#getting-started) | ||
* [Options](#options) | ||
* [Methods](#methods) | ||
* [muuri.on( event, listener )](#muurion-event-listener-) | ||
* [muuri.off( eventName, listener )](#muurioff-eventname-listener-) | ||
* [muuri.refresh( [targets] )](#muurirefresh-targets-) | ||
* [muuri.get( [targets], [state] )](#muuriget-targets-state-) | ||
* [muuri.add( elements, [index] )](#muuriadd-elements-index-) | ||
* [muuri.remove( targets, [removeElement] )](#muuriremove-targets-removeelement-) | ||
* [muuri.synchronize()](#muurisynchronize) | ||
* [muuri.layout( [instant], [callback] )](#muurilayout-instant-callback-) | ||
* [muuri.show( targets, [instant], [callback] )](#muurishow-targets-instant-callback-) | ||
* [muuri.hide( targets, [instant], [callback] )](#muurihide-targets-instant-callback-) | ||
* [muuri.indexOf( target )](#muuriindexof-target-) | ||
* [muuri.move( targetFrom, targetTo )](#muurimove-targetfrom-targetto-) | ||
* [muuri.swap( targetA, targetB )](#muuriswap-targeta-targetb-) | ||
* [muuri.destroy()](#muuridestroy) | ||
* [Events](#events) | ||
* [refresh](#refresh) | ||
* [synchronize](#synchronize) | ||
* [layoutstart](#layoutstart) | ||
* [layoutend](#layoutend) | ||
* [showstart](#showstart) | ||
* [showend](#showend) | ||
* [hidestart](#hidestart) | ||
* [hideend](#hideend) | ||
* [move](#move) | ||
* [swap](#swap) | ||
* [add](#add) | ||
* [remove](#remove) | ||
* [dragstart](#dragstart) | ||
* [dragmove](#dragmove) | ||
* [dragscroll](#dragscroll) | ||
* [dragend](#dragend) | ||
* [releasestart](#releasestart) | ||
* [releaseend](#releaseend) | ||
* [destroy](#destroy) | ||
* [API](#api) | ||
* [Grid constructor](#grid-constructor) | ||
* [Grid options](#grid-options) | ||
* [Grid methods](#grid-methods) | ||
* [Grid events](#grid-events) | ||
* [Item methods](#item-methods) | ||
* [Credits](#credits) | ||
* [License](#license) | ||
@@ -57,22 +24,51 @@ | ||
### 1. Get Muuri | ||
Download from GitHub: | ||
* [muuri.js](https://raw.githubusercontent.com/haltu/muuri/0.3.0/muuri.js) - for development (not minified, with comments). | ||
* [muuri.min.js](https://raw.githubusercontent.com/haltu/muuri/0.3.0/muuri.min.js) - for production (minified, no comments). | ||
Or link directly via CDNJS: | ||
```html | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/muuri/0.3.0/muuri.js"></script> | ||
<script src="https://cdnjs.cloudflare.com/ajax/libs/muuri/0.3.0/muuri.min.js"></script> | ||
``` | ||
Or install with [npm](https://www.npmjs.com/): | ||
```bash | ||
npm install muuri | ||
``` | ||
Or install with [bower](http://bower.io): | ||
```bash | ||
bower install muuri | ||
``` | ||
### 2. Get the dependencies | ||
Muuri depends on the following libraries: | ||
* [Velocity](https://github.com/julianshapiro/velocity) (1.2.x) | ||
* [Hammer.js](https://github.com/hammerjs/hammer.js) (2.0.x) optional, required only if you are using the dragging feature | ||
* [Velocity](https://github.com/julianshapiro/velocity) (v1.2.0+) | ||
* By default Muuri users Velocity to power all the animations. However, it is possible to replace Velocity with any other animation engine by overwriting the `Muuri.ItemAnimate` constructor. | ||
* [Hammer.js](https://github.com/hammerjs/hammer.js) (v2.0.0+) | ||
* Hammer.js is an optional dependency and only required if the dragging is enabled. Currently there is no easy way to use another library for handling the drag interaction. Almost all of the drag related logic exists within `Muuri.ItemDrag` constructor, which is instantiated for each item, so if you really need to customize the drag behaviour beyond what is available via the options you can replace the `Muuri.ItemDrag` constructor with your own implementation (fingers crossed). | ||
**First, include Muuri and it's dependencies in your site.** | ||
### 3. Add the script tags | ||
Include Muuri inside the *body* element in your site and make sure to include the dependencies before Muuri. Muuri has to be inside the body element because it does some feature checking during initiation and might not work correctly if it does not have access to `document.body`. | ||
```html | ||
<script src="velocity.js"></script> | ||
<script src="hammer.js"></script> | ||
<!-- Needs to be within in body element or have access to body element --> | ||
<!-- Muuri needs to have access to document.body when initiated --> | ||
<script src="muuri.js"></script> | ||
``` | ||
An important note for including Muuri to your site is that it needs to have access to the `body` element when it's loaded. Muuri does some feature checking on init and might not work correctly if it does not have access to the `body` element. | ||
### 4. Add the markup | ||
**Then, define your grid markup.** | ||
* Every grid must have a container element. | ||
* Grid items must always consist of at least two elements. The outer element is used for positioning the item and the inner element (first direct child) is used for animating the item's visibility (show/hide methods). You can insert any markup you wish inside the inner item element. | ||
* Every grid must have a container element and item element(s) within the container element. | ||
* A grid item must always consist of at least two elements. The outer element is used for positioning the item and the inner element (first direct child) is used for animating the item's visibility (show/hide methods). You can insert any markup you wish inside the inner item element. | ||
```html | ||
@@ -83,3 +79,5 @@ <div class="grid"> | ||
<div class="item-content"> | ||
<!-- Safe zone, enter your custom markup --> | ||
This can be anything. | ||
<!-- Safe zone ends --> | ||
</div> | ||
@@ -90,5 +88,7 @@ </div> | ||
<div class="item-content"> | ||
<!-- Safe zone, enter your custom markup --> | ||
<div class="my-custom-content"> | ||
Yippee! | ||
</div> | ||
<!-- Safe zone ends --> | ||
</div> | ||
@@ -100,8 +100,8 @@ </div> | ||
**Next, let's apply some styles.** | ||
### 5. Add the styles | ||
* The grid element must be "positioned" meaning that it's CSS position property must be set to *relative*, *absolute* or *fixed*. Also note that Muuri automatically resizes the container element depending on the area the items cover. | ||
* The item elements must have their CSS position set to *absolute* and their display property set to *block*, unless of course the elements have their display set to *block* inherently. | ||
* The item elements must not have any CSS transitions or animations applied to them since it might conflict with Velocity's animations. | ||
* You can control the gaps between the tiles by giving some margin to the item elements. | ||
* The container element must be "positioned" meaning that it's CSS position property must be set to *relative*, *absolute* or *fixed*. Also note that Muuri automatically resizes the container element's width/height depending on the area the items cover and the layout algorithm configuration. | ||
* The item elements must have their CSS position set to *absolute* and their display property set to *block*. Muuri actually enforces the `display:block;` rule and adds it as an inline style to all item elements, just in case. | ||
* The item elements must not have any CSS transitions or animations applied to them, because they might conflict with Velocity's animations. However, the container element can have transitions applied to it if you want it to animate when it's size changes after the layout operation. | ||
* You can control the gaps between the tiles by giving some margin to the item elements. Note that Muuri's items are positioned relative to the container element's content with padding excluded (intentionally) to provide more control over the gutter spacing (normally an absolutely positioned element is positioned relative to the containing element's content with padding included). | ||
@@ -134,151 +134,96 @@ ```css | ||
**Finally, initiate a Muuri instance.** | ||
### 6. Fire it up | ||
* The bare minimum configuration is demonstrated below. You must always provide Muuri with the container element and the initial item elements. | ||
* Be sure to check out the all the available [options](#options), [methods](#methods) and [events](#events). | ||
The bare minimum configuration is demonstrated below. You must always provide the container element (or a selector so Muuri can fetch the element for you), everything else is optional. | ||
```javascript | ||
var grid = new Muuri({ | ||
container: document.getElementsByClassName('grid')[0], | ||
items: document.getElementsByClassName('item') | ||
}); | ||
var grid = new Muuri('.grid'); | ||
``` | ||
## Options | ||
## API | ||
* **`container`** — *element* | ||
### Grid constructor | ||
`Muuri` is a constructor function and should be always instantiated with the `new` keyword. For the sake of clarity, we refer to a Muuri instance as *grid* throughout the documentation. | ||
**Syntax** | ||
`Muuri( element, [options] )` | ||
**Parameters** | ||
* **element** — *element* / *string* | ||
* Default value: `null`. | ||
* The container element. Must be always defined. | ||
* **`items`** — *array of elements* | ||
* Default value: `null`. | ||
* The initial item elements wrapped in an array. The elements must be children of the container element. | ||
* **`positionDuration`** — *number* | ||
* Default value: `300`. | ||
* The duration for item's positioning animation in milliseconds. Set to `0` to disable. | ||
* **`positionEasing`** — *string / array* | ||
* Default value: `"ease-out"`. | ||
* The easing for item's positioning animation. Read [Velocity's easing documentation](http://julian.com/research/velocity/#easing) for more info on possible easing values. | ||
* **`show`** — *object* | ||
* Default value: `{duration: 300, easing: "ease-out"}`. | ||
* The object should contain *duration* (integer, milliseconds) and [*easing*](http://julian.com/research/velocity/#easing) properties. Set to *null* to disable hide animation altogether. | ||
* **`hide`** — *object* | ||
* Default value: `{duration: 300, easing: "ease-out"}`. | ||
* The object should contain *duration* (integer, milliseconds) and [*easing*](http://julian.com/research/velocity/#easing) properties. Set to *null* to disable hide animation altogether. | ||
* **`layout`** — *array / function / string* | ||
* Default value: `"firstFit"`. | ||
* Define the layout method to be used for calculating the positions of the items. If you provide a string or an array Muuri will try to locate a registered layout method in `Muuri.Layout.methods` object. Currently there is only one built-in method: `"firstFit"`. | ||
* The array syntax is the only way to use the built-in layout methods and provide arguments for them. The first value should be a string (name of the method) and the second value (optional) should be a configuration object, e.g. `["firstFit", {horizontal: true}]`. | ||
* You can always just provide a function which will receive a `Muuri.Layout` instance as it's context which you can manipulate as much as you want to get the items to the wanted positions. More info about rolling your own layout method is coming up later on, but in the meantime you can check the source code and see how the default method is implemented. | ||
* Available methods and related settings: | ||
* `"firstFit"` | ||
* `horizontal` (type: *boolean*, default: `false`) | ||
* When `true` the grid works in landscape mode (grid expands to the right). Use for horizontally scrolling sites. When `false` the grid works in "portrait" mode and expands downwards. | ||
* `alignRight` (type: *boolean*, default: `false`) | ||
* When `true` the items are aligned from right to left. | ||
* `alignBottom` (type: *boolean*, default: `false`) | ||
* When `true` the items are aligned from the bottom up. | ||
* `fillGaps` (type: *boolean*, default: `false`) | ||
* When `true` the algorithm goes through every item in order and places each item to the first available free slot, even if the slot happens to be visually *before* the previous element's slot. Practically this means that the items might not end up visually in order, but there will be less gaps in the grid. By default this options is `false` which basically means that the following condition will be always true when calculating the layout: `nextItem.top > prevItem.top || (nextItem.top === prevItem.top && nextItem.left > prevItem.left)`. This also means that the items will be visually in order. | ||
* **`layoutOnResize`** — *null / number* | ||
* Default value: `100`. | ||
* Should Muuri automatically trigger layout on window resize? Set to `null` to disable. When a number (`0` or greater) is provided Muuri will automatically trigger layout when window is resized. The provided number equals to the amount of time (in milliseconds) that is waited before the layout is triggered after each resize event. The layout method is wrapped in a debouned function in order to avoid unnecessary layout calls. | ||
* **`layoutOnInit`** — *boolean* | ||
* Default value: `true`. | ||
* Should Muuri trigger layout automatically on init? | ||
* **`dragEnabled`** — *boolean* | ||
* Default value: `false`. | ||
* Should items be draggable? | ||
* **`dragPredicate`** — *null / function* | ||
* Default value: `null`. | ||
* A function that determines when dragging should start. Set to null to use the default predicate. | ||
* **`dragSort`** — *boolean* | ||
* Default value: `true`. | ||
* Should the items be sorted during drag? | ||
* **`dragContainer`** — *null / element* | ||
* Default value: `null`. | ||
* Which item should the dragged item be appended to for the duration of the drag? If `null` is provided the item's muuri container element will be used. | ||
* **`dragReleaseDuration`** — *number* | ||
* Default value: `300`. | ||
* The duration for item's drag release animation. Set to `0` to disable. | ||
* **`dragReleaseEasing`** — *string / array* | ||
* Default value: `"ease-out"`. | ||
* The easing for item's drag release animation. Read [Velocity's easing documentation](http://julian.com/research/velocity/#easing) for more info on possible easing values. | ||
* **`dragOverlapInterval`** — *number* | ||
* Default value: `50`. | ||
* When an item is dragged around the grid Muuri automatically checks if the item overlaps another item enough to move the item in it's place. The overlap check method is debounced and this option defines the debounce interval in milliseconds. In other words, this is option defines the amount of time the dragged item must be still before an overlap is checked. | ||
* **`dragOverlapTolerance`** — *number* | ||
* Default value: `50`. | ||
* Allowed values: `1` - `100`. | ||
* How many percent the intersection area between the dragged item and the compared item should be from the maximum potential intersection area between the two items in order to justify for the dragged item's replacement. | ||
* **`dragOverlapAction`** — *string* | ||
* Default value: `"move"`. | ||
* Allowed values: `"move"`, `"swap"`. | ||
* Should the dragged item be *moved* to the new position or should it *swap* places with the item it overlaps? | ||
* **`containerClass`** — *string* | ||
* Default value: `"muuri"`. | ||
* Container element classname. | ||
* **`itemClass`** — *string* | ||
* Default value: `"muuri-item"`. | ||
* Item element classname. | ||
* **`shownClass`** — *string* | ||
* Default value: `"muuri-shown"`. | ||
* Visible item classname. | ||
* **`hiddenClass`** — *string* | ||
* Default value: `"muuri-hidden"`. | ||
* Hidden item classname. | ||
* **`positioningClass`** — *string* | ||
* Default value: `"muuri-positioning"`. | ||
* This classname will be added to the item element for the duration of positioing. | ||
* **`draggingClass`** — *string* | ||
* Default value: `"muuri-dragging"`. | ||
* This classname will be added to the item element for the duration of drag. | ||
* **`releasingClass`** — *string* | ||
* Default value: `"muuri-releasing"`. | ||
* This classname will be added to the item element for the duration of release. | ||
* You can provide the element directly or use a selector (string) which uses [querySelectorAll()](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) internally. The first element of the query's result will be used. | ||
* **options** — *object* | ||
* Optional. Check out the [detailed options reference](#grid-options). | ||
**Modify default settings** | ||
**Default options** | ||
The default settings are stored in `Muuri.defaultSettings` object. | ||
The default options are stored in `Muuri.defaultOptions` object, which in it's default state contains the following configuration: | ||
```javascript | ||
Muuri.defaultSettings.containerDuration = 400; | ||
Muuri.defaultSettings.dragOverlapAction = 'swap'; | ||
``` | ||
{ | ||
**Quick reference** | ||
// Item elements | ||
items: '*', | ||
```javascript | ||
var defaults = { | ||
// Default show animation | ||
showDuration: 300, | ||
showEasing: 'ease', | ||
// Container | ||
container: null, | ||
// Default hide animation | ||
hideDuration: 300, | ||
hideEasing: 'ease', | ||
// Items | ||
items: [], | ||
positionDuration: 300, | ||
positionEasing: 'ease-out', | ||
show: { | ||
duration: 300, | ||
easing: 'ease-out' | ||
// Custom show/hide animations | ||
showAnimation: null, | ||
hideAnimation: null, | ||
// Item's visible/hidden state styles | ||
visibleStyles: { | ||
opacity: 1, | ||
scale: 1 | ||
}, | ||
hide: { | ||
duration: 300, | ||
easing: 'ease-out' | ||
hiddenStyles: { | ||
opacity: 0, | ||
scale: 0.5 | ||
}, | ||
// Layout | ||
layout: 'firstFit', | ||
layout: { | ||
fillGaps: false, | ||
horizontal: false, | ||
alignRight: false, | ||
alignBottom: false | ||
}, | ||
layoutOnResize: 100, | ||
layoutOnInit: true, | ||
layoutDuration: 300, | ||
layoutEasing: 'ease', | ||
// Sorting | ||
sortData: null, | ||
// Drag & Drop | ||
dragEnabled: false, | ||
dragPredicate: null, | ||
dragContainer: null, | ||
dragStartPredicate: { | ||
distance: 0, | ||
delay: 0, | ||
handle: false | ||
}, | ||
dragSort: true, | ||
dragContainer: null, | ||
dragSortInterval: 100, | ||
dragSortPredicate: { | ||
threshold: 50, | ||
action: 'move' | ||
}, | ||
dragSortGroup: null, | ||
dragSortWith: null, | ||
dragReleaseDuration: 300, | ||
dragReleaseEasing: 'ease-out', | ||
dragOverlapInterval: 50, | ||
dragOverlapTolerance: 50, | ||
dragOverlapAction: 'move', | ||
dragReleaseEasing: 'ease', | ||
dragHammerSettings: { | ||
touchAction: 'none' | ||
}, | ||
@@ -288,221 +233,781 @@ // Classnames | ||
itemClass: 'muuri-item', | ||
shownClass: 'muuri-shown', | ||
hiddenClass: 'muuri-hidden', | ||
positioningClass: 'muuri-positioning', | ||
draggingClass: 'muuri-dragging', | ||
releasingClass: 'muuri-releasing' | ||
itemVisibleClass: 'muuri-item-shown', | ||
itemHiddenClass: 'muuri-item-hidden', | ||
itemPositioningClass: 'muuri-item-positioning', | ||
itemDraggingClass: 'muuri-item-dragging', | ||
itemReleasingClass: 'muuri-item-releasing' | ||
}; | ||
} | ||
``` | ||
## Methods | ||
You can modify the default options easily: | ||
### `muuri.on( event, listener )` | ||
```javascript | ||
Muuri.defaultOptions.showDuration = 400; | ||
Muuri.defaultOptions.dragSortPredicate.action = 'swap'; | ||
``` | ||
Bind an event on the Muuri instance. | ||
```javascript | ||
// Minimum configuration. | ||
var gridA = new Muuri('.grid-a'); | ||
**Parameters** | ||
// Providing some options. | ||
var gridB = new Muuri('.grid-b', { | ||
items: '.item' | ||
}); | ||
``` | ||
* **event** — *string* | ||
* **listener** — *function* | ||
### Grid options | ||
**Returns** — *object* | ||
* [items](#items-) | ||
* [showDuration](#showduration-) | ||
* [showEasing](#showeasing-) | ||
* [hideDuration](#hideduration-) | ||
* [hideEasing](#hideeasing-) | ||
* [visibleStyles](#visiblestyles-) | ||
* [hiddenStyles](#hiddenstyles-) | ||
* [layout](#layout-) | ||
* [layoutOnResize](#layoutonresize-) | ||
* [layoutOnInit](#layoutoninit-) | ||
* [layoutDuration](#layoutduration-) | ||
* [layoutEasing](#layouteasing-) | ||
* [sortData](#sortdata-) | ||
* [dragEnabled](#dragenabled-) | ||
* [dragContainer](#dragcontainer-) | ||
* [dragStartPredicate](#dragstartpredicate-) | ||
* [dragSort](#dragsort-) | ||
* [dragSortInterval](#dragsortinterval-) | ||
* [dragSortPredicate](#dragsortpredicate-) | ||
* [dragSortGroup](#dragsortgroup-) | ||
* [dragSortWith](#dragsortconnections-) | ||
* [dragReleaseDuration](#dragreleaseduration-) | ||
* [dragReleaseEasing](#dragreleaseeasing-) | ||
* [containerClass](#containerclass-) | ||
* [itemClass](#itemclass-) | ||
* [itemVisibleClass](#itemvisibleclass-) | ||
* [itemHiddenClass](#itemhiddenclass-) | ||
* [itemPositioningClass](#itempositioningclass-) | ||
* [itemDraggingClass](#itemdraggingclass-) | ||
* [itemReleasingClass](#itemreleasingclass-) | ||
Returns the instance. | ||
### items | ||
**Examples** | ||
The initial item elements, which should be children of the container element. All elements that are not children of the container will be appended to the container. You can provide an *array* of elements, a [*node list*](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) or a selector (string). If you provide a selector Muuri uses it to filter the current child elements of the container element and sets them as initial items. By default all current child elements of the provided container element are used as initial items. | ||
* Default value: `'*'`. | ||
* Accepted types: array (of elements), [node list](https://developer.mozilla.org/en-US/docs/Web/API/NodeList), string, null. | ||
```javascript | ||
muuri.on('layoutend', function (items) { | ||
console.log(items); | ||
// Use specific items. | ||
var grid = new Muuri(elem, { | ||
items: [elemA, elemB, elemC] | ||
}); | ||
// Use node list. | ||
var grid = new Muuri(elem, { | ||
items: elem.querySelectorAll('.item') | ||
}); | ||
// Use selector. | ||
var grid = new Muuri(elem, { | ||
items: '.item' | ||
}); | ||
``` | ||
| ||
### showDuration | ||
### `muuri.off( eventName, listener )` | ||
Show animation duration in milliseconds. Set to `0` to disable show animation. | ||
Unbind an event from the Muuri instance. | ||
* Default value: `300`. | ||
* Accepted types: number. | ||
**Parameters** | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
showDuration: 600 | ||
}); | ||
``` | ||
* **event** — *string* | ||
* **listener** — *function* | ||
### showEasing | ||
**Returns** — *object* | ||
Show animation easing. Accepts any valid [Velocity.js easing](http://velocityjs.org/#easing) value. | ||
Returns the instance. | ||
* Default value: `'ease'`. | ||
* Accepted types: array, string. | ||
**Examples** | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
showEasing: 'ease-out' | ||
}); | ||
``` | ||
### hideDuration | ||
Hide animation duration in milliseconds. Set to `0` to disable hide animation. | ||
* Default value: `300`. | ||
* Accepted types: number. | ||
```javascript | ||
var listener = function (items) { | ||
console.log(items); | ||
}; | ||
var grid = new Muuri(elem, { | ||
hideDuration: 600 | ||
}); | ||
``` | ||
muuri | ||
.on('layoutend', listener) | ||
.off('layoutend', listener); | ||
### hideEasing | ||
Hide animation easing. Accepts any valid [Velocity.js easing](http://velocityjs.org/#easing) value. | ||
* Default value: `'ease'`. | ||
* Accepted types: array, string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
hideEasing: 'ease-out' | ||
}); | ||
``` | ||
### `muuri.refresh( [targets] )` | ||
### visibleStyles | ||
Recalculate the width and height of the provided targets. If no targets are provided all *active* items will be refreshed. | ||
The styles that will be applied to all visible items. These styles are also used for the show/hide animations which means that you have to have the same style properties in visibleStyles and hiddenStyles options. | ||
**Parameters** | ||
* Default value: `{opacity: 1, scale: 1}`. | ||
* Accepted types: object. | ||
* **targets** — *array / element / Muuri.Item / number* | ||
* Optional. | ||
* An array of DOM elements and/or `Muuri.Item` instances and/or integers (which describe the index of the item). | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
visibleStyles: { | ||
opacity: 1, | ||
rotateZ: '45deg' | ||
}, | ||
hiddenStyles: { | ||
opacity: 0, | ||
rotateZ: '-45deg' | ||
} | ||
}); | ||
``` | ||
**Examples** | ||
### hiddenStyles | ||
The styles that will be applied to all hidden items. These styles are also used for the show/hide animations which means that you have to have the same style properties in visibleStyles and hiddenStyles options. | ||
* Default value: `{opacity: 0, scale: 0.5}`. | ||
* Accepted types: object. | ||
```javascript | ||
// Refresh all active items | ||
muuri.refresh(); | ||
var grid = new Muuri(elem, { | ||
visibleStyles: { | ||
opacity: 1, | ||
rotateZ: '45deg' | ||
}, | ||
hiddenStyles: { | ||
opacity: 0, | ||
rotateZ: '-45deg' | ||
} | ||
}); | ||
``` | ||
// Refresh the first item. | ||
muuri.refresh(0); | ||
### layout | ||
// Refresh all items which match the provided DOM elements. | ||
muuri.refresh([elemA, elemB]); | ||
Define how the items will be laid out. Although it's not documented well (at all) in this section, you *can* provide a function here also if you want to provide your own layout algorithm (may the source be with you). | ||
// Refresh specific items (instances of Muuri.Item). | ||
muuri.refresh([itemA, itemB]); | ||
* Default value: `{fillGaps: false, horizontal: false, alignRight: false, alignBottom: false}`. | ||
* Accepted types: function, object. | ||
Provide an object to configure the default layout algorithm with the following properties: | ||
* **fillGaps** — *boolean* | ||
* Default value: `false`. | ||
* When `true` the algorithm goes through every item in order and places each item to the first available free slot, even if the slot happens to be visually *before* the previous element's slot. Practically this means that the items might not end up visually in order, but there will be less gaps in the grid. By default this option is `false` which basically means that the following condition will be always true when calculating the layout (assuming `alignRight` and `alignBottom` are `false`): `nextItem.top > prevItem.top || (nextItem.top === prevItem.top && nextItem.left > prevItem.left)`. This also means that the items will be visually in order. | ||
* **horizontal** — *boolean* | ||
* Default value: `false`. | ||
* When `true` the grid works in landscape mode (grid expands to the right). Use for horizontally scrolling sites. When `false` the grid works in "portrait" mode and expands downwards. | ||
* **alignRight** — *boolean* | ||
* Default value: `false`. | ||
* When `true` the items are aligned from right to left. | ||
* **alignBottom** — *boolean* | ||
* Default value: `false`. | ||
* When `true` the items are aligned from the bottom up. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
layout: { | ||
fillGaps: true, | ||
horizontal: true, | ||
alignRight: true, | ||
alignBottom: true | ||
} | ||
}); | ||
``` | ||
### `muuri.get( [targets], [state] )` | ||
### layoutOnResize | ||
Get all items. Optionally you can provide specific targets (indices or elements) and filter the results by the items' state (active/inactive). Note that the returned array is not the same object used by the instance so modifying it will not affect instance's items. All items that are not found are omitted from the returned array. | ||
Should Muuri automatically trigger `layout` method on window resize? Set to `false` to disable. When a number or `true` is provided Muuri will automatically lay out the items every time window is resized. The provided number (`true` is transformed to `0`) equals to the amount of time (in milliseconds) that is waited before items are laid out after each window resize event. | ||
**Parameters** | ||
* Default value: `100`. | ||
* Accepted types: boolean, number. | ||
* **targets** — *array / element / Muuri.Item / number* | ||
* Optional. | ||
* An array of DOM elements and/or `Muuri.Item` instances and/or integers (which describe the index of the item). | ||
* **state** — *string* | ||
* Optional. | ||
* Default value: `undefined`. | ||
* Allowed values: `"active"`, `"inactive"`. | ||
* Filter the returned array by the items' state. For example, if set to `"active"` all *inactive* items will be removed from the returned array. | ||
```javascript | ||
// No layout on resize. | ||
var grid = new Muuri(elem, { | ||
layoutOnResize: false | ||
}); | ||
**Returns** — *array* | ||
// Layout on resize (instantly). | ||
var grid = new Muuri(elem, { | ||
layoutOnResize: true | ||
}); | ||
Returns an array of `Muuri.Item` instances. | ||
// Layout on resize (with 200ms debounce). | ||
var grid = new Muuri(elem, { | ||
layoutOnResize: 200 | ||
}); | ||
``` | ||
**Examples** | ||
### layoutOnInit | ||
Should Muuri trigger `layout` method automatically on init? | ||
* Default value: `true`. | ||
* Accepted types: boolean. | ||
```javascript | ||
// Get all items, active and inactive. | ||
var allItems = muuri.get(); | ||
var grid = new Muuri(elem, { | ||
layoutOnInit: false | ||
}); | ||
``` | ||
// Get all active items. | ||
var activeItems = muuri.get('active'); | ||
### layoutDuration | ||
// Get all inactive items. | ||
var inactiveItems = muuri.get('inactive'); | ||
The duration for item's layout animation in milliseconds. Set to `0` to disable. | ||
// Get the first item. | ||
var firstItem = muuri.get(0)[0]; | ||
* Default value: `300`. | ||
* Accepted types: number. | ||
// Get specific items by their elements. | ||
var items = muuri.get([elemA, elemB]); | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
layoutDuration: 600 | ||
}); | ||
``` | ||
// Get specific inactive items. | ||
var items = muuri.get([elemA, elemB], 'inactive'); | ||
### layoutEasing | ||
The easing for item's layout animation. Accepts any valid [Velocity.js easing](http://velocityjs.org/#easing) value. | ||
* Default value: `'ease'`. | ||
* Accepted types: string. | ||
```javascript | ||
// jQuery UI easings. | ||
var grid = new Muuri(elem, { | ||
layoutEasing: 'easeInSine' | ||
}); | ||
// Custom bezier curve. | ||
var grid = new Muuri(elem, { | ||
layoutEasing: [0.17, 0.67, 0.83, 0.67] | ||
}); | ||
// Spring physics. | ||
var grid = new Muuri(elem, { | ||
layoutEasing: [250, 15] | ||
}); | ||
// Step easing. | ||
var grid = new Muuri(elem, { | ||
layoutEasing: [8] | ||
}); | ||
``` | ||
### `muuri.add( elements, [index] )` | ||
### sortData | ||
Add new items by providing the elements you wish to add to the instance and optionally provide the index where you want the items to be inserted into. All elements that are not already children of the container element will be automatically appended to the container. | ||
The sort data getter functions. Provide an object where the key is the name of the sortable attribute and the function returns a value (from the item) by which the items can be sorted. | ||
If an element has it's CSS display property set to none it will be marked as *inactive* during the initiation process. As long as the item is *inactive* it will not be part of the layout, but it will retain it's index. You can activate items at any point with `muuri.show()` method. | ||
* Default value: `null`. | ||
* Accepted types: object, null. | ||
This method will automatically call `muuri.layout()` if one or more of the added elements are visible. If only hidden items are added no layout will be called. All the new visible items are positioned without animation during their first layout. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
sortData: { | ||
foo: function (item, element) { | ||
return parseFloat(element.getAttribute('data-foo')); | ||
}, | ||
bar: function (item, element) { | ||
return element.getAttribute('data-bar').toUpperCase(); | ||
} | ||
} | ||
}); | ||
// Refresh sort data whenever an item's data-foo or data-bar changes | ||
grid.refreshSortData(); | ||
// Sort the grid by foo and bar. | ||
grid.sort('foo bar'); | ||
``` | ||
**Parameters** | ||
### dragEnabled | ||
* **elements** — *array / element* | ||
* An array of DOM elements. | ||
Should items be draggable? | ||
* Default value: `false`. | ||
* Accepted types: boolean. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
dragEnabled: true | ||
}); | ||
``` | ||
### dragContainer | ||
The element the dragged item should be appended to for the duration of the drag. If set to `null` (which is also the default value) the grid's container element will be used. Note that the provided element should be "positioned" meaning that it's CSS position property should be *relative*, *absolute* or *fixed*. | ||
* Default value: `null`. | ||
* Accepted types: element, null. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
dragContainer: document.body | ||
}); | ||
``` | ||
### dragStartPredicate | ||
A function that determines when the item should start to move when the item is being dragged. By default uses the built-in predicate which has some configurable options. | ||
* Default value: `{distance: 0, delay: 0, handle: false}`. | ||
* Accepted types: function, object. | ||
If an object is provided the default sort predicate handler will be used. You can define the following properties: | ||
* **distance** — *number* | ||
* Default value: `0`. | ||
* How many pixels must be dragged before the dragging starts. | ||
* **delay** — *number* | ||
* Default value: `0`. | ||
* How long (in milliseconds) the user must drag before the dragging starts. | ||
* **handle** — *string / boolean* | ||
* Default value: `false`. | ||
* The selector(s) which much match the event target element for the dragging to start. | ||
If you provide a function you can totally customize the drag start logic. When the user starts to drag an item this predicate function will be called until you return `true` or `false`. If you return `true` the item will begin to move whenever the item is dragged. If you return `false` the item will not be moved at all. Note that after you have returned `true` or `false` this function will not be called until the item is released and dragged again. | ||
The predicate function receives two arguments: | ||
* **item** — *Muuri.Item* | ||
* The item that's being dragged. | ||
* **event** — *object* | ||
* The drag event (Hammer.js event). | ||
```javascript | ||
// Configure the default preficate | ||
var grid = new Muuri(elem, { | ||
dragStartPredicate: { | ||
distance: 10, | ||
delay: 100, | ||
handle: '.foo, .bar' | ||
} | ||
}); | ||
// Provide your own predicate | ||
var grid = new Muuri(elem, { | ||
dragStartPredicate: function (item, e) { | ||
// Start moving the item after the item has been dragged for one second. | ||
if (e.deltaTime > 1000) { | ||
return true; | ||
} | ||
} | ||
}); | ||
``` | ||
### dragSort | ||
Should the items be sorted during drag? | ||
* Default value: `true`. | ||
* Accepted types: boolean. | ||
```javascript | ||
// Disable drag sorting. | ||
var grid = new Muuri(elem, { | ||
dragSort: false | ||
}); | ||
``` | ||
### dragSortInterval | ||
Defines the amount of time the dragged item must be still before `dragSortPredicate` function is called. The default `dragSortPredicate` is pretty heavy function which means that you might see some janky animations and/or an unresponsive UI if you set this value too low (`0` is not recommended). | ||
* Default value: `100`. | ||
* Accepted types: number. | ||
```javascript | ||
// Sort on every drag move. | ||
var grid = new Muuri(elem, { | ||
dragSortInterval: 0 | ||
}); | ||
// Sort with a decent buffer. | ||
var grid = new Muuri(elem, { | ||
dragSortInterval: 150 | ||
}); | ||
``` | ||
### dragSortPredicate | ||
Defines the logic for the sort procedure during dragging an item. | ||
* Default value: `{action: 'move', tolerance: 50}`. | ||
* Accepted types: function, object. | ||
If an object is provided the default sort predicate handler will be used. You can define the following properties: | ||
* **action** — *string* | ||
* Default value: `'move'`. | ||
* Allowed values: `'move'`, `'swap'`. | ||
* Should the dragged item be *moved* to the new position or should it *swap* places with the item it overlaps? | ||
* **threshold** — *number* | ||
* Default value: `50`. | ||
* Allowed values: `1` - `100`. | ||
* How many percent the intersection area between the dragged item and the compared item should be from the maximum potential intersection area between the items before sorting is triggered. | ||
Alternatively you can provide your own callback function where you can define your own custom sort logic. The callback function receives two arguments: | ||
* **item** — *Muuri.Item* | ||
* The item that's being dragged. | ||
* **event** — *object* | ||
* The drag event (Hammer.js event). | ||
The callback should return a *falsy* value if sorting should not occur. If, however, sorting should occur the callback should return an object containing the following properties: | ||
* **index** — *number* | ||
* The index where the item should be moved to. | ||
* **grid** — *Muuri* | ||
* The grid where the item should be moved to. | ||
* Defaults to the item's current grid. | ||
* Optional. | ||
* Default value: `0`. | ||
* The index where you want the items to be inserted in. A value of `-1` will insert the items to the end of the list while `0` will insert the items to the beginning. Note that the DOM elements are always just appended to the instance container regardless of the index value. You can use the `muuri.synchronize()` method to arrange the DOM elments to the same order as the items. | ||
* **action** — *string* | ||
* The movement method. | ||
* Default value: `'move'`. | ||
* Allowed values: `'move'` or `'swap'`. | ||
* Optional. | ||
**Returns** — *array* | ||
```javascript | ||
// Customize the default predicate. | ||
var grid = new Muuri(elem, { | ||
dragSortPredicate: { | ||
threshold: 90, | ||
action: 'swap' | ||
} | ||
}); | ||
Returns an array of `Muuri.Item` instances. | ||
// Provide your own predicate. | ||
var grid = new Muuri(elem, { | ||
dragSortPredicate: function (item, e) { | ||
if (e.deltaTime > 1000) { | ||
return { | ||
index: Math.round(e.deltaTime / 1000) % 2 === 0 ? -1 : 0, | ||
action: 'swap' | ||
}; | ||
} | ||
} | ||
}); | ||
``` | ||
**Examples** | ||
### dragSortGroup | ||
The grid's sort group(s), e.g. `'groupA'` or `['groupA', 'groupB']`. If you provide no sort group the grid cannot be targeted with `dragSortWith` option, which means that items can not be dragged into the grid from other grids. | ||
* Default value: `null`. | ||
* Accepted types: array, string, null. | ||
```javascript | ||
// Add two new items to the beginning. | ||
muuri.add([elemA, elemB]); | ||
var gridA = new Muuri(elemA, { | ||
dragSortGroup: 'groupA' | ||
}); | ||
var gridB = new Muuri(elemB, { | ||
dragSortGroup: ['groupA', 'groupB'] | ||
}); | ||
``` | ||
// Add two new items to the end. | ||
muuri.add([elemA, elemB], -1); | ||
### dragSortWith | ||
Defines the sort group(s) that this instance's item's can be dragged to. Provide a string to target a single sort group, e.g. `'groupA'`, or an array of targeted sort groups using an array, e.g. `['groupA', 'groupC']`. | ||
* Default value: `null`. | ||
* Accepted types: array, null. | ||
```javascript | ||
// This grid's items can not be dragged into any other grids. | ||
var gridA = new Muuri(elemA, { | ||
dragSortGroup: 'a' | ||
}); | ||
// This grid's items can be dragged into gridC. | ||
var gridB = new Muuri(elemB, { | ||
dragSortGroup: 'b', | ||
dragSortWith: 'c' | ||
}); | ||
// This grid's items can be dragged into gridA and gridB. | ||
var gridC = new Muuri(elemC, { | ||
dragSortGroup: 'c', | ||
dragSortWith: ['a', 'b'] | ||
}); | ||
``` | ||
### `muuri.remove( targets, [removeElement] )` | ||
### dragReleaseDuration | ||
Remove items from the instance. | ||
The duration for item's drag release animation. Set to `0` to disable. | ||
* Default value: `300`. | ||
* Accepted types: number. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
dragReleaseDuration: 600 | ||
}); | ||
``` | ||
### dragReleaseEasing | ||
The easing for item's drag release animation. Accepts any valid [Velocity.js easing](http://velocityjs.org/#easing) value. | ||
* Default value: `'ease'`. | ||
* Accepted types: array, string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
dragReleaseEasing: 'ease-out' | ||
}); | ||
``` | ||
### containerClass | ||
Container element's classname. | ||
* Default value: `'muuri'`. | ||
* Accepted types: string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
containerClass: 'foo' | ||
}); | ||
``` | ||
### itemClass | ||
Item element's classname. | ||
* Default value: `'muuri-item'`. | ||
* Accepted types: string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
itemClass: 'foo-item' | ||
}); | ||
``` | ||
### itemVisibleClass | ||
Visible item's classname. | ||
* Default value: `'muuri-item-shown'`. | ||
* Accepted types: string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
itemVisibleClass: 'foo-item-shown' | ||
}); | ||
``` | ||
### itemHiddenClass | ||
Hidden item's classname. | ||
* Default value: `'muuri-item-hidden'`. | ||
* Accepted types: string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
itemHiddenClass: 'foo-item-hidden' | ||
}); | ||
``` | ||
### itemPositioningClass | ||
This classname will be added to the item element for the duration of positioning. | ||
* Default value: `'muuri-item-positioning'`. | ||
* Accepted types: string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
itemPositioningClass: 'foo-item-positioning' | ||
}); | ||
``` | ||
### itemDraggingClass | ||
This classname will be added to the item element for the duration of drag. | ||
* Default value: `'muuri-item-dragging'`. | ||
* Accepted types: string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
itemDraggingClass: 'foo-item-dragging' | ||
}); | ||
``` | ||
### itemReleasingClass | ||
This classname will be added to the item element for the duration of release. | ||
* Default value: `'muuri-item-releasing'`. | ||
* Accepted types: string. | ||
```javascript | ||
var grid = new Muuri(elem, { | ||
itemReleasingClass: 'foo-item-releasing' | ||
}); | ||
``` | ||
### Grid methods | ||
* [grid.getElement()](#gridgetelement) | ||
* [grid.getItems( [targets], [state] )](#gridgetitems-targets-state-) | ||
* [grid.refreshItems( [items] )](#gridrefreshitems-items-) | ||
* [grid.refreshSortData( [items] )](#gridrefreshsortdata-items-) | ||
* [grid.synchronize()](#gridsynchronize) | ||
* [grid.layout( [instant], [callback] )](#gridlayout-instant-callback-) | ||
* [grid.add( elements, [options] )](#gridadd-elements-options-) | ||
* [grid.remove( items, [options] )](#gridremove-items-options-) | ||
* [grid.show( items, [options] )](#gridshow-items-options-) | ||
* [grid.hide( items, [options] )](#gridhide-items-options-) | ||
* [grid.filter( predicate, [options] )](#gridfilter-predicate-options-) | ||
* [grid.sort( comparer, [options] )](#gridsort-comparer-options-) | ||
* [grid.move( item, position, [options] )](#gridmove-item-position-options-) | ||
* [grid.send( item, grid, position, [options] )](#gridsend-item-grid-position-options-) | ||
* [grid.on( event, listener )](#gridon-event-listener-) | ||
* [grid.once( event, listener )](#gridonce-event-listener-) | ||
* [grid.off( event, listener )](#gridoff-event-listener-) | ||
* [grid.destroy( [removeElements] )](#griddestroy-removeelements-) | ||
### grid.getElement() | ||
Get the instance element. | ||
**Returns** — *element* | ||
```javascript | ||
var elem = grid.getElement(); | ||
``` | ||
### grid.getItems( [targets], [state] ) | ||
Get all items in the grid. Optionally you can provide specific targets (indices or elements) and filter the results by the items' state. | ||
**Parameters** | ||
* **targets** — *array / element / Muuri.Item / number* | ||
* An array of DOM elements and/or `Muuri.Item` instances and/or integers (which describe the index of the item). | ||
* **removeElement** — *boolean* | ||
* An array of item instances/elements/indices. | ||
* Optional. | ||
* Default value: `false`. | ||
* Should the associated DOM element be removed or not? | ||
* **state** — *string* | ||
* Accepted values: `'active'`, `'inactive'`, `'visible'`, `'hidden'`, `'showing'`, `'hiding'`, `'positioning'`, `'dragging'`, `'releasing'`, `'migrating'`. | ||
* Default value: `undefined`. | ||
* Optional. | ||
**Returns** — *array* | ||
Returns the indices of the removed items. | ||
Returns the queried items. | ||
**Examples** | ||
```javascript | ||
// Get all items, both active and inactive. | ||
var allItems = grid.getItems(); | ||
// Get all active (visible) items. | ||
var activeItems = grid.getItems('active'); | ||
// Get all inactive (hidden) items. | ||
var inactiveItems = grid.getItems('inactive'); | ||
// Get the first item (active or inactive). | ||
var firstItem = grid.getItems(0)[0]; | ||
// Get specific items by their elements (inactive or active). | ||
var items = grid.getItems([elemA, elemB]); | ||
// Get specific inactive items. | ||
var items = grid.getItems([elemA, elemB], 'inactive'); | ||
``` | ||
### grid.refreshItems( [items] ) | ||
Refresh the cached dimensions of the grid's items. When called without any arguments all active items are refreshed. Optionally you can provide specific the items which you want to refresh as the first argument. | ||
**Parameters** | ||
* **items** — *array / element / Muuri.Item / number / string* | ||
* To target specific items provide an array of item instances/elements/indices. By default all active items are targeted. | ||
* Optional. | ||
```javascript | ||
// Remove the first item, but keep the element in the DOM. | ||
muuri.remove(0); | ||
// Refresh dimensions of all active item elements. | ||
grid.refreshItems(); | ||
// Remove items and the associated elements. | ||
muuri.remove([elemA, elemB], true); | ||
// Refresh dimensions of specific item elements. | ||
grid.refreshItems([0, someElem, someItem]); | ||
``` | ||
### `muuri.synchronize()` | ||
### grid.refreshSortData( [items] ) | ||
Order the item elements to match the order of the items. If the item's element is not a child of the container it is ignored and left untouched. This comes handy if you need to keep the DOM structure matched with the order of the items. | ||
Refresh the sort data of the instance's items. | ||
**Examples** | ||
**Parameters** | ||
* **items** — *array / element / Muuri.Item / number* | ||
* To target specific items provide an array of item instances/elements/indices. By default all items are targeted. | ||
* Optional. | ||
```javascript | ||
muuri.synchronize(); | ||
// Refresh the sort data for every item. | ||
grid.refreshSortData(); | ||
// Refresh the sort data for specific items. | ||
grid.refreshSortData([0, someElem, someItem]); | ||
``` | ||
### `muuri.layout( [instant], [callback] )` | ||
### grid.synchronize() | ||
Calculate item positions and move items to their calculated positions unless they are already positioned correctly. The container's height is also adjusted according to the position of the items. | ||
Synchronize the item elements to match the order of the items in the DOM. This comes handy if you need to keep the DOM structure matched with the order of the items. Note that if an item's element is not currently a child of the container element (if it is dragged for example) it is ignored and left untouched. | ||
```javascript | ||
// Let's say we have to move the first item in the grid as the last. | ||
grid.move(0, -1); | ||
// Now the DOM order of the items is not in sync anymore with the | ||
// order of the items. We can sync the DOM with synchronize method. | ||
grid.synchronize(); | ||
``` | ||
### grid.layout( [instant], [callback] ) | ||
Calculate item positions and move items to their calculated positions, unless they are already positioned correctly. The grid's height/width (depends on the layout algorithm) is also adjusted according to the position of the items. | ||
**Parameters** | ||
* **instant** — *boolean* | ||
* Should the items be positioned instantly without any possible animation? | ||
* Default value: `false`. | ||
* Optional. | ||
* Default value: `false`. | ||
* Should the items be positioned instantly without any possible animation? | ||
* **callback** — *function* | ||
* A callback function that is called after the items have positioned. Receives one argument: an array of all the items that were successfully positioned without interruptions. | ||
* Optional. | ||
* A callback function that is called after the items have positioned. Receives two arguments. The first one is an array of all the items that were successfully positioned without interruptions and the second is a layout data object. | ||
**Examples** | ||
```javascript | ||
// Layout with animations (if any). | ||
muuri.layout(); | ||
// Layout items. | ||
grid.layout(); | ||
// Layout instantly without animations. | ||
muuri.layout(true); | ||
// Layout items instantly (without animations). | ||
grid.layout(true); | ||
// Layout with callback (and with animations if any). | ||
muuri.layout(function (items, layoutData) { | ||
// Layout all items and define a callback that will be called | ||
// after all items have been animated to their positions. | ||
grid.layout(function (items) { | ||
console.log('layout done!'); | ||
@@ -512,34 +1017,101 @@ }); | ||
### `muuri.show( targets, [instant], [callback] )` | ||
### grid.add( elements, [options] ) | ||
Show the targeted items. | ||
Add new items by providing the elements you wish to add to the instance and optionally provide the index where you want the items to be inserted into. All elements that are not already children of the container element will be automatically appended to the container element. If an element has it's CSS display property set to none it will be marked as *inactive* during the initiation process. As long as the item is *inactive* it will not be part of the layout, but it will retain it's index. You can activate items at any point with `grid.show()` method. This method will automatically call `grid.layout()` if one or more of the added elements are visible. If only hidden items are added no layout will be called. All the new visible items are positioned without animation during their first layout. | ||
**Parameters** | ||
* **targets** — *array / element / Muuri.Item / number* | ||
* An array of DOM elements and/or `Muuri.Item` instances and/or integers (which describe the index of the item). | ||
* **instant** — *boolean* | ||
* **elements** — *array / element* | ||
* An array of DOM elements. | ||
* **options.index** — *number* | ||
* The index where you want the items to be inserted in. A value of `-1` will insert the items to the end of the list while `0` will insert the items to the beginning. Note that the DOM elements are always just appended to the instance container regardless of the index value. You can use the `grid.synchronize()` method to arrange the DOM elments to the same order as the items. | ||
* Default value: `-1`. | ||
* Optional. | ||
* **options.layout** — *boolean / function / string* | ||
* By default `grid.layout()` is called at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
**Returns** — *array* | ||
Returns the added items. | ||
```javascript | ||
// Add two new items to the end. | ||
grid.add([elemA, elemB]); | ||
// Add two new items to the beginning. | ||
grid.add([elemA, elemB], {index: 0}); | ||
// Skip the automatic layout. | ||
grid.add([elemA, elemB], {layout: false}); | ||
``` | ||
### grid.remove( items, [options] ) | ||
Remove items from the instance. | ||
**Parameters** | ||
* **items** — *array / element / Muuri.Item / number* | ||
* An array of item instances/elements/indices. | ||
* **options.removeElements** — *boolean* | ||
* Should the associated DOM element be removed from the DOM? | ||
* Default value: `false`. | ||
* Optional. | ||
* **options.layout** — *boolean / function / string* | ||
* By default `grid.layout()` is called at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
**Returns** — *array* | ||
Returns the destroyed items. | ||
```javascript | ||
// Remove the first item, but keep the element in the DOM. | ||
grid.remove(0); | ||
// Remove items and the associated elements. | ||
grid.remove([elemA, elemB], {removeElements: true}); | ||
// Skip the layout. | ||
grid.remove([elemA, elemB], {layout: false}); | ||
``` | ||
### grid.show( items, [options] ) | ||
Show the targeted items. | ||
**Parameters** | ||
* **items** — *array / element / Muuri.Item / number* | ||
* An array of item instances/elements/indices. | ||
* **options.instant** — *boolean* | ||
* Should the items be shown instantly without any possible animation? | ||
* **callback** — *function* | ||
* Default value: `false`. | ||
* Optional. | ||
* **options.onFinish** — *function* | ||
* A callback function that is called after the items are shown. | ||
* Optional. | ||
* **options.layout** — *boolean / function / string* | ||
* By default `grid.layout()` is called at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
**Examples** | ||
```javascript | ||
// Show items with animation (if any). | ||
muuri.show([elemA, elemB]); | ||
grid.show([elemA, elemB]); | ||
// Show items instantly without animations. | ||
muuri.show([elemA, elemB], true); | ||
grid.show([elemA, elemB], {instant: true}); | ||
// Show items with callback (and with animations if any). | ||
muuri.show([elemA, elemB], function (items) { | ||
grid.show([elemA, elemB], {onFinish: function (items) { | ||
console.log('items shown!'); | ||
}); | ||
}}); | ||
``` | ||
### `muuri.hide( targets, [instant], [callback] )` | ||
### grid.hide( items, [options] ) | ||
@@ -550,113 +1122,197 @@ Hide the targeted items. | ||
* **targets** — *array / element / Muuri.Item / number* | ||
* An array of DOM elements and/or `Muuri.Item` instances and/or integers (which describe the index of the item). | ||
* **instant** — *boolean* | ||
* Optional. | ||
* **items** — *array / element / Muuri.Item / number* | ||
* An array of item instances/elements/indices. | ||
* **options.instant** — *boolean* | ||
* Should the items be hidden instantly without any possible animation? | ||
* Default value: `false`. | ||
* Should the items be hidden instantly without any possible animation? | ||
* **callback** — *function* | ||
* Optional. | ||
* **options.onFinish** — *function* | ||
* A callback function that is called after the items are hidden. | ||
* Optional. | ||
* **options.layout** — *boolean / function / string* | ||
* By default `grid.layout()` is called at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
**Examples** | ||
```javascript | ||
// Hide items with animation (if any). | ||
muuri.hide([elemA, elemB]); | ||
// Hide items with animation. | ||
grid.hide([elemA, elemB]); | ||
// Hide items instantly without animations. | ||
muuri.hide([elemA, elemB], true); | ||
grid.hide([elemA, elemB], {instant: true}); | ||
// Hide items with callback (and with animations if any). | ||
muuri.hide([elemA, elemB], function (items) { | ||
// Hide items and call the callback function after | ||
// all items are hidden. | ||
grid.hide([elemA, elemB], {onFinish: function (items) { | ||
console.log('items hidden!'); | ||
}); | ||
}}); | ||
``` | ||
### `muuri.indexOf( target )` | ||
### grid.filter( predicate, [options] ) | ||
Get item's index. | ||
Filter items. Expects at least one argument, a predicate, which should be either a function or a string. The predicate callback is executed for every item in the instance. If the return value of the predicate is truthy the item in question will be shown and otherwise hidden. The predicate callback receives the item instance as it's argument. If the predicate is a string it is considered to be a selector and it is checked against every item element in the instance with the native element.matches() method. All the matching items will be shown and others hidden. | ||
**Parameters** | ||
* **target** — *element / Muuri.Item* | ||
* **predicate** — *function / string* | ||
* A predicate callback or a selector. | ||
* **options.instant** — *boolean* | ||
* Should the items be shown/hidden instantly without any possible animation? | ||
* Default value: `false`. | ||
* Optional. | ||
* **options.onFinish** — *function* | ||
* An optional callback function that is called after all the items are shown/hidden. | ||
* Optional. | ||
* **options.layout** — *boolean / function / string* | ||
* By default `grid.layout()` is called at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
**Returns** — *number / null* | ||
```javascript | ||
// Show all items that have the attribute "data-foo". | ||
grid.filter(function (item) { | ||
return item.getElement().hasAttribute('data-foo'); | ||
}); | ||
Returns the target's index or null if the target is not found. | ||
// Or simply just... | ||
grid.filter('[data-foo]'); | ||
**Examples** | ||
```javascript | ||
var index = muuri.indexOf(elemA); | ||
// Show all items that have a class foo. | ||
grid.filter('.foo'); | ||
``` | ||
### `muuri.move( targetFrom, targetTo )` | ||
### grid.sort( comparer, [options] ) | ||
Move item to another index or in place of another item. | ||
Sort items. There are three ways to sort the items. The first is simply by providing a function as the comparer which works almost identically to [native array sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort). Th only difference is that the sort is always stable. Alternatively you can sort by the sort data you have provided in the instance's options. Just provide the sort data key(s) as a string (separated by space) and the items will be sorted based on the provided sort data keys. Lastly you have the opportunity to provide a presorted array of items which will be used to sync the internal items array in the same order. | ||
**Parameters** | ||
* **targetFrom** — *element / Muuri.Item / number* | ||
* DOM element or `Muuri.Item` instance or index of the item as an integer. | ||
* **targetTo** — *element / Muuri.Item / number* | ||
* DOM element or `Muuri.Item` instance or index of the item as an integer. | ||
* **comparer** — *array / function / string* | ||
* Provide a comparer function, sort data keys as a string (separated with space) or a presorted array of items. It is recommended to use the sort data feature, because it allows you to cache the sort data and make the sorting faster. | ||
* **options.descending** — *boolean* | ||
* By default the items are sorted in ascending order. If you want to sort them in descending order set this to `true`. | ||
* Default value: `false`. | ||
* Optional. | ||
* **options.layout** — *boolean / function / string* | ||
* By default `grid.layout()` is called at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
**Examples** | ||
```javascript | ||
// Sort items by data-id attribute value (ascending). | ||
grid.sort(function (itemA, itemB) { | ||
var aId = parseInt(itemA.getElement().getAttribute('data-id')); | ||
var bId = parseInt(itemB.getElement().getAttribute('data-id')); | ||
return aId - bId; | ||
}); | ||
// Move elemA to the index of elemB. | ||
muuri.move(elemA, elemB); | ||
// Sort items with a presorted array of items. | ||
grid.sort(presortedItems); | ||
// Move first item as last. | ||
muuri.move(0, -1); | ||
// Sort items using the sort data keys (ascending). | ||
grid.sort('foo bar'); | ||
// Sort items using the sort data keys (descending). | ||
grid.sort('foo bar', {descending: true}); | ||
// Sort items using the sort data keys. Sort some keys | ||
// ascending and some keys descending. | ||
grid.sort('foo bar:desc'); | ||
``` | ||
### `muuri.swap( targetA, targetB )` | ||
### grid.move( item, position, [options] ) | ||
Swap positions of two items. | ||
Move an item to another position in the grid. | ||
**Parameters** | ||
* **targetA** — *element / Muuri.Item / number* | ||
* DOM element or `Muuri.Item` instance or index of the item as an integer. | ||
* **targetB** — *element / Muuri.Item / number* | ||
* DOM element or `Muuri.Item` instance or index of the item as an integer. | ||
* **item** — *element / Muuri.Item / number* | ||
* Item instance, element or index. | ||
* **position** — *element / Muuri.Item / number* | ||
* Item instance, element or index. | ||
* **options.action** — *string* | ||
* Accepts the following values: | ||
* `'move'`: moves item in place of another item. | ||
* `'swap'`: swaps position of items. | ||
* Default value: `'move'`. | ||
* Optional. | ||
* **options.layout** — *boolean / function / string* | ||
* By default `grid.layout()` is called at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
**Examples** | ||
```javascript | ||
// Move elemA to the index of elemB. | ||
grid.move(elemA, elemB); | ||
```javascript | ||
// Move the first item in the grid as the last. | ||
grid.move(0, -1); | ||
// Swap positions of elemA and elemB. | ||
muuri.swap(elemA, elemB); | ||
grid.move(elemA, elemB, {action: 'swap'}); | ||
// Swap positions of the first and the last item. | ||
muuri.swap(0, -1); | ||
grid.move(0, -1, {action: 'swap'}); | ||
``` | ||
### `muuri.destroy()` | ||
### grid.send( item, grid, position, [options] ) | ||
Destroy the instance. | ||
Move an item into another grid. | ||
**Examples** | ||
**Parameters** | ||
* **item** — *element / Muuri.Item / number* | ||
* The item that should be moved. You can define the item with an item instance, element or index. | ||
* **grid** — *Muuri* | ||
* The grid where the item should be moved to. | ||
* **position** — *element / Muuri.Item / number* | ||
* To which position should the item be placed to in the new grid? You can define the position with an item instance, element or index. | ||
* **options.appendTo** — *element* | ||
* Which element the item element should be appended to for the duration of the layout animation? Note that the provided element should be "positioned" meaning that it's CSS position property should be *relative*, *absolute* or *fixed*. | ||
* Default value: `document.body`. | ||
* **options.layoutSender** — *boolean / function / string* | ||
* By default `grid.layout()` is called for the sending grid at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
* **options.layoutReceiver** — *boolean / function / string* | ||
* By default `grid.layout()` is called for the receiving grid at the end of this method. With this argument you can control the layout call. You can disable the layout completely with `false`, or provide a callback function for the layout method, or provide the string `'instant'` to make the layout happen instantly without any animations. | ||
* Default value: `true`. | ||
* Optional. | ||
```javascript | ||
muuri.destroy(); | ||
// Move the first item of gridA as the last item of gridB. | ||
gridA.send(0, gridB, -1); | ||
// Move the first item of gridA as the last item of gridB. | ||
gridA.send(0, gridB, -1 { | ||
appendTo: someElem | ||
}); | ||
// Do something after the item has been sent and the layout | ||
// processes have finished. | ||
gridA.send(0, gridB, -1 { | ||
layoutSender: function (isAborted, items) { | ||
// Do your thing here... | ||
}, | ||
layoutReceiver: function (isAborted, items) { | ||
// Do your other thing here... | ||
} | ||
}); | ||
``` | ||
## Events | ||
### grid.on( event, listener ) | ||
### `refresh` | ||
Bind an event listener. | ||
Triggered after the `muuri.refresh()` method is called. | ||
**Parameters** | ||
**Listener parameters** | ||
* **event** — *string* | ||
* **listener** — *function* | ||
* **items** — *array* | ||
* An array of `Muuri.Item` instances which were refreshed. | ||
**Returns** — *object* | ||
**Examples** | ||
Returns the instance. | ||
```javascript | ||
muuri.on('refresh', function (items) { | ||
grid.on('layoutEnd', function (items) { | ||
console.log(items); | ||
@@ -666,10 +1322,96 @@ }); | ||
### `synchronize` | ||
### grid.once( event, listener ) | ||
Triggered after the `muuri.synchronize()` is called. | ||
Bind an event listener that is triggered only once. | ||
**Examples** | ||
**Parameters** | ||
* **event** — *string* | ||
* **listener** — *function* | ||
**Returns** — *object* | ||
Returns the instance. | ||
```javascript | ||
muuri.on('synchronize', function () { | ||
grid.once('layoutEnd', function (items) { | ||
console.log(items); | ||
}); | ||
``` | ||
### grid.off( event, listener ) | ||
Unbind an event listener. | ||
**Parameters** | ||
* **event** — *string* | ||
* **listener** — *function* | ||
**Returns** — *object* | ||
Returns the instance. | ||
```javascript | ||
var listener = function (items) { | ||
console.log(items); | ||
}; | ||
muuri | ||
.on('layoutEnd', listener) | ||
.off('layoutEnd', listener); | ||
``` | ||
### grid.destroy( [removeElements] ) | ||
Destroy the grid instance. | ||
**Parameters** | ||
* **removeElements** — *boolean* | ||
* Should the item elements be removed or not? | ||
* Default value: `false`. | ||
* Optional. | ||
**Returns** — *object* | ||
Returns the instance. | ||
```javascript | ||
// Destroy the instance. | ||
grid.destroy(); | ||
// Destroy the instance and remove item elements. | ||
grid.destroy(true); | ||
``` | ||
### Grid events | ||
* [synchronize](#synchronize) | ||
* [layoutStart](#layoutstart) | ||
* [layoutEnd](#layoutend) | ||
* [add](#add) | ||
* [remove](#remove) | ||
* [showStart](#showstart) | ||
* [showEnd](#showend) | ||
* [hideStart](#hidestart) | ||
* [hideEnd](#hideend) | ||
* [filter](#filter) | ||
* [sort](#sort) | ||
* [move](#move) | ||
* [send](#send) | ||
* [receive](#receive) | ||
* [dragStart](#dragstart) | ||
* [dragMove](#dragmove) | ||
* [dragScroll](#dragscroll) | ||
* [dragEnd](#dragend) | ||
* [dragReleaseStart](#dragreleasestart) | ||
* [dragReleaseEnd](#dragreleaseend) | ||
* [destroy](#destroy) | ||
### synchronize | ||
Triggered after `grid.synchronize()` is called. | ||
```javascript | ||
grid.on('synchronize', function () { | ||
console.log('Synced!'); | ||
@@ -679,75 +1421,73 @@ }); | ||
### `layoutstart` | ||
### layoutStart | ||
Triggered when `muuri.layout()` method is called, just before the items are positioned. | ||
Triggered after `grid.layout()` is called, just before the items are positioned. | ||
**Listener parameters** | ||
**Arguments** | ||
* **items** — *array* | ||
* An array of `Muuri.Item` instances that were succesfully positioned. If, for example, an item is being dragged it is ignored by the layout method. | ||
* **layout** — *object* | ||
* A `Muuri.Layout` instance. | ||
* **layout.muuri** — *Muuri* | ||
* A `Muuri` instance for which the layout was generated. | ||
* **layout.items** — *array* | ||
* An array of `Muuri.Item` instances that were positioned. | ||
* **layout.slots** — *object* | ||
* An object containing the positions of the `layout.items`. Indexed with the ids of the items. For example, to get the first item's position you would do `layout.slots[layout.items[0]._id]`. Each slot contains the the item's *width*, *height*, *left* and *top*. | ||
* **layout.width** — *number* | ||
* The width of the grid. | ||
* **layout.height** — *number* | ||
* The height of the grid. | ||
* The items that are about to be positioned. | ||
**Examples** | ||
```javascript | ||
muuri.on('layoutstart', function (items, layout) { | ||
grid.on('layoutStart', function (items) { | ||
console.log(items); | ||
console.log(layout); | ||
}); | ||
``` | ||
### `layoutend` | ||
### layoutEnd | ||
Triggered when `muuri.layout()` method is called, after the items have positioned. | ||
Triggered after `grid.layout()` is called, after the items have positioned. Note that if `grid.layout()` is called during an ongoing layout animation the ongoing layout process will be aborted and it's layoutEnd event will never be triggered. | ||
**Listener parameters** | ||
**Arguments** | ||
* **items** — *array* | ||
* An array of `Muuri.Item` instances that were succesfully positioned. If, for example, an item is being dragged it is ignored by the layout method. | ||
* **layout** — *object* | ||
* A `Muuri.Layout` instance. | ||
* **layout.muuri** — *Muuri* | ||
* A `Muuri` instance for which the layout was generated. | ||
* **layout.items** — *array* | ||
* An array of `Muuri.Item` instances that were positioned. | ||
* **layout.slots** — *object* | ||
* An object containing the positions of the `layout.items`. Indexed with the ids of the items. For example, to get the first item's position you would do `layout.slots[layout.items[0]._id]`. Each slot contains the the item's *width*, *height*, *left* and *top*. | ||
* **layout.width** — *number* | ||
* The width of the grid. | ||
* **layout.height** — *number* | ||
* The height of the grid. | ||
* The items that were intended to be positioned. Note that these items are always identical to what the layoutStart event's callback receives as it's argument. So if, for example, you destroy an item during the layout animation and don't do call another layout the destroyed item will still be included in this array of items. The original intention was to filter these items so that all items that were "interrupted" somehow during the layout process would be omitted from the results, but that solution was much more prone to errors and much more harder to explain/understand. | ||
**Examples** | ||
```javascript | ||
muuri.on('layoutend', function (items, layout) { | ||
grid.on('layoutEnd', function (items) { | ||
console.log(items); | ||
console.log(layout); | ||
}); | ||
``` | ||
### `showstart` | ||
### add | ||
Triggered when `muuri.show()` method is called, just before the items are shown (with or without animation). | ||
Triggered after `grid.add()` is called. | ||
**Listener parameters** | ||
**Arguments** | ||
* **items** — *array* | ||
* An array of `Muuri.Item` instances that are about to be shown. | ||
* The items that were succesfully added. | ||
**Examples** | ||
```javascript | ||
grid.on('add', function (items) { | ||
console.log(items); | ||
}); | ||
``` | ||
### remove | ||
Triggered after `grid.remove()` is called. | ||
**Arguments** | ||
* **indices** — *array* | ||
* Indices of the items that were succesfully removed. | ||
```javascript | ||
muuri.on('showstart', function (items) { | ||
grid.on('remove', function (indices) { | ||
console.log(indices); | ||
}); | ||
``` | ||
### showStart | ||
Triggered after `grid.show()` is called, just before the items are shown. | ||
**Arguments** | ||
* **items** — *array* | ||
* The items that are about to be shown. | ||
```javascript | ||
grid.on('showStart', function (items) { | ||
console.log(items); | ||
@@ -757,15 +1497,13 @@ }); | ||
### `showend` | ||
### showEnd | ||
Triggered when `muuri.show()` method is called, after the items are shown (with or without animation). | ||
Triggered after `grid.show()` is called, after the items are shown. | ||
**Listener parameters** | ||
**Arguments** | ||
* **items** — *array* | ||
* An array of `Muuri.Item` instances that were succesfully shown without interruptions. If an item is already visible when the `muuri.show()` method is called it is cosidered as successfully shown. | ||
* The items that were succesfully shown without interruptions. | ||
**Examples** | ||
```javascript | ||
muuri.on('showend', function (items) { | ||
grid.on('showEnd', function (items) { | ||
console.log(items); | ||
@@ -775,15 +1513,13 @@ }); | ||
### `hidestart` | ||
### hideStart | ||
Triggered when `muuri.hide()` method is called, just before the items are hidden (with or without animation). | ||
Triggered after `grid.hide()` is called, just before the items are hidden. | ||
**Listener parameters** | ||
**Arguments** | ||
* **items** — *array* | ||
* An array of `Muuri.Item` instances that are about to be hidden. | ||
* The items that are about to be hidden. | ||
**Examples** | ||
```javascript | ||
muuri.on('hidestart', function (items) { | ||
grid.on('hideStart', function (items) { | ||
console.log(items); | ||
@@ -793,15 +1529,13 @@ }); | ||
### `hideend` | ||
### hideEnd | ||
Triggered when `muuri.hide()` method is called, after the items are hidden (with or without animation). | ||
Triggered after `grid.hide()` is called, after the items are hidden (with or without animation). | ||
**Listener parameters** | ||
**Arguments** | ||
* **items** — *array* | ||
* An array of `Muuri.Item` instances that were succesfully hidden without interruptions. If an item is already hidden when the `muuri.show()` method is called it is cosidered as successfully hidden. | ||
* The items that were succesfully hidden without interruptions. | ||
**Examples** | ||
```javascript | ||
muuri.on('hideend', function (items) { | ||
grid.on('hideEnd', function (items) { | ||
console.log(items); | ||
@@ -811,213 +1545,191 @@ }); | ||
### `move` | ||
### filter | ||
Triggered after `muuri.move()` method is called. | ||
Triggered after `grid.filter()` is called. | ||
**Listener parameters** | ||
**Arguments** | ||
* **targetFrom** — *array* | ||
* `Muuri.Item` instance that was moved. | ||
* **targetTo** — *array* | ||
* `Muuri.Item` instance to which's index the *targetFrom* item was moved to. | ||
* **shownItems** — *array* | ||
* The items that were shown. | ||
* **hiddenItems** — *array* | ||
* The items that were hidden. | ||
**Examples** | ||
```javascript | ||
grid.on('filter', function (shownItems, hiddenItems) { | ||
console.log(shownItems); | ||
console.log(hiddenItems); | ||
}); | ||
``` | ||
### sort | ||
Triggered after `grid.sort()` is called. | ||
**Arguments** | ||
* **currentOrder** — *array* | ||
* All items in their current order. | ||
* **previousOrder** — *array* | ||
* All items in their previous order. | ||
```javascript | ||
muuri.on('move', function (targetFrom, targetTo) { | ||
console.log(targetFrom); | ||
console.log(targetTo); | ||
grid.on('sort', function (currentOrder, previousOrder) { | ||
console.log(currentOrder); | ||
console.log(previousOrder); | ||
}); | ||
``` | ||
### `swap` | ||
### move | ||
Triggered after `muuri.swap()` method is called. | ||
Triggered after `grid.move()` is called or when the grid is sorted during drag. Note that this is event not triggered when an item is dragged into another grid. | ||
**Listener parameters** | ||
**Arguments** | ||
* **targetA** — *array* | ||
* `Muuri.Item` instance that was swapped with *targetB*. | ||
* **targetB** — *array* | ||
* `Muuri.Item` instance that was swapped with *targetA*. | ||
* **data** — *object* | ||
* **data.item** — *Muuri.Item* | ||
* The item that was moved. | ||
* **data.fromIndex** — *number* | ||
* The index the item was moved from. | ||
* **data.toIndex** — *number* | ||
* The index the item was moved to. | ||
* **data.action** — *string* | ||
* "move" or "swap". | ||
**Examples** | ||
```javascript | ||
muuri.on('move', function (targetA, targetB) { | ||
console.log(targetA); | ||
console.log(targetB); | ||
grid.on('move', function (data) { | ||
console.log(data); | ||
}); | ||
``` | ||
### `add` | ||
### send | ||
Triggered after `muuri.add()` method is called. | ||
Triggered, for the originating grid, after `grid.send()` is called or when an item is dragged into another grid. | ||
**Listener parameters** | ||
**Arguments** | ||
* **items** — *array* | ||
* An array of `Muuri.Item` instances that were succesfully added to the muuri instance. | ||
* **data** — *object* | ||
* **data.item** — *Muuri.Item* | ||
* The item that was sent. | ||
* **data.fromGrid** — *Muuri* | ||
* The grid the item was sent from. | ||
* **data.fromIndex** — *number* | ||
* The index the item was moved from. | ||
* **data.toGrid** — *Muuri* | ||
* The grid the item was sent to. | ||
* **data.toIndex** — *number* | ||
* The index the item was moved to. | ||
**Examples** | ||
```javascript | ||
muuri.on('add', function (items) { | ||
console.log(items); | ||
grid.on('send', function (data) { | ||
console.log(data); | ||
}); | ||
``` | ||
### `remove` | ||
### receive | ||
Triggered after `muuri.remove()` method is called. | ||
Triggered, for the receiving grid, after `grid.send()` is called or when an item is dragged into another grid. | ||
**Listener parameters** | ||
**Arguments** | ||
* **itemIndices** — *array* | ||
* Indices of the `Muuri.Item` instances that were succesfully removed from the muuri instance. | ||
* **data** — *object* | ||
* **data.item** — *Muuri.Item* | ||
* The item that was sent. | ||
* **data.fromGrid** — *Muuri* | ||
* The grid the item was sent from. | ||
* **data.fromIndex** — *number* | ||
* The index the item was moved from. | ||
* **data.toGrid** — *Muuri* | ||
* The grid the item was sent to. | ||
* **data.toIndex** — *number* | ||
* The index the item was moved to. | ||
**Examples** | ||
```javascript | ||
muuri.on('remove', function (itemIndices) { | ||
console.log(itemIndices); | ||
grid.on('receive', function (data) { | ||
console.log(data); | ||
}); | ||
``` | ||
### `dragstart` | ||
### dragStart | ||
Triggered when dragging of an item begins. | ||
**Listener parameters** | ||
**Arguments** | ||
* **item** — *Muuri.Item* | ||
* `Muuri.Item` instance that is being dragged. | ||
* **data** — *object* | ||
* **data.type** — *String* | ||
* `"dragstart"` | ||
* **data.event** — *object* | ||
* The hammer event for the drag start event. | ||
* **data.currentLeft** — *number* | ||
* The dragged element's current translateX value. | ||
* **data.currentTop** — *object* | ||
* The dragged element's current translateY value. | ||
* **data.gridLeft** — *number* | ||
* The dragged element's current x-coordinate within the muuri container element. | ||
* **data.gridTop** — *object* | ||
* The dragged element's current y-coordinate within the muuri container element. | ||
* The dragged item. | ||
* **event** — *object* | ||
* Hammer.js event data. | ||
**Examples** | ||
```javascript | ||
muuri.on('dragstart', function (item, data) { | ||
grid.on('dragStart', function (item, event) { | ||
console.log(event); | ||
console.log(item); | ||
console.log(data); | ||
}); | ||
``` | ||
### `dragmove` | ||
### dragMove | ||
Triggered when an item is dragged. | ||
**Listener parameters** | ||
**Arguments** | ||
* **item** — *Muuri.Item* | ||
* `Muuri.Item` instance that is being dragged. | ||
* **data** — *object* | ||
* **data.type** — *String* | ||
* `"dragmove"` | ||
* **data.event** — *object* | ||
* The hammer event for the drag start event. | ||
* **data.currentLeft** — *number* | ||
* The dragged element's current translateX value. | ||
* **data.currentTop** — *object* | ||
* The dragged element's current translateY value. | ||
* **data.gridLeft** — *number* | ||
* The dragged element's current x-coordinate within the muuri container element. | ||
* **data.gridTop** — *object* | ||
* The dragged element's current y-coordinate within the muuri container element. | ||
* The dragged item. | ||
* **event** — *object* | ||
* Hammer.js event data. | ||
**Examples** | ||
```javascript | ||
muuri.on('dragmove', function (item, data) { | ||
grid.on('dragMove', function (item, event) { | ||
console.log(event); | ||
console.log(item); | ||
console.log(data); | ||
}); | ||
``` | ||
### `dragscroll` | ||
### dragScroll | ||
Triggered when any of the scroll parents of a dragged item is scrolled. | ||
**Listener parameters** | ||
**Arguments** | ||
* **item** — *Muuri.Item* | ||
* `Muuri.Item` instance that is being dragged. | ||
* **data** — *object* | ||
* **data.type** — *String* | ||
* `"dragscroll"` | ||
* **data.event** — *object* | ||
* Th scroll event. | ||
* **data.currentLeft** — *number* | ||
* The dragged element's current translateX value. | ||
* **data.currentTop** — *object* | ||
* The dragged element's current translateY value. | ||
* **data.gridLeft** — *number* | ||
* The dragged element's current x-coordinate within the muuri container element. | ||
* **data.gridTop** — *object* | ||
* The dragged element's current y-coordinate within the muuri container element. | ||
* The dragged item. | ||
* **event** — *object* | ||
* The scroll event data. | ||
**Examples** | ||
```javascript | ||
muuri.on('dragscroll', function (item, data) { | ||
grid.on('dragScroll', function (item, event) { | ||
console.log(event); | ||
console.log(item); | ||
console.log(data); | ||
}); | ||
``` | ||
### `dragend` | ||
### dragEnd | ||
Triggered after item dragging ends. | ||
Triggered when dragging of an item ends. | ||
**Listener parameters** | ||
**Arguments** | ||
* **item** — *Muuri.Item* | ||
* `Muuri.Item` instance that is being dragged. | ||
* **data** — *object* | ||
* **data.type** — *String* | ||
* `"dragend"` | ||
* **data.event** — *object* | ||
* The hammer event for the drag start event. | ||
* **data.currentLeft** — *number* | ||
* The dragged element's current translateX value. | ||
* **data.currentTop** — *object* | ||
* The dragged element's current translateY value. | ||
* **data.gridLeft** — *number* | ||
* The dragged element's current x-coordinate within the muuri container element. | ||
* **data.gridTop** — *object* | ||
* The dragged element's current y-coordinate within the muuri container element. | ||
* The dragged item. | ||
* **event** — *object* | ||
* Hammer.js event data. | ||
**Examples** | ||
```javascript | ||
muuri.on('dragend', function (item, data) { | ||
grid.on('dragEnd', function (item, event) { | ||
console.log(event); | ||
console.log(item); | ||
console.log(data); | ||
}); | ||
``` | ||
### `releasestart` | ||
### dragReleaseStart | ||
Triggered when item is released (right after dragging ends). | ||
Triggered when a dragged item is released. | ||
**Listener parameters** | ||
**Arguments** | ||
* **item** — *Muuri.Item* | ||
* `Muuri.Item` instance that is being dragged. | ||
* The released item. | ||
**Examples** | ||
```javascript | ||
muuri.on('releasestart', function (item) { | ||
grid.on('dragReleaseStart', function (item) { | ||
console.log(item); | ||
@@ -1027,15 +1739,13 @@ }); | ||
### `releaseend` | ||
### dragReleaseEnd | ||
Triggered after item has finished the release procedure (animated back to it's position if animations are enabled). | ||
Triggered after released item has been animated to position. | ||
**Listener parameters** | ||
**Arguments** | ||
* **item** — *Muuri.Item* | ||
* `Muuri.Item` instance that is being dragged. | ||
* The released item. | ||
**Examples** | ||
```javascript | ||
muuri.on('releaseend', function (item) { | ||
grid.on('dragReleaseEnd', function (item) { | ||
console.log(item); | ||
@@ -1045,10 +1755,8 @@ }); | ||
### `destroy` | ||
### destroy | ||
Triggered after `muuri.destroy()` method is called. | ||
Triggered after `grid.destroy()` is called. | ||
**Examples** | ||
```javascript | ||
muuri.on('destroy', function () { | ||
grid.on('destroy', function () { | ||
console.log('Muuri is no more...'); | ||
@@ -1058,2 +1766,165 @@ }); | ||
### Item methods | ||
* [item.getGrid()](#itemgetgrid) | ||
* [item.getElement()](#itemgetelement) | ||
* [item.getWidth()](#itemgetwidth) | ||
* [item.getHeight()](#itemgetheight) | ||
* [item.getMargin()](#itemgetmargin) | ||
* [item.getPosition()](#itemgetposition) | ||
* [item.isActive()](#itemisactive) | ||
* [item.isVisible()](#itemisvisible) | ||
* [item.isShowing()](#itemisshowing) | ||
* [item.isHiding()](#itemishiding) | ||
* [item.isPositioning()](#itemispositioning) | ||
* [item.isDragging()](#itemisdragging) | ||
* [item.isReleasing()](#itemisreleasing) | ||
### item.getGrid() | ||
Get the instance's grid instance. | ||
**Returns** — *Muuri* | ||
```javascript | ||
var grid = item.getMuuri(); | ||
``` | ||
### item.getElement() | ||
Get the instance element. | ||
**Returns** — *element* | ||
```javascript | ||
var elem = item.getElement(); | ||
``` | ||
### item.getWidth() | ||
Get instance element's cached width. The returned value includes the element's paddings and borders. Note that the values are rounded with `Math.round()`. | ||
**Returns** — *number* | ||
```javascript | ||
var width = item.getWidth(); | ||
``` | ||
### item.getHeight() | ||
Get instance element's cached height. The returned value includes the element's paddings and borders. Note that the values are rounded with `Math.round()`. | ||
**Returns** — *number* | ||
```javascript | ||
var height = item.getHeight(); | ||
``` | ||
### item.getMargin() | ||
Get instance element's cached margins. Note that the values are rounded with `Math.round()`. | ||
**Returns** — *object* | ||
* **obj.left** — *number* | ||
* **obj.right** — *number* | ||
* **obj.top** — *number* | ||
* **obj.bottom** — *number* | ||
```javascript | ||
var margin = item.getMargin(); | ||
``` | ||
### item.getPosition() | ||
Get instance element's cached position (relative to the container element). | ||
**Returns** — *object* | ||
* **obj.left** — *number* | ||
* **obj.top** — *number* | ||
```javascript | ||
var position = item.getPosition(); | ||
``` | ||
### item.isActive() | ||
Check if the item is currently *active*. Only active items are considered to be part of the layout. | ||
**Returns** — *boolean* | ||
```javascript | ||
var isActive = item.isActive(); | ||
``` | ||
### item.isVisible() | ||
Check if the item is currently *visible*. | ||
**Returns** — *boolean* | ||
```javascript | ||
var isVisible = item.isVisible(); | ||
``` | ||
### item.isShowing() | ||
Check if the item is currently animating to visible. | ||
**Returns** — *boolean* | ||
```javascript | ||
var isShowing = item.isShowing(); | ||
``` | ||
### item.isHiding() | ||
Check if the item is currently animating to hidden. | ||
**Returns** — *boolean* | ||
```javascript | ||
var isHiding = item.isHiding(); | ||
``` | ||
### item.isPositioning() | ||
Check if the item is currently being positioned. | ||
**Returns** — *boolean* | ||
```javascript | ||
var isPositioning = item.isPositioning(); | ||
``` | ||
### item.isDragging() | ||
Check if the item is currently being dragged. | ||
**Returns** — *boolean* | ||
```javascript | ||
var isDragging = item.isDragging(); | ||
``` | ||
### item.isReleasing() | ||
Check if the item is currently being released. | ||
**Returns** — *boolean* | ||
```javascript | ||
var isReleasing = item.isReleasing(); | ||
``` | ||
## Credits | ||
Created and maintained by [Niklas Rämö](https://github.com/niklasramo). | ||
* This project owes much to David DeSandro's [Masonry](http://masonry.desandro.com/) and [Packery](http://packery.metafizzy.co/) libraries. You should go ahead and check them out right now if you haven't yet. Thanks Dave! | ||
* Jukka Jylänki's research [A Thousand Ways to Pack the Bin](http://clb.demon.fi/files/RectangleBinPack.pdf) came in handy when building Muuri's layout algorithms. Thanks Jukka! | ||
* Big thanks to the people behind [Velocity.js](http://velocityjs.org/) and [Hammer.js](http://hammerjs.github.io/) for providing such awesome libraries. Muuri would be much less cool without animations and dragging. | ||
* [Haltu Oy](http://www.haltu.fi/) was responsible for initiating this project in the first place and funded the intial development. Thanks Haltu! | ||
## License | ||
@@ -1060,0 +1931,0 @@ |
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
1916
0
253114
2
22
5
4825
2
1