{"version":3,"sources":["components/masonry.js"],"names":["dmx","Component","extends","constructor","node","parent","this","onResize","bind","reflow","debounce","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","event","dmxMasonry","children","length","insideReflow","array","querySelectorAll","forEach","img","src","viewportWidth","innerWidth","props","breakpoint","nodes","childNodes","filter","nodeType","getComputedStyle","padding","parseFloat","paddingLeft","paddingRight","columnWidth","Math","floor","clientWidth","Event","dispatchEvent","err","document","createEvent","initEvent","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.onResize = this.onResize.bind(this);\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.onResize);\r\n },\r\n\r\n updated: function() {\r\n this.reflow();\r\n },\r\n\r\n onResize: function(event) {\r\n if (!event.dmxMasonry) {\r\n this.reflow();\r\n }\r\n },\r\n\r\n reflow: function() {\r\n if (!this.children.length) return;\r\n if (this.insideReflow) 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 // trigger resize now that we have width\r\n try {\r\n var event = new Event('resize');\r\n event.dmxMasonry = true;\r\n window.dispatchEvent(event);\r\n } catch (err) {\r\n var event = document.createEvent('Event');\r\n event.dmxMasonry = true;\r\n event.initEvent('resize', false, false);\r\n window.dispatchEvent(event);\r\n }\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"]}