diff --git a/dist/salvattore.js b/dist/salvattore.js index 2f5ef47..19322bc 100644 --- a/dist/salvattore.js +++ b/dist/salvattore.js @@ -174,6 +174,14 @@ var self = {}, element.setAttribute("data-" + key, value); } return; + }, + get_from_dataset = function(element, key, value) { + // uses dataset function or a fallback for 0) { + return colsHeight.indexOf(minColHeight); } + + // otherwise, previous method fallback + for (i = 0; i < m; i++) { + child = children[i]; + currentRowCount = child.children.length + (fragments[i].children || fragments[i].childNodes).length; + if(lowestRowCount === 0) { + lowestRowCount = currentRowCount; + } if(currentRowCount < lowestRowCount) { index = i; lowestRowCount = currentRowCount; @@ -415,8 +432,17 @@ self.append_elements = function append_elements(grid, elements) { var columns = grid.children , numberOfColumns = columns.length , fragments = self.create_list_of_fragments(numberOfColumns) + , heightContainer = document.createElement("div") ; + // first of all, append all items to a column to be able to retrieve proper height + // (if you try to do that hidden from the screen, you can miss the good DOM/CSS context) + heightContainer.className = self.obtain_grid_settings(grid).columnClasses.join(" "); + heightContainer.appendChild(self.create_fragment(elements)); + grid.appendChild(heightContainer); + self.save_elements_height(elements); + grid.removeChild(heightContainer); + elements.forEach(function append_to_next_fragment(element) { var columnIndex = self.next_element_column_index(grid, fragments); fragments[columnIndex].appendChild(element); @@ -483,13 +509,38 @@ self.register_grid = function register_grid (grid) { grids.push(grid); }; +self.create_fragment = function create_fragment (elements) { + var frag = document.createDocumentFragment(); + Array.prototype.forEach.call(elements, function create_fragment_loop(element) { + frag.appendChild(element); + }); + return frag; +}; + +self.get_height_from_element = function get_height_from_element(el) { + var height = el.getBoundingClientRect().height; + if (!height) { + var h = get_from_dataset(el, "salvatorreHeight"); + if (h) { + height = parseInt(h, 10); + } + } + return height; +}; + +self.save_elements_height = function save_elements_height (elements) { + Array.prototype.forEach.call(elements, function save_element_height(el) { + add_to_dataset(el, "salvatorreHeight", el.getBoundingClientRect().height); + }); +}; + self.init = function init() { // adds required CSS rule to hide 'content' based // configuration. var css = document.createElement("style"); - css.innerHTML = "[data-columns]::before{visibility:hidden;position:absolute;font-size:1px;}"; + css.innerHTML = "[data-columns]::before{display:block;visibility:hidden;position:absolute;font-size:1px;}"; document.head.appendChild(css); // scans all the grids in the document and generates diff --git a/dist/salvattore.min.js b/dist/salvattore.min.js index c26dc4d..c7e73ea 100644 --- a/dist/salvattore.min.js +++ b/dist/salvattore.min.js @@ -2,4 +2,4 @@ * Salvattore 1.0.5 by @rnmp and @ppold * https://github.com/rnmp/salvattore */ -!function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define("salvattore",[],b):a.salvattore=b()}(this,function(){window.matchMedia||(window.matchMedia=function(){"use strict";var a=window.styleMedia||window.media;if(!a){var b=document.createElement("style"),c=document.getElementsByTagName("script")[0],d=null;b.type="text/css",b.id="matchmediajs-test",c.parentNode.insertBefore(b,c),d="getComputedStyle"in window&&window.getComputedStyle(b,null)||b.currentStyle,a={matchMedium:function(a){var c="@media "+a+"{ #matchmediajs-test { width: 1px; } }";return b.styleSheet?b.styleSheet.cssText=c:b.textContent=c,"1px"===d.width}}}return function(b){return{matches:a.matchMedium(b||"all"),media:b||"all"}}}()),function(){if(window.matchMedia&&window.matchMedia("all").addListener)return!1;var a=window.matchMedia,b=a("only all").matches,c=!1,d=0,e=[],f=function(){clearTimeout(d),d=setTimeout(function(){for(var b=0,c=e.length;c>b;b++){var d=e[b].mql,f=e[b].listeners||[],g=a(d.media).matches;if(g!==d.matches){d.matches=g;for(var h=0,i=f.length;i>h;h++)f[h].call(window,d)}}},30)};window.matchMedia=function(d){var g=a(d),h=[],i=0;return g.addListener=function(a){b&&(c||(c=!0,window.addEventListener("resize",f,!0)),0===i&&(i=e.push({mql:g,listeners:h})),h.push(a))},g.removeListener=function(a){for(var b=0,c=h.length;c>b;b++)h[b]===a&&h.splice(b,1)},g}}(),function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;c *:nth-child("+h+"n-"+l+")",j.push(d.querySelectorAll(f));j.forEach(function(a){var c=b.createElement("div"),d=b.createDocumentFragment();c.className=i.join(" "),Array.prototype.forEach.call(a,function(a){d.appendChild(a)}),c.appendChild(d),k.appendChild(c)}),a.appendChild(k),e(a,"columns",h)},c.remove_columns=function(c){var d=b.createRange();d.selectNodeContents(c);var f=Array.prototype.filter.call(d.extractContents().childNodes,function(b){return b instanceof a.HTMLElement}),g=f.length,h=f[0].childNodes.length,i=new Array(h*g);Array.prototype.forEach.call(f,function(a,b){Array.prototype.forEach.call(a.children,function(a,c){i[c*g+b]=a})});var j=b.createElement("div");return e(j,"columns",0),i.filter(function(a){return!!a}).forEach(function(a){j.appendChild(a)}),j},c.recreate_columns=function(b){a.requestAnimationFrame(function(){c.add_columns(b,c.remove_columns(b))})},c.media_query_change=function(a){a.matches&&Array.prototype.forEach.call(d,c.recreate_columns)},c.get_css_rules=function(a){var b;try{b=a.sheet.cssRules||a.sheet.rules}catch(c){return[]}return b||[]},c.get_stylesheets=function(){return Array.prototype.concat.call(Array.prototype.slice.call(b.querySelectorAll("style[type='text/css']")),Array.prototype.slice.call(b.querySelectorAll("link[rel='stylesheet']")))},c.media_rule_has_columns_selector=function(a){for(var b,c=a.length;c--;)if(b=a[c],b.selectorText&&b.selectorText.match(/\[data-columns\](.*)::?before$/))return!0;return!1},c.scan_media_queries=function(){var b=[];a.matchMedia&&(c.get_stylesheets().forEach(function(d){Array.prototype.forEach.call(c.get_css_rules(d),function(d){d.media&&c.media_rule_has_columns_selector(d.cssRules)&&b.push(a.matchMedia(d.media.mediaText))})}),b.forEach(function(a){a.addListener(c.media_query_change)}))},c.next_element_column_index=function(a,b){var c,d,e,f=a.children,g=f.length,h=0,i=0;for(e=0;g>e;e++)c=f[e],d=c.children.length+b[e].children.length,0===h&&(h=d),h>d&&(i=e,h=d);return i},c.create_list_of_fragments=function(a){for(var c=new Array(a),d=0;d!==a;)c[d]=b.createDocumentFragment(),d++;return c},c.append_elements=function(a,b){var d=a.children,e=d.length,f=c.create_list_of_fragments(e);b.forEach(function(b){var d=c.next_element_column_index(a,f);f[d].appendChild(b)}),Array.prototype.forEach.call(d,function(a,b){a.appendChild(f[b])})},c.prepend_elements=function(a,d){var e=a.children,f=e.length,g=c.create_list_of_fragments(f),h=f-1;d.forEach(function(a){var b=g[h];b.insertBefore(a,b.firstChild),0===h?h=f-1:h--}),Array.prototype.forEach.call(e,function(a,b){a.insertBefore(g[b],a.firstChild)});for(var i=b.createDocumentFragment(),j=d.length%f;0!==j--;)i.appendChild(a.lastChild);a.insertBefore(i,a.firstChild)},c.register_grid=function(f){if("none"!==a.getComputedStyle(f).display){var g=b.createRange();g.selectNodeContents(f);var h=b.createElement("div");h.appendChild(g.extractContents()),e(h,"columns",0),c.add_columns(f,h),d.push(f)}},c.init=function(){var a=b.createElement("style");a.innerHTML="[data-columns]::before{visibility:hidden;position:absolute;font-size:1px;}",b.head.appendChild(a);var d=b.querySelectorAll("[data-columns]");Array.prototype.forEach.call(d,c.register_grid),c.scan_media_queries()},c.init(),{append_elements:c.append_elements,prepend_elements:c.prepend_elements,register_grid:c.register_grid}}(window,window.document);return a}); \ No newline at end of file +!function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define("salvattore",[],b):a.salvattore=b()}(this,function(){window.matchMedia||(window.matchMedia=function(){"use strict";var a=window.styleMedia||window.media;if(!a){var b=document.createElement("style"),c=document.getElementsByTagName("script")[0],d=null;b.type="text/css",b.id="matchmediajs-test",c.parentNode.insertBefore(b,c),d="getComputedStyle"in window&&window.getComputedStyle(b,null)||b.currentStyle,a={matchMedium:function(a){var c="@media "+a+"{ #matchmediajs-test { width: 1px; } }";return b.styleSheet?b.styleSheet.cssText=c:b.textContent=c,"1px"===d.width}}}return function(b){return{matches:a.matchMedium(b||"all"),media:b||"all"}}}()),function(){if(window.matchMedia&&window.matchMedia("all").addListener)return!1;var a=window.matchMedia,b=a("only all").matches,c=!1,d=0,e=[],f=function(){clearTimeout(d),d=setTimeout(function(){for(var b=0,c=e.length;c>b;b++){var d=e[b].mql,f=e[b].listeners||[],g=a(d.media).matches;if(g!==d.matches){d.matches=g;for(var h=0,i=f.length;i>h;h++)f[h].call(window,d)}}},30)};window.matchMedia=function(d){var g=a(d),h=[],i=0;return g.addListener=function(a){b&&(c||(c=!0,window.addEventListener("resize",f,!0)),0===i&&(i=e.push({mql:g,listeners:h})),h.push(a))},g.removeListener=function(a){for(var b=0,c=h.length;c>b;b++)h[b]===a&&h.splice(b,1)},g}}(),function(){for(var a=0,b=["ms","moz","webkit","o"],c=0;cf;f++)l[f]=c.get_height_from_element(h[f]),Array.prototype.forEach.call(b[f].childNodes,m);if(g=Math.min.apply(Math,l),g>0)return l.indexOf(g);for(f=0;i>f;f++)d=h[f],e=d.children.length+(b[f].children||b[f].childNodes).length,0===j&&(j=e),j>e&&(k=f,j=e);return k},c.create_list_of_fragments=function(a){for(var c=new Array(a),d=0;d!==a;)c[d]=b.createDocumentFragment(),d++;return c},c.append_elements=function(a,d){var e=a.children,f=e.length,g=c.create_list_of_fragments(f),h=b.createElement("div");h.className=c.obtain_grid_settings(a).columnClasses.join(" "),h.appendChild(c.create_fragment(d)),a.appendChild(h),c.save_elements_height(d),a.removeChild(h),d.forEach(function(b){var d=c.next_element_column_index(a,g);g[d].appendChild(b)}),Array.prototype.forEach.call(e,function(a,b){a.appendChild(g[b])})},c.prepend_elements=function(a,d){var e=a.children,f=e.length,g=c.create_list_of_fragments(f),h=f-1;d.forEach(function(a){var b=g[h];b.insertBefore(a,b.firstChild),0===h?h=f-1:h--}),Array.prototype.forEach.call(e,function(a,b){a.insertBefore(g[b],a.firstChild)});for(var i=b.createDocumentFragment(),j=d.length%f;0!==j--;)i.appendChild(a.lastChild);a.insertBefore(i,a.firstChild)},c.register_grid=function(f){if("none"!==a.getComputedStyle(f).display){var g=b.createRange();g.selectNodeContents(f);var h=b.createElement("div");h.appendChild(g.extractContents()),e(h,"columns",0),c.add_columns(f,h),d.push(f)}},c.create_fragment=function(a){var c=b.createDocumentFragment();return Array.prototype.forEach.call(a,function(a){c.appendChild(a)}),c},c.get_height_from_element=function(a){var b=a.getBoundingClientRect().height;if(!b){var c=f(a,"salvatorreHeight");c&&(b=parseInt(c,10))}return b},c.save_elements_height=function(a){Array.prototype.forEach.call(a,function(a){e(a,"salvatorreHeight",a.getBoundingClientRect().height)})},c.init=function(){var a=b.createElement("style");a.innerHTML="[data-columns]::before{display:block;visibility:hidden;position:absolute;font-size:1px;}",b.head.appendChild(a);var d=b.querySelectorAll("[data-columns]");Array.prototype.forEach.call(d,c.register_grid),c.scan_media_queries()},c.init(),{append_elements:c.append_elements,prepend_elements:c.prepend_elements,register_grid:c.register_grid}}(window,window.document);return a}); \ No newline at end of file diff --git a/src/salvattore.js b/src/salvattore.js index fac6639..72a28e7 100644 --- a/src/salvattore.js +++ b/src/salvattore.js @@ -11,6 +11,14 @@ var self = {}, element.setAttribute("data-" + key, value); } return; + }, + get_from_dataset = function(element, key, value) { + // uses dataset function or a fallback for 0) { + return colsHeight.indexOf(minColHeight); + } + + // otherwise, previous method fallback for (i = 0; i < m; i++) { child = children[i]; currentRowCount = child.children.length + (fragments[i].children || fragments[i].childNodes).length; - if(lowestRowCount === 0) { - lowestRowCount = currentRowCount; - } + if(lowestRowCount === 0) { + lowestRowCount = currentRowCount; + } if(currentRowCount < lowestRowCount) { index = i; lowestRowCount = currentRowCount; @@ -252,8 +269,17 @@ self.append_elements = function append_elements(grid, elements) { var columns = grid.children , numberOfColumns = columns.length , fragments = self.create_list_of_fragments(numberOfColumns) + , heightContainer = document.createElement("div") ; + // first of all, append all items to a column to be able to retrieve proper height + // (if you try to do that hidden from the screen, you can miss the good DOM/CSS context) + heightContainer.className = self.obtain_grid_settings(grid).columnClasses.join(" "); + heightContainer.appendChild(self.create_fragment(elements)); + grid.appendChild(heightContainer); + self.save_elements_height(elements); + grid.removeChild(heightContainer); + elements.forEach(function append_to_next_fragment(element) { var columnIndex = self.next_element_column_index(grid, fragments); fragments[columnIndex].appendChild(element); @@ -320,13 +346,38 @@ self.register_grid = function register_grid (grid) { grids.push(grid); }; +self.create_fragment = function create_fragment (elements) { + var frag = document.createDocumentFragment(); + Array.prototype.forEach.call(elements, function create_fragment_loop(element) { + frag.appendChild(element); + }); + return frag; +}; + +self.get_height_from_element = function get_height_from_element(el) { + var height = el.getBoundingClientRect().height; + if (!height) { + var h = get_from_dataset(el, "salvatorreHeight"); + if (h) { + height = parseInt(h, 10); + } + } + return height; +}; + +self.save_elements_height = function save_elements_height (elements) { + Array.prototype.forEach.call(elements, function save_element_height(el) { + add_to_dataset(el, "salvatorreHeight", el.getBoundingClientRect().height); + }); +}; + self.init = function init() { // adds required CSS rule to hide 'content' based // configuration. var css = document.createElement("style"); - css.innerHTML = "[data-columns]::before{visibility:hidden;position:absolute;font-size:1px;}"; + css.innerHTML = "[data-columns]::before{display:block;visibility:hidden;position:absolute;font-size:1px;}"; document.head.appendChild(css); // scans all the grids in the document and generates