{"version":3,"sources":["components/masonry.js"],"names":["dmx","Component","extends","constructor","node","parent","this","reflow","debounce","bind","breakpoints","sm","md","lg","xl","BaseComponent","call","attributes","columns","type","Number","default","columns-sm","columns-md","columns-lg","columns-xl","gutter","gutter-sm","gutter-md","gutter-lg","gutter-xl","preserve-order","Boolean","animated","animation-duration","methods","render","prototype","$node","style","setProperty","window","addEventListener","updated","children","length","array","querySelectorAll","forEach","img","dmxMasonry","src","viewportWidth","innerWidth","props","breakpoint","nodes","childNodes","filter","nodeType","getComputedStyle","padding","parseFloat","paddingLeft","paddingRight","columnWidth","Math","floor","clientWidth","columnHeights","Array","apply","map","nodesHeights","clientHeight","index","columnIndex","indexOf","min","x","y","dmxMasonryInit","requestAnimationFrame","max"],"mappings":"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","file":"../dmxMasonry/dmxMasonry.js","sourcesContent":["dmx.Component('masonry', {\r\n\r\n extends: 'repeat',\r\n\r\n constructor: function(node, parent) {\r\n this.reflow = dmx.debounce(this.reflow.bind(this));\r\n this.breakpoints = {\r\n sm: 480,\r\n md: 768,\r\n lg: 992,\r\n xl: 1200\r\n };\r\n dmx.BaseComponent.call(this, node, parent);\r\n },\r\n\r\n attributes: {\r\n columns: {\r\n // the number of columns to create\r\n type: Number,\r\n default: 4\r\n },\r\n\r\n 'columns-sm': { // >= 480px\r\n type: Number,\r\n default: null\r\n },\r\n\r\n 'columns-md': { // >= 768px\r\n type: Number,\r\n default: null\r\n },\r\n\r\n 'columns-lg': { // >= 992px\r\n type: Number,\r\n default: null\r\n },\r\n\r\n 'columns-xl': { // >= 1200px\r\n type: Number,\r\n default: null\r\n },\r\n\r\n gutter: {\r\n // the gutter size in px\r\n type: Number,\r\n default: 15\r\n },\r\n\r\n 'gutter-sm': { // >= 480px\r\n type: Number,\r\n default: null\r\n },\r\n\r\n 'gutter-md': { // >= 768px\r\n type: Number,\r\n default: null\r\n },\r\n\r\n 'gutter-lg': { // >= 992px\r\n type: Number,\r\n default: null\r\n },\r\n\r\n 'gutter-xl': { // >= 1200px\r\n type: Number,\r\n default: null\r\n },\r\n\r\n 'preserve-order': {\r\n // will order the items from left to right into the columns\r\n // when false it will optimize layout by equalizing the height of each column\r\n type: Boolean,\r\n default: false\r\n },\r\n\r\n animated: {\r\n type: Boolean,\r\n default: false\r\n },\r\n\r\n 'animation-duration': {\r\n type: Number,\r\n default: 400\r\n }\r\n },\r\n\r\n methods: {\r\n reflow: function() {\r\n // allow manual reflow (when user changes size of item outside of app connect)\r\n this.reflow();\r\n }\r\n },\r\n\r\n render: function(node) {\r\n dmx.Component('repeat').prototype.render.call(this, node);\r\n // container must have position relative\r\n this.$node.style.setProperty('position', 'relative');\r\n // listen to resize event\r\n window.addEventListener('resize', this.reflow.bind(this));\r\n },\r\n\r\n updated: function() {\r\n this.reflow();\r\n },\r\n\r\n reflow: function() {\r\n if (!this.children.length) return;\r\n\r\n dmx.array(this.$node.querySelectorAll('img')).forEach(function(img) {\r\n if (!img.dmxMasonry) {\r\n // attach load event listener to images to update layout\r\n img.addEventListener('load', this.reflow.bind(this));\r\n if (img.src) {\r\n img.src = img.src;\r\n }\r\n img.dmxMasonry = true;\r\n }\r\n }, this);\r\n\r\n var viewportWidth = window.innerWidth;\r\n var columns = this.props.columns;\r\n var gutter = this.props.gutter;\r\n\r\n ['sm','md','lg','xl'].forEach(function(breakpoint) {\r\n if (viewportWidth >= this.breakpoints[breakpoint]) {\r\n columns = this.props['columns-' + breakpoint] || columns;\r\n gutter = this.props['gutter-' + breakpoint] || gutter;\r\n }\r\n }, this);\r\n\r\n // get all nodes that must be updated\r\n var nodes = dmx.array(this.$node.childNodes).filter(function(node) { return node.nodeType === 1; });\r\n\r\n // calculate the column width\r\n var style = window.getComputedStyle(this.$node);\r\n var padding = {\r\n left: parseFloat(style.paddingLeft),\r\n right: parseFloat(style.paddingRight)\r\n }\r\n var columnWidth = Math.floor((this.$node.clientWidth - padding.left - padding.right - ((columns - 1) * gutter)) / columns);\r\n // set the width on all nodes\r\n nodes.forEach(function(node) {\r\n // force border-box\r\n node.style.setProperty('box-sizing', 'border-box');\r\n node.style.setProperty('width', columnWidth + 'px');\r\n }, this);\r\n // prepare an array for the column heights\r\n var columnHeights = Array.apply(null, Array(columns)).map(function() { return 0; });\r\n // get all the nodes heights\r\n var nodesHeights = nodes.map(function(node) { return node.clientHeight; });\r\n\r\n nodes.forEach(function(node, index) {\r\n // which column should we place the item\r\n var columnIndex = this.props['preserve-order'] ? index % columns : columnHeights.indexOf(Math.min.apply(Math, columnHeights));\r\n // calculate x position\r\n var x = (columnIndex * columnWidth) + (columnIndex * gutter);\r\n // calculate y position\r\n var y = columnHeights[columnIndex];\r\n\r\n // position the node\r\n node.style.setProperty('transform', 'translate3d(' + x + 'px, ' + y + 'px, 0px)');\r\n\r\n if (nodesHeights[index]) {\r\n // only execute following code on first run\r\n if (!node.dmxMasonryInit) {\r\n // set position absolute\r\n node.style.setProperty('position', 'absolute');\r\n if (this.props.animated) {\r\n node.style.setProperty('transition', 'transform ' + this.props['animation-duration'] + 'ms')\r\n }\r\n // we make it visible on the next animation frame to prevent some flickering\r\n window.requestAnimationFrame(function() {\r\n node.style.setProperty('visibility', 'visible');\r\n });\r\n // we did init this node, so not execute this code next reflow\r\n node.dmxMasonryInit = true;\r\n }\r\n\r\n // update the columns heights array\r\n columnHeights[columnIndex] += nodesHeights[index] + gutter;\r\n }\r\n }, this);\r\n\r\n this.$node.style.setProperty('height', (Math.max.apply(Math, columnHeights) - gutter) + 'px');\r\n }\r\n\r\n});\r\n"]}