├── images
└── milo.png
├── example
├── main.js
├── style.css
├── index.html
└── bundle.js
├── .gitignore
├── package.json
├── lib
└── debounce.js
├── README.md
├── .jshintrc
├── milo.min.js
└── milo.js
/images/milo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/davidchase/milo/master/images/milo.png
--------------------------------------------------------------------------------
/example/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var Milo = require('../milo');
3 |
4 | var milo = new Milo({
5 | container: '.grid'
6 | });
7 |
8 | window.addEventListener('load', milo.buildGrid);
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Node ###
2 | # Logs
3 | logs
4 | *.log
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | node_modules
18 |
19 | *.DS_Store
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "milo-grid",
3 | "version": "1.0.1",
4 | "description": "Javascript Grid fallback for browsers that dont support column-count",
5 | "main": "milo.js",
6 | "directories": {
7 | "example": "example"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/davidchase/milo.git"
12 | },
13 | "keywords": [
14 | "grid",
15 | "columns",
16 | "grid-support"
17 | ],
18 | "author": "David Chase",
19 | "license": "MIT",
20 | "bugs": {
21 | "url": "https://github.com/davidchase/milo/issues"
22 | },
23 | "homepage": "https://github.com/davidchase/milo#readme"
24 | }
25 |
--------------------------------------------------------------------------------
/lib/debounce.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = function debounce(fn, threshold, isAsap) {
3 | var timeout, result;
4 |
5 | var debounced = function() {
6 | var args = arguments;
7 | var context = this;
8 |
9 | var delayed = function() {
10 | if (!isAsap) {
11 | result = fn.apply(context, args);
12 | }
13 | timeout = null;
14 | };
15 | if (timeout) {
16 | clearTimeout(timeout);
17 | } else if (isAsap) {
18 | result = fn.apply(context, args);
19 | }
20 | timeout = setTimeout(delayed, threshold);
21 | return result;
22 | };
23 | debounced.cancel = function() {
24 | clearTimeout(timeout);
25 | };
26 | return debounced;
27 | };
--------------------------------------------------------------------------------
/example/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 | body {
7 | background: #f6f4f2;
8 | font-family:'Helvetica Neue', Helvetica, sans-serif;
9 | margin: 13px;
10 | }
11 | h1 {
12 | text-align: center;
13 | margin-bottom: 26px;
14 | color: #3e3e3e;
15 | }
16 | .grid {
17 | margin: 0 auto;
18 | position: relative;
19 | width: 100%;
20 | }
21 | .grid-item {
22 | font-size: 13px;
23 | padding: 0px 0px 32px 0px;
24 | position: absolute;
25 | background: #fff;
26 | box-sizing: border-box;
27 | box-shadow: 0px 2px 5px 1px #ccc;
28 | width:auto;
29 | height: auto;
30 | }
31 |
32 | img {
33 | max-width: 100%;
34 | height:auto;
35 | display: inline-block;
36 | vertical-align: middle;
37 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Milo
2 | ======
3 |
4 | 
5 |
6 | A small pure javascript grid that provides as a nice fallback to browsers
7 | that don't currently support column-count such as IE8, IE9
8 |
9 | Simple usage:
10 | -------------
11 |
12 | Check out the [**demo**](https://rawgit.com/davidchase/milo/master/example/index.html)
13 |
14 | Use [browserify](http://browserify.org) for client commonjs `require`
15 |
16 | `npm install -g browserify`
17 |
18 | ```js
19 | var Milo = require('./milo');
20 |
21 | var milo = new Milo({
22 | container: '.grid'
23 | });
24 |
25 | window.addEventListener('load', milo.buildGrid);
26 | ```
27 |
28 | HTML can be formatted like so:
29 |
30 | ```html
31 |
32 |
...
33 |
...
34 |
...
35 |
...
36 | ...
37 |
38 | ```
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "nonew": true, // Prohibit use of constructors for side-effects.
3 | "curly": true, // Require {} for every new block or scope.
4 | "noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`.
5 | "forin": true, // Tolerate `for in` loops without `hasOwnPrototype`.
6 | "noempty": true, // Prohibit use of empty blocks.
7 | "node": true, // Enable globals available when code is running inside of the NodeJS runtime environment.
8 | "eqeqeq": true, // Require triple equals i.e. `===`.
9 | "strict": true, // Require `use strict` pragma in every file.
10 | "undef": true, // Require all non-global variables be declared before they are used.
11 | "newcap": true, // Require capitalization of all constructor functions e.g. `new F()`.
12 | "immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
13 | "browser": true, // Standard browser globals e.g. `window`, `document`.
14 | "freeze": true, // Prohibits overwriting prototypes of native objects e.g. Array, Data, etc
15 | "multistr": true, // Tolerate multi-line strings.
16 | "predef": [ "test", "setup", "teardown", "require" ],
17 | "sub": true
18 | }
--------------------------------------------------------------------------------
/milo.min.js:
--------------------------------------------------------------------------------
1 | "use strict";var debounce=require("./lib/debounce"),qs=document.querySelector.bind(document),MiloGrid=function(i){if(!i||"object"!=typeof i)throw new Error("Need to add at least a container");this.containerEl=qs(i.container),this.children=this.containerEl.children,this.gridItemMargin=i.margin||10,this.gridItemWidth=i.width||210,this._resizeBind()},MiloGridProto=MiloGrid.prototype;MiloGridProto._calcTopPosition=function(i){return i>=this.gridColumns?this.topOffset[i-this.gridColumns]:0},MiloGridProto._calcGridColumns=function(){this.containerWidth=this.containerEl.clientWidth,this.gridColumns=Math.floor(this.containerWidth/(this.gridItemWidth+this.gridItemMargin))},MiloGridProto.buildGrid=function(){var i=0,t=this.children.length;for(this.topOffset=[],this._calcGridColumns(),i;t>i;i++)this.children[i].style.cssText="margin:"+this.gridItemMargin/2+";top:"+this._calcTopPosition(i)+";left:"+(this.gridItemWidth+this.gridItemMargin)*Math.round(i%this.gridColumns)+";width:"+this.gridItemWidth+";",this.topOffset.push(this.children[i].offsetHeight+this.gridItemMargin+this.children[i].offsetTop)},MiloGridProto._destroyGrid=function(){var i=0,t=this.children.length;for(i;t>i;i++)this.children[i].style.cssText=""},MiloGridProto._resizeBind=function(){var i=function(){this.buildGrid()}.bind(this);window.addEventListener("resize",debounce(i,600))};var Milo=function(i){var t=new MiloGrid(i);this.buildGrid=t.buildGrid.bind(t)};module.exports=Milo;
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The Grid
5 |
6 |
7 |
8 | The Milo Project
9 | with special guest Bill Murray
10 | Images courtesy of http://fillmurray.com
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/milo.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var debounce = require('./lib/debounce');
4 | var qs = document.querySelector.bind(document);
5 | var MiloGrid = function(options) {
6 | if (!options || typeof options !== 'object') {
7 | throw new Error('Need to add at least a container');
8 | }
9 | this.containerEl = qs(options.container);
10 | this.children = this.containerEl.children;
11 | this.gridItemMargin = options.margin || 10;
12 | this.gridItemWidth = options.width || 210;
13 |
14 | this._resizeBind();
15 | };
16 | var MiloGridProto = MiloGrid.prototype;
17 |
18 | MiloGridProto._calcTopPosition = function(index) {
19 | return index >= this.gridColumns ? this.topOffset[index - this.gridColumns] : 0;
20 | };
21 |
22 | // to calculate the columns
23 | // get the current available width
24 | // then divide it by gridItem width + gridItem margin
25 | // we are using Math.floor to get the most possible
26 | // amount of columns to fit into the area allocated
27 | MiloGridProto._calcGridColumns = function() {
28 | this.containerWidth = this.containerEl.clientWidth;
29 | this.gridColumns = Math.floor((this.containerWidth / (this.gridItemWidth + this.gridItemMargin)));
30 | };
31 |
32 | MiloGridProto.buildGrid = function() {
33 | var idx = 0;
34 | var length = this.children.length;
35 | // clean array before each build
36 | this.topOffset = [];
37 |
38 | this._calcGridColumns();
39 |
40 | for (idx; idx < length; idx++) {
41 | this.children[idx].style.cssText =
42 | 'margin:' + this.gridItemMargin / 2 + 'px;' +
43 | 'top:' + this._calcTopPosition(idx) + 'px;' +
44 | 'left:' + (this.gridItemWidth + this.gridItemMargin) * Math.round(idx % this.gridColumns) + 'px;' +
45 | 'width:' + this.gridItemWidth + 'px;';
46 |
47 | this.topOffset.push(this.children[idx].offsetHeight + this.gridItemMargin + this.children[idx].offsetTop);
48 | }
49 | };
50 |
51 | MiloGridProto._destroyGrid = function() {
52 | var idx = 0;
53 | var length = this.children.length;
54 | for (idx; idx < length; idx++) {
55 | this.children[idx].style.cssText = '';
56 | }
57 | };
58 |
59 | MiloGridProto._resizeBind = function() {
60 | var rebuildGrid = function() {
61 | this.buildGrid();
62 | }.bind(this);
63 |
64 | // debounce the window resize
65 | // to minimize the amount of rebuild calls
66 | window.addEventListener('resize', debounce(rebuildGrid, 600));
67 | };
68 |
69 | // expose a public api
70 | var Milo = function(options) {
71 | var miloGrid = new MiloGrid(options);
72 | this.buildGrid = miloGrid.buildGrid.bind(miloGrid);
73 | };
74 |
75 | module.exports = Milo;
--------------------------------------------------------------------------------
/example/bundle.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= this.gridColumns ? this.topOffset[index - this.gridColumns] : 0;
58 | };
59 |
60 | // to calculate the columns
61 | // get the current available width
62 | // then divide it by gridItem width + gridItem margin
63 | // we are using Math.floor to get the most possible
64 | // amount of columns to fit into the area allocated
65 | MiloGridProto._calcGridColumns = function() {
66 | this.containerWidth = this.containerEl.clientWidth;
67 | this.gridColumns = Math.floor((this.containerWidth / (this.gridItemWidth + this.gridItemMargin)));
68 | };
69 |
70 | MiloGridProto.buildGrid = function() {
71 | var idx = 0;
72 | var length = this.children.length;
73 | // clean array before each build
74 | this.topOffset = [];
75 |
76 | this._calcGridColumns();
77 |
78 | for (idx; idx < length; idx++) {
79 | this.children[idx].style.cssText =
80 | 'margin:' + this.gridItemMargin / 2 + 'px;' +
81 | 'top:' + this._calcTopPosition(idx) + 'px;' +
82 | 'left:' + (this.gridItemWidth + this.gridItemMargin) * Math.round(idx % this.gridColumns) + 'px;' +
83 | 'width:' + this.gridItemWidth + 'px;';
84 |
85 | this.topOffset.push(this.children[idx].offsetHeight + this.gridItemMargin + this.children[idx].offsetTop);
86 | }
87 | };
88 |
89 | MiloGridProto._destroyGrid = function() {
90 | var idx = 0;
91 | var length = this.children.length;
92 | for (idx; idx < length; idx++) {
93 | this.children[idx].style.cssText = '';
94 | }
95 | };
96 |
97 | MiloGridProto._resizeBind = function() {
98 | var rebuildGrid = function() {
99 | this.buildGrid();
100 | }.bind(this);
101 |
102 | // debounce the window resize
103 | // to minimize the amount of rebuild calls
104 | window.addEventListener('resize', debounce(rebuildGrid, 600));
105 | };
106 |
107 | // expose a public api
108 | var Milo = function(options) {
109 | var miloGrid = new MiloGrid(options);
110 | this.buildGrid = miloGrid.buildGrid.bind(miloGrid);
111 | };
112 |
113 | module.exports = Milo;
114 | },{"./lib/debounce":2}]},{},[1]);
115 |
--------------------------------------------------------------------------------