diff --git a/README.md b/README.md index fc22375..f46f6d8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ [![MIT License](https://img.shields.io/npm/l/magic-grid.svg?style=for-the-badge)](https://www.npmjs.com/package/magic-grid) [![Downloads](https://img.shields.io/npm/dt/magic-grid.svg?style=for-the-badge)](https://www.npmjs.com/package/magic-grid) + # Magic Grid [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Magic%20Grid%20-%20A%20simple,%20lightweight%20Javascript%20library%20for%20dynamic%20grid%20layouts.&url=https://github.com/e-oj/Magic-Grid&hashtags=MagicGrid,GridLayout,JS) @@ -26,12 +27,13 @@ Check out [CSS Grid AMA's issue #19](https://github.com/rachelandrew/cssgrid- ### Ports -| Repo | Author | -|:--------|:-------| -| [Vue-Magic-Grid](https://github.com/imlinus/Vue-Magic-Grid) | [@imlinus](https://github.com/imlinus) | -| [Magic-Grid-React](https://github.com/IniZio/Magic-Grid-React) | [@IniZio](https://github.com/IniZio) | +| Repo | Author | +| :------------------------------------------------------------- | :------------------------------------- | +| [Vue-Magic-Grid](https://github.com/imlinus/Vue-Magic-Grid) | [@imlinus](https://github.com/imlinus) | +| [Magic-Grid-React](https://github.com/IniZio/Magic-Grid-React) | [@IniZio](https://github.com/IniZio) | ### Getting Started + #### Step 1 Get Magic Grid via NPM: @@ -41,6 +43,7 @@ npm install magic-grid ``` Or CDN + ```html @@ -53,11 +56,12 @@ Or CDN Import Magic Grid: ```javascript -import MagicGrid from "magic-grid" +import MagicGrid from "magic-grid"; // or let MagicGrid = require("magic-grid"); ``` +
You can also pull Magic Grid directly into your html @@ -80,8 +84,11 @@ magicGrid.listen(); ``` ### Usage + #### Static content: + If your container doesn't have any dynamically loaded content i.e., all its child elements are always in the DOM, you should initialize the grid this way: + ```javascript let magicGrid = new MagicGrid({ container: "#container", // Required. Can be a class, id, or an HTMLElement. @@ -93,11 +100,13 @@ magicGrid.listen(); ``` #### Dynamic content: + If the container relies on data from an api, or experiences a delay, for whatever reason, before it can render its content in the DOM, you need to let the grid know the number of items to expect: + ```javascript let magicGrid = new MagicGrid({ container: "#container", // Required. Can be a class, id, or an HTMLElement. - items: 20, // For a grid with 20 items. Required for dynamic content. + size: 20, // For a grid with 20 items. Required for dynamic content. animate: true, // Optional. }); @@ -107,27 +116,32 @@ magicGrid.listen(); ### API #### MagicGrid(config) - > config (required): Configuration object + +> config (required): Configuration object The MagicGrid constructor. Initializes the grid with a configuration object. + ```javascript let magicGrid = new MagicGrid({ container: "#container", // Required. Can be a class, id, or an HTMLElement static: false, // Required for static content. Default: false. - items: 30, // Required for dynamic content. Initial number of items in the container. + size: 30, // Required for dynamic content. Initial number of items in the container. + items: nodes, // Optional. Useful if items are not direct descendants of container. Default: this.container.children gutter: 30, // Optional. Space between items. Default: 25(px). maxColumns: 5, // Optional. Maximum number of columns. Default: Infinite. useMin: true, // Optional. Prioritize shorter columns when positioning items? Default: false. useTransform: true, // Optional. Position items using CSS transform? Default: True. animate: true, // Optional. Animate item positioning? Default: false. - center: true, //Optional. Center the grid items? Default: true. + center: true, //Optional. Center the grid items? Default: true. }); ``` --- #### .listen() + Positions the items and listens for changes to the window size. All items are repositioned whenever the window is resized. + ```javascript let magicGrid = new MagicGrid({ container: "#container", // Required. Can be a class, id, or an HTMLElement @@ -141,12 +155,13 @@ magicGrid.listen(); --- #### .positionItems() + This function is useful in cases where you have to manually trigger a repositioning; for instance, if a new element is added to the container. ```javascript let magicGrid = new MagicGrid({ container: "#container", // Required. Can be a class, id, or an HTMLElement - items: 30, // Required for dynamic content. + size: 30, // Required for dynamic content. animate: true, // Optional }); diff --git a/dist/magic-grid.cjs.js b/dist/magic-grid.cjs.js index b918866..27bb7ec 100644 --- a/dist/magic-grid.cjs.js +++ b/dist/magic-grid.cjs.js @@ -214,7 +214,7 @@ var checkParams = function checkParams(config) { config.gutter = DEFAULT_GUTTER; } if (!config.container) error("container"); - if (!config.items && !config["static"]) error("items or static"); + if (!config.items && !config.static) error("items or static"); }; /** @@ -253,6 +253,7 @@ var getMin = function getMin(cols) { }; var POSITIONING_COMPLETE_EVENT = "positionComplete"; +var REPOSITIONING_DELAY = 200; var MagicGrid = /*#__PURE__*/function (_EventEmitter) { /** @@ -262,6 +263,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { * @param config - configuration object */ function MagicGrid(config) { + var _config$items; var _this; _classCallCheck(this, MagicGrid); _this = _callSuper(this, MagicGrid); @@ -273,8 +275,9 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { _this.containerClass = config.container; _this.container = document.querySelector(config.container); } - _this["static"] = config["static"] || false; - _this.size = config.items; + _this.static = config.static || false; + _this.size = config.size; + _this.items = (_config$items = config.items) !== null && _config$items !== void 0 ? _config$items : _this.container.children; _this.gutter = config.gutter; _this.maxColumns = config.maxColumns || false; _this.useMin = config.useMin || false; @@ -298,7 +301,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { value: function initStyles() { if (!this.ready()) return; this.container.style.position = "relative"; - var items = this.items(); + var items = this.items; for (var i = 0; i < items.length; i++) { if (this.styledItems.has(items[i])) continue; var style = items[i].style; @@ -310,18 +313,6 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { } } - /** - * Gets a collection of all items in a grid. - * - * @return {HTMLCollection} - * @private - */ - }, { - key: "items", - value: function items() { - return this.container.children; - } - /** * Calculates the width of a column. * @@ -331,7 +322,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { }, { key: "colWidth", value: function colWidth() { - return this.items()[0].getBoundingClientRect().width + this.gutter; + return this.items[0].getBoundingClientRect().width + this.gutter; } /** @@ -400,7 +391,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { wSpace = _this$setup.wSpace; var maxHeight = 0; var colWidth = this.colWidth(); - var items = this.items(); + var items = this.items; wSpace = this.center ? Math.floor(wSpace / 2) : 0; this.initStyles(); for (var i = 0; i < items.length; i++) { @@ -434,8 +425,8 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { }, { key: "ready", value: function ready() { - if (this["static"]) return true; - return this.items().length >= this.size; + if (this.static) return true; + return this.items.length >= this.size; } /** @@ -466,7 +457,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { this.resizeObserver = new ResizeObserver(function () { setTimeout(function () { _this3.positionItems(); - }, 200); + }, REPOSITIONING_DELAY); }); this.resizeObserver.observe(this.container); } @@ -484,7 +475,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { window.addEventListener("resize", function () { setTimeout(function () { _this4.positionItems(); - }, 200); + }, REPOSITIONING_DELAY); }); this.observeContainerResize(); this.positionItems(); diff --git a/dist/magic-grid.esm.js b/dist/magic-grid.esm.js index 64ff861..a256e63 100644 --- a/dist/magic-grid.esm.js +++ b/dist/magic-grid.esm.js @@ -212,7 +212,7 @@ var checkParams = function checkParams(config) { config.gutter = DEFAULT_GUTTER; } if (!config.container) error("container"); - if (!config.items && !config["static"]) error("items or static"); + if (!config.items && !config.static) error("items or static"); }; /** @@ -251,6 +251,7 @@ var getMin = function getMin(cols) { }; var POSITIONING_COMPLETE_EVENT = "positionComplete"; +var REPOSITIONING_DELAY = 200; var MagicGrid = /*#__PURE__*/function (_EventEmitter) { /** @@ -260,6 +261,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { * @param config - configuration object */ function MagicGrid(config) { + var _config$items; var _this; _classCallCheck(this, MagicGrid); _this = _callSuper(this, MagicGrid); @@ -271,8 +273,9 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { _this.containerClass = config.container; _this.container = document.querySelector(config.container); } - _this["static"] = config["static"] || false; - _this.size = config.items; + _this.static = config.static || false; + _this.size = config.size; + _this.items = (_config$items = config.items) !== null && _config$items !== void 0 ? _config$items : _this.container.children; _this.gutter = config.gutter; _this.maxColumns = config.maxColumns || false; _this.useMin = config.useMin || false; @@ -296,7 +299,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { value: function initStyles() { if (!this.ready()) return; this.container.style.position = "relative"; - var items = this.items(); + var items = this.items; for (var i = 0; i < items.length; i++) { if (this.styledItems.has(items[i])) continue; var style = items[i].style; @@ -308,18 +311,6 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { } } - /** - * Gets a collection of all items in a grid. - * - * @return {HTMLCollection} - * @private - */ - }, { - key: "items", - value: function items() { - return this.container.children; - } - /** * Calculates the width of a column. * @@ -329,7 +320,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { }, { key: "colWidth", value: function colWidth() { - return this.items()[0].getBoundingClientRect().width + this.gutter; + return this.items[0].getBoundingClientRect().width + this.gutter; } /** @@ -398,7 +389,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { wSpace = _this$setup.wSpace; var maxHeight = 0; var colWidth = this.colWidth(); - var items = this.items(); + var items = this.items; wSpace = this.center ? Math.floor(wSpace / 2) : 0; this.initStyles(); for (var i = 0; i < items.length; i++) { @@ -432,8 +423,8 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { }, { key: "ready", value: function ready() { - if (this["static"]) return true; - return this.items().length >= this.size; + if (this.static) return true; + return this.items.length >= this.size; } /** @@ -464,7 +455,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { this.resizeObserver = new ResizeObserver(function () { setTimeout(function () { _this3.positionItems(); - }, 200); + }, REPOSITIONING_DELAY); }); this.resizeObserver.observe(this.container); } @@ -482,7 +473,7 @@ var MagicGrid = /*#__PURE__*/function (_EventEmitter) { window.addEventListener("resize", function () { setTimeout(function () { _this4.positionItems(); - }, 200); + }, REPOSITIONING_DELAY); }); this.observeContainerResize(); this.positionItems(); diff --git a/dist/magic-grid.min.js b/dist/magic-grid.min.js index 41eb6ac..dcef7ee 100644 --- a/dist/magic-grid.min.js +++ b/dist/magic-grid.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).MagicGrid=e()}(this,(function(){"use strict";function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=Array(e);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){i=i.call(e)},n:function(){var t=i.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==i.return||i.return()}finally{if(u)throw s}}}}function u(t){return u=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},u(t)}function c(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(t){}return(c=function(){return!!t})()}function f(t,e){return f=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},f(t,e)}function l(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var i=n.call(t,e);if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t,"string");return"symbol"==typeof e?e:e+""}var h=new WeakMap,y=function(t){throw new Error("Missing property '".concat(t,"' in MagicGrid config"))},p="positionComplete";return function(t){function e(t){var r;return i(this,e),r=n(this,e),function(t){if(!t)throw new Error("No config object has been provided.");for(var e=0,n=["useTransform","center"];ethis.maxColumns&&(n=this.maxColumns);for(var r=0;ri&&(i=a.height)}this.container.style.height=i+this.gutter+"px",this.isPositioning=!1,this.emit(p)}}},{key:"ready",value:function(){return!!this.static||this.items().length>=this.size}},{key:"getReady",value:function(){var t=this,e=setInterval((function(){t.container=document.querySelector(t.containerClass),t.ready()&&(clearInterval(e),t.listen())}),100)}},{key:"observeContainerResize",value:function(){var t=this;this.resizeObserver||(this.resizeObserver=new ResizeObserver((function(){setTimeout((function(){t.positionItems()}),200)})),this.resizeObserver.observe(this.container))}},{key:"listen",value:function(){var t=this;this.ready()?(window.addEventListener("resize",(function(){setTimeout((function(){t.positionItems()}),200)})),this.observeContainerResize(),this.positionItems()):this.getReady()}},{key:"onPositionComplete",value:function(t){this.addListener(p,t)}}])}(function(){return s((function t(){var n,r,s;i(this,t),o(this,h,void 0),r=this,s=[],(n=h).set(e(n,r),s)}),[{key:"addListener",value:function(t,e){r(h,this).push({event:t,handler:e})}},{key:"emit",value:function(t,e){var n,i=a(r(h,this));try{for(i.s();!(n=i.n()).done;){var o=n.value;o.event===t&&o.handler(e)}}catch(t){i.e(t)}finally{i.f()}}}])}())})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).MagicGrid=e()}(this,(function(){"use strict";function t(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,i=Array(e);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){i=i.call(e)},n:function(){var t=i.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==i.return||i.return()}finally{if(u)throw s}}}}function u(t){return u=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},u(t)}function c(){try{var t=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(t){}return(c=function(){return!!t})()}function f(t,e){return f=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},f(t,e)}function l(t){var e=function(t,e){if("object"!=typeof t||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var i=n.call(t,e);if("object"!=typeof i)return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t,"string");return"symbol"==typeof e?e:e+""}var h=new WeakMap,y=function(t){throw new Error("Missing property '".concat(t,"' in MagicGrid config"))},p="positionComplete";return function(t){function e(t){var r,o;return i(this,e),o=n(this,e),function(t){if(!t)throw new Error("No config object has been provided.");for(var e=0,n=["useTransform","center"];ethis.maxColumns&&(n=this.maxColumns);for(var r=0;ri&&(i=a.height)}this.container.style.height=i+this.gutter+"px",this.isPositioning=!1,this.emit(p)}}},{key:"ready",value:function(){return!!this.static||this.items.length>=this.size}},{key:"getReady",value:function(){var t=this,e=setInterval((function(){t.container=document.querySelector(t.containerClass),t.ready()&&(clearInterval(e),t.listen())}),100)}},{key:"observeContainerResize",value:function(){var t=this;this.resizeObserver||(this.resizeObserver=new ResizeObserver((function(){setTimeout((function(){t.positionItems()}),200)})),this.resizeObserver.observe(this.container))}},{key:"listen",value:function(){var t=this;this.ready()?(window.addEventListener("resize",(function(){setTimeout((function(){t.positionItems()}),200)})),this.observeContainerResize(),this.positionItems()):this.getReady()}},{key:"onPositionComplete",value:function(t){this.addListener(p,t)}}])}(function(){return s((function t(){var n,r,s;i(this,t),o(this,h,void 0),r=this,s=[],(n=h).set(e(n,r),s)}),[{key:"addListener",value:function(t,e){r(h,this).push({event:t,handler:e})}},{key:"emit",value:function(t,e){var n,i=a(r(h,this));try{for(i.s();!(n=i.n()).done;){var o=n.value;o.event===t&&o.handler(e)}}catch(t){i.e(t)}finally{i.f()}}}])}())})); diff --git a/index.d.ts b/index.d.ts index 8c2a6c4..a1e1e7c 100644 --- a/index.d.ts +++ b/index.d.ts @@ -10,7 +10,8 @@ export interface MagicGridProps{ container: string | HTMLElement; static?: boolean; - items?: number; + size?: number; + items?: Element[]; gutter?: number; maxColumns?: number; useMin?: boolean; diff --git a/src/index.js b/src/index.js index 3ccc9ed..898e4d4 100644 --- a/src/index.js +++ b/src/index.js @@ -16,7 +16,7 @@ class MagicGrid extends EventEmitter{ * Initializes the necessary variables * for a magic grid. * - * @param config - configuration object + * @param {import("../index.d.ts").MagicGridProps} config */ constructor (config) { super(); @@ -32,7 +32,8 @@ class MagicGrid extends EventEmitter{ } this.static = config.static || false; - this.size = config.items; + this.size = config.size; + this.items = config.items ?? this.container.children; this.gutter = config.gutter; this.maxColumns = config.maxColumns || false; this.useMin = config.useMin || false; @@ -53,7 +54,7 @@ class MagicGrid extends EventEmitter{ if (!this.ready()) return; this.container.style.position = "relative"; - const items = this.items(); + const items = this.items; for (let i = 0; i < items.length; i++) { if (this.styledItems.has(items[i])) continue; @@ -70,16 +71,6 @@ class MagicGrid extends EventEmitter{ } } - /** - * Gets a collection of all items in a grid. - * - * @return {HTMLCollection} - * @private - */ - items () { - return this.container.children; - } - /** * Calculates the width of a column. * @@ -87,7 +78,7 @@ class MagicGrid extends EventEmitter{ * @private */ colWidth () { - return this.items()[0].getBoundingClientRect().width + this.gutter; + return this.items[0].getBoundingClientRect().width + this.gutter; } /** @@ -150,7 +141,7 @@ class MagicGrid extends EventEmitter{ let { cols, wSpace } = this.setup(); let maxHeight = 0; let colWidth = this.colWidth(); - let items = this.items(); + let items = this.items; wSpace = this.center ? Math.floor(wSpace / 2) : 0; @@ -191,7 +182,7 @@ class MagicGrid extends EventEmitter{ */ ready () { if (this.static) return true; - return this.items().length >= this.size; + return this.items.length >= this.size; } /** diff --git a/test/nested.html b/test/nested.html new file mode 100644 index 0000000..2540e7d --- /dev/null +++ b/test/nested.html @@ -0,0 +1,72 @@ + + + + + Magic Grid + + + + +
+
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
+
+ + + + +