jack's boxes
by Felis Catus
HTML
<script src="http://fb.me/react-with-addons-0.12.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.0.js"></script>
<script src="http://fb.me/react-js-fiddle-integration.js"></script>
CSS
.Grid {
position: relative;
margin: 10px;
padding: 5px;
background-color: rgba(6, 60, 109, 1);
-webkit-transition: all .3s;
-moz-transition: all .3s;
-o-transition: all .3s;
transition: all .3s;
}
.block {
background-color: rgba(255, 164, 25, 1);
-webkit-transition: all .3s;
-moz-transition: all .3s;
-o-transition: all .3s;
transition: all .3s;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.active {
opacity: 0.4;
}
.placeholder {
z-index: 1000;
background-color: rgba(255, 164, 25, 1);
-moz-box-shadow: 1px 1px 2px 2px #000;
-webkit-box-shadow: 1px 1px 2px 2px #000;
box-shadow: 1px 1px 2px 2px #000;
}
.addBlock {
background-color: rgba(255, 164, 25, 0.6);
border: 5px dashed rgba(255, 164, 25, 0.8);
cursor: pointer;
-webkit-transition: all .3s;
-moz-transition: all .3s;
-o-transition: all .3s;
transition: all .3s;
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
.removeBlock {
min-width: 24px;
min-height: 18px;
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAQCAYAAAAMJL+VAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAABigAAAYoBM5cwWAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAACDSURBVDjLY/j//z8DLTHDgFsABAZAzINFnAckR5EFQFABxCDGZSAWQxIXg4qBOBVkWQAENlADYPgqEItD8VU0ORtyLBAF4vtoBl2HYmQxkBpRcoNIDojvohmIjEFycpRGsiwQ38FiOEhMlhqpiHYW0DSIaB7JNE+mNM9odCkqhkRpCgDUbYLSOAz5bwAAAABJRU5ErkJggg71016572dfa09f0c81c90339e17120a3');
position: absolute;
top: 0;
right: -3px;
cursor: pointer;
}
.resizeBlock {
min-width: 16px;
min-height: 16px;
background-image:...
JavaScript 1.7
var u = {
copyLayout: function(layout) {
return layout.map(function (block, i) {
var b = {};
Object.keys(block).forEach(function (key) {
b[key] = block[key];
});
return b;
});
},
getRowsCols: function (layout, arg) {
return layout.reduce(function (prev, cur) {
return Math.max(prev, cur[arg] + cur[arg + 'span']);
}, 1);
},
exclude: function (layout, block) {
return layout.filter(function (b) {
return b !== block;
});
},
getBlock: function (layout, row, col) {
return layout.filter(function (b) {
return b.row === row && b.col === col;
})[0];
},
getCollisions: function (layout, block) {
return layout.filter(function (b) {
return b !== block && !(
b.row + b.rowspan <= block.row ||
b.row >= block.row + block.rowspan ||
b.col + b.colspan <= block.col ||
b.col >= block.col + block.colspan
);
});
},
doesBlockCollide: function (layout, block) {
return u.getCollisions(layout, block).length > 0;
},
compactLayout: function (layout) {
var rows = u.getRowsCols(layout, 'row');
var cols = u.getRowsCols(layout, 'col');
for (var i = 0; i < rows; ++i) {
for (var j = 0; j < cols; ++j) {
var b = u.getBlock(layout, i, j);
if (b !== undefined) {
for (var r = b.row - 1; r >= 0; --r) {
b.row = r;
if (u.doesBlockCollide(layout, b)) {
b.row += 1;
break;
}
}
}
}
}
return layout;
},
resolveCollisions: function (layout, block, depth) {
if...