124 lines
2.7 KiB
JavaScript
124 lines
2.7 KiB
JavaScript
import * as File from WTK.File;
|
|
import * as Async from UnitJS.Async;
|
|
import compose from UnitJS.Fun;
|
|
import * as Dom from UnitJS.Dom;
|
|
import {color, tool} from Toolbox;
|
|
|
|
|
|
var grid = {
|
|
element: null,
|
|
data: null
|
|
};
|
|
var down = false;
|
|
|
|
return {
|
|
init: init
|
|
};
|
|
|
|
function init(size, elementId) {
|
|
grid.element = document.getElementById(elementId || 'grid');
|
|
for(var row = 0; row < size; row++) {
|
|
grid.element.appendChild(
|
|
makeRow({tag: 'td', attributes: bodyAttributes, row: row, size: size})
|
|
);
|
|
}
|
|
grid.data = emptyGrid(size);
|
|
grid.element.addEventListener('mouseleave', function() {
|
|
down = false;
|
|
});
|
|
document.getElementById('load').addEventListener('click', load);
|
|
document.getElementById('save').addEventListener('click', save);
|
|
}
|
|
|
|
function emptyGrid(size) {
|
|
var result = {};
|
|
for(var i = 0; i < size; i++) {
|
|
result[i] = {};
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function makeRow(config) {
|
|
var cells = [];
|
|
for(var column = 0; column < config.size; column++) {
|
|
cells.push(Dom.make(config.tag, config.attributes(config.row, column)));
|
|
}
|
|
return Dom.make('tr', {}, cells);
|
|
}
|
|
|
|
function bodyAttributes(i, j) {
|
|
return {
|
|
onMousedown: function(e) {
|
|
down = true;
|
|
if(tool() == 'draw') {
|
|
colorize(i, j, e.target);
|
|
}
|
|
},
|
|
onMouseup: function(e) {
|
|
down = false;
|
|
if(tool() == 'paint') {
|
|
paint(i, j);
|
|
}
|
|
},
|
|
onMouseenter: function(e) {
|
|
if(down && tool() == 'draw') {
|
|
colorize(i, j, e.target);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
function colorize(i, j, element) {
|
|
grid.data[i][j] = color();
|
|
element.className = grid.data[i][j];
|
|
}
|
|
|
|
function paint(i0, j0) {
|
|
var originColor = grid.data[i0][j0];
|
|
var size = grid.element.children.length;
|
|
var done = emptyGrid(size);
|
|
var queue = [{i: i0, j: j0}];
|
|
while(queue.length > 0) {
|
|
var p0 = queue[0];
|
|
colorize(p0.i, p0.j, grid.element.children[p0.i].children[p0.j]);
|
|
done[p0.i][p0.j] = true;
|
|
for(var d = -1; d < 2; d += 2) {
|
|
[{i: p0.i + d, j: p0.j}, {i: p0.i, j: p0.j + d}].forEach(function(p1) {
|
|
if(p1.i >= 0 && p1.i < size && p1.j >= 0 && p1.j < size
|
|
&& !done[p1.i][p1.j]
|
|
&& grid.data[p1.i][p1.j] == originColor) {
|
|
queue.push(p1);
|
|
}
|
|
});
|
|
}
|
|
queue.shift();
|
|
}
|
|
}
|
|
|
|
function load() {
|
|
Async.run(
|
|
Async.bind(
|
|
File.pick({accept: 'text/json,.json'}),
|
|
function(input) {
|
|
return File.load(input.files[0]);
|
|
},
|
|
Async.map(compose(setGridData, JSON.parse))
|
|
)
|
|
);
|
|
}
|
|
|
|
function setGridData(data) {
|
|
if(data != undefined) {
|
|
for(var row = 0; row < grid.element.children.length; row++) {
|
|
for(var column = 0; column < grid.element.children[row].children.length; column++) {
|
|
grid.data[row][column] = data[row][column];
|
|
grid.element.children[row].children[column].className = data[row][column];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function save() {
|
|
File.save('data:text/json,' + JSON.stringify(grid.data), "grid.json");
|
|
}
|