Skip to content

Instantly share code, notes, and snippets.

@boertel
Last active August 29, 2015 14:06
Show Gist options
  • Select an option

  • Save boertel/f4ee743a7cc523e14e1f to your computer and use it in GitHub Desktop.

Select an option

Save boertel/f4ee743a7cc523e14e1f to your computer and use it in GitHub Desktop.
Grid constructor
body {
font-family: Helvetica;
}
.controls {
margin-bottom: 20px;
}
.square {
position: relative;
}
.square .row {
overflow: hidden;
}
.square .column-1 {
width: 40px;
height: 40px;
float: left;
margin: 2px;
background-color: #ccc;
border-radius: 4px;
border: 1px solid #ccc;
text-align: center;
}
.square .column-1.active {
border-width: 1px;
border-style: solid;
}
$('#export').on('click', function () {
$('#output').val(layout.export());
});
$('#import').on('click', function () {
layout.import($('#output').val());
layout.selections.forEach(function (selection) {
selection.select();
selection.blur();
})
});
$('#generate').on('click', function () {
$('#html').val(layout.html());
});
var onerow = true;
$('#one_row').on('change', function () {
onerow = $(this).is(':checked');
});
var squareContent = function ($node) {
for (var i = 0; i < 12; i += 1) {
var $row = $('<div></div>').addClass('row');
for (var j = 0; j < 12; j += 1) {
var column = $('<div></div>')
.attr('data-x', j)
.attr('data-y', i)
.addClass('column-1')
$row.append(column);
}
$node.append($row);
}
};
squareContent($('.square'))
function Selection(x1, x2, y1, y2, index) {
this.first = {x: x1, y: y1};
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.index = index;
this.classes = '.column-1.box-' + index;
}
Selection.prototype.set = function (x, y) {
this.x1 = x;
this.y1 = y;
};
Selection.prototype.sizex = function () {
return Math.abs(this.x1 - this.x2) + 1;
};
Selection.prototype.sizey = function () {
return Math.abs(this.y1 - this.y2) + 1;
};
Selection.prototype.minx = function () {
return Math.min(this.x1, this.x2);
};
Selection.prototype.miny = function () {
return Math.min(this.y1, this.y2);
};
Selection.prototype.remove = function () {
var index = this.index
$(this.classes)
.removeAttr('style')
.removeAttr('data-box')
.removeClass('box')
.removeClass('box-' + index)
.html('');
};
Selection.prototype.focus = function () {
$(this.classes).css({'opacity': 1})
};
Selection.prototype.blur = function () {
$(this.classes).css({'opacity': 0.5})
};
Selection.prototype.select = function () {
var index = this.index,
selectors = [];
this.remove();
var start = {
x: Math.min(this.x1, this.x2),
y: Math.min(this.y1, this.y2)
},
end = {
x: Math.max(this.x1, this.x2),
y: Math.max(this.y1, this.y2)
}
for (var x = start.x; x <= end.x; x += 1) {
for (var y = start.y; y <= end.y; y += 1) {
selectors.push('.column-1[data-x=' + x + '][data-y=' + y + ']');
}
}
var first = '.column-1[data-x=' + this.first.x + '][data-y=' + this.first.y + ']';
$(first).html(this.sizex() + ', ' + this.sizey());
$(selectors.join(',')).css({
'border-color': color(index),
'background-color': color(index, 0.1)
}).addClass('box-' + index).addClass('box')
.attr('data-box', index);
};
Selection.attributes = ['x1', 'x2', 'y1', 'y2', 'first', 'index'];
Selection.prototype.toJSON = function () {
var out = {};
Selection.attributes.forEach(function (attr) {
out[attr] = this[attr];
}, this);
return out
};
Selection.fromJSON = function (json) {
var args = [];
Selection.attributes.forEach(function (attr) {
args.push(json[attr]);
});
var selection = new Selection(json.x1, json.x2, json.y1, json.y2, json.index);
selection.first = json.first;
return selection;
};
Selection.sortX = function (a, b) {
return (a.minx() < b.minx()) ? -1 : 1;
};
Selection.sortY = function (a, b) {
return (a.miny() < b.miny()) ? -1 : 1;
}
function Layout (selections) {
this.selections = selections || [];
}
Layout.prototype.length = function () {
return this.selections.length;
};
Layout.prototype.push = function (selection) {
return this.selections.push(selection);
};
Layout.prototype.get = function (i) {
return this.selections[i];
};
Layout.prototype.remove = function (i) {
return this.selections.splice(i, 1);
};
Layout.prototype.indexOf = function (selection) {
return this.selections.indexOf(selection);
};
Layout.prototype.export = function () {
return JSON.stringify(this.selections);
};
Layout.prototype.import = function (str) {
var json = JSON.parse(str);
json.forEach(function (d) {
this.selections.push(Selection.fromJSON(d));
}, this);
return this.selections;
};
Layout.prototype.layout = function () {
var matrix = [],
selections = this.selections.slice(0);
selections.sort(Selection.sortY);
selections.forEach(function (d) {
matrix[d.miny()] = matrix[d.miny()] || []
matrix[d.miny()].push(d);
});
matrix.forEach(function (d) {
d.sort(Selection.sortX);
});
return matrix;
};
Layout.prototype.html = function () {
var matrix = this.layout(),
output = [];
matrix.forEach(function (y) {
output.push('<div class="row">');
y.forEach(function (x) {
output.push('<div class="column large-' + x.sizex() + '"></div>');
});
output.push('</div>');
});
return output.join('');
};
var current,
deactivated = true,
colors = [
[255, 0, 0],
[0, 255, 0],
[0, 0, 255],
[255, 255, 0],
[255, 0, 255],
[0, 255, 255],
];
function color (i, alpha) {
var index = i % colors.length;
var rgba = colors[index].slice(0);
alpha = alpha || 1;
rgba.push(alpha);
return 'rgba(' + rgba.join(',') + ')';
}
function draw() {
var x = $(this).data('x'),
y = $(this).data('y');
if (current === undefined) {
current = new Selection(x, x, y, y, layout.length());
layout.push(current);
}
if (onerow && y !== current.first.y) {
return;
}
current.set(x, y)
current.select();
}
function create () {
deactivated = !deactivated;
if (current === undefined) {
// start
draw.bind(this)();
} else {
// end
current.blur();
current = undefined
}
return false;
}
function edit () {
deactivated = false;
var i = parseInt($(this).attr('data-box'));
current = layout.get(i);
current.focus()
return false;
}
function remove() {
current.remove();
layout.remove(current.index);
current = undefined;
deactivated = true;
}
var layout = new Layout()
$('.column-1').on('mouseover', function (e) {
if (deactivated || ($(this).hasClass('box') && !$(this).hasClass('box-' + current.index))) {
return;
}
draw.bind(this)();
})
$('.column-1').on('click', function () {
if ($(this).hasClass('box')) {
if (current === undefined) {
edit.bind(this)()
return false;
}
}
create.bind(this)()
})
$(document).on('keyup', function (e) {
if (current !== undefined) {
switch (e.which) {
case 68:
remove()
break;
case 27:
create()
break;
}
}
return false;
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="./grid-constructor.css">
</head>
<body>
<div class="controls">
<div style="overflow: hidden;">
<div class="square" style="float: left;"></div>
<div class="output" style="float: left;">
<button id="export">Export</button>
<button id="import">Import</button>
<br>
<textarea id="output" name="" cols="30" rows="10"></textarea>
<hr>
<button id="generate">Generate</button>
<br>
<textarea id="html" name="" cols="30" rows="10"></textarea>
<hr>
<label><input type="checkbox" id="one_row" checked="checked">1 row only</label>
</div>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="./grid-constructor.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment