diff options
| author | Jules Laplace <jules@okfoc.us> | 2014-11-21 13:33:20 -0500 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2014-11-21 13:33:20 -0500 |
| commit | fea42b1513e321b6c397c914327a9a4a7d96e331 (patch) | |
| tree | 0c52449d5e53fc60c30d06f75a0e7b6f9a3bd608 /js | |
| parent | 9546cd5705e723e4c39ad4b34f0e154b8ab5e904 (diff) | |
split up js and style a little
Diffstat (limited to 'js')
| -rw-r--r-- | js/app.js | 223 | ||||
| -rw-r--r-- | js/lex.js | 105 | ||||
| -rw-r--r-- | js/matrix.js | 90 | ||||
| -rw-r--r-- | js/tool.js | 16 |
4 files changed, 434 insertions, 0 deletions
diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..480b20c --- /dev/null +++ b/js/app.js @@ -0,0 +1,223 @@ +var contentType = 'text/plain;charset=utf-8' + +var cols = 80 +var rows = 24 +var dragging = false +var drawing = true +var erasing = false +var focused + +var canvas, tools, palette, brush, mode, current_tool + +var color_names = ("white black dark-blue green red dark-red purple orange" + + "yellow lime dark-cyan cyan blue magenta dark-gray light-gray").split(" "); +var letters = "abcdefghijklmnop"; +var colors = {}, controls = {} +color_names.forEach(function(name, i){ colors[name] = i }) + +// var tools = "square circle rectangle" + +function init () { + build() + bind() +} +function build () { + canvas = new Matrix (cols, rows, function(x,y){ + var lex = new Lex (x,y) + if (x > y || y > x + 20 || x > y / 4 + 10) { + lex.clear() + } + else { + lex.bg = x+y*y + lex.fg = (x+y)%2 + lex.char = ":" + } + lex.build() + return lex + }) + brush = new Matrix (5, 5, function(x,y){ + var lex = new Lex (x,y) + lex.build() + return lex + }) + palette = new Matrix (32, 2, function(x,y){ + var lex = new Lex (x,y) + lex.bg = y>>1 + lex.build() + return lex + }) + canvas.append(canvas_rapper) + brush.append(brush_rapper) + palette.append(palette_rapper) + + controls.circle = new Tool (circle_el) + controls.circle.use = function(){ + brush.generate = controls.circle.generate + brush.generate() + drawing = true + } + controls.circle.generate = function(){ + var fg = brush.fg, bg = brush.bg + var hw = brush.w/2|0, hh = brush.h/2|0 + brush.forEach(function(lex,x,y) { + var len = Math.sqrt(Math.pow(x-hw,2)+Math.pow(y-hh,2)) + if (len > Math.abs(hw)) { + lex.clear() + } + else { + lex.fill(fg,bg) + } + }) + } + + controls.square = new Tool (square_el) + controls.square.use = function(){ + brush.generate = controls.square.generate + brush.generate() + drawing = true + } + controls.square.generate = function(){ + var fg = brush.fg, bg = brush.bg + brush.fill(fg,bg) + } + + controls.text = new Tool (text_el) + controls.text.use = function(){ + brush.generate = controls.text.generate + brush.generate() + drawing = false + } + controls.text.generate = function(){ + } + + controls.width = new Lex (width_el) + controls.height = new Lex (height_el) + + controls.circle.focus() + + brush.bg = colors.red + brush.generate() + brush.build() +} +function bind () { + canvas.forEach(function(lex, x, y){ + lex.span.addEventListener('mousedown', function(e){ + e.preventDefault() + dragging = true + if (drawing) { + erasing = e.which == "3" + draw(lex, x, y, erasing) + } + else { + lex.focus() + } + }) + lex.span.addEventListener("mousemove", function(){ + if (! dragging) return + if (drawing) { + draw(lex, x, y, erasing) + } + else { + lex.focus() + } + }) + }) + palette.forEach(function(lex, x, y){ + lex.span.addEventListener('mousedown', function(e){ + e.preventDefault() + dragging = true + erasing = e.which == "3" + brush.fg = lex.fg + brush.bg = lex.bg + brush.generate() + }) + }) + brush.forEach(function(lex, x, y){ + lex.span.addEventListener('mousedown', function(e){ + e.preventDefault() + dragging = true +// lex.fill(lex.fg, lex.bg) + }) + }) + window.addEventListener('mouseup', function(){ + dragging = erasing = false + }); + + [controls.width, controls.height].forEach(function(lex){ + lex.span.addEventListener('mousedown', function(e){ + lex.focus() + }) + }); + + [controls.square, controls.circle, controls.text].forEach(function(tool){ + tool.span.addEventListener('mousedown', function(e){ + tool.focus() + }) + }) + + controls.width.key = int_key(function(n, keyCode){ + controls.width.blur() + controls.width.char = ""+n + controls.width.build() + brush.w = n + brush.rebuild() + }) + controls.height.key = int_key(function(n, keyCode){ + controls.height.blur() + controls.height.char = ""+n + controls.height.build() + brush.h = n + brush.rebuild() + }) + window.addEventListener('keydown', function(e){ + if (! e.metaKey && ! e.ctrlKey && ! e.altKey) { + e.preventDefault() + } + switch (e.keyCode) { + case 27: // esc + if (focused) focused.blur() + break + default: + if (focused) focused.key(String.fromCharCode(e.keyCode), e.keyCode) + break + } + }) +} +function int_key (f) { + return function (key, keyCode) { + var n = parseInt(key) + n && f(n) + } +} + + + +function draw (lex, x, y, erasing) { + stamp (canvas, brush, x, y, erasing) +} +function stamp (canvas, brush, x, y, erasing) { + hh = brush.w/2|0 + brush.forEach(function(lex, s, t){ + s += x-hh + t += y-hh + if (s >= 0 && s < canvas.w && t >= 0 && t < canvas.h) { + canvas.aa[t][s].clone(lex) + } + }) +} +function mod (i,n) { + return i - n * Math.floor(i / n) +} + +document.body.addEventListener('copy', function (e) { + if (e.clipboardData) { + e.preventDefault(); + e.clipboardData.setData(contentType, canvas.ascii()); + } + if (window.clipboardData) { + e.returnValue = false; + window.clipboardData.setData(contentType, canvas.ascii()); + } +}, false); + +init() diff --git a/js/lex.js b/js/lex.js new file mode 100644 index 0000000..39a47cd --- /dev/null +++ b/js/lex.js @@ -0,0 +1,105 @@ +function Lex (x,y) { + if (typeof x == "number") { + this.x = x + this.y = y + this.span = document.createElement("span") + } + else { + this.span = x + } + this.fg = colors.white + this.bg = colors.black + this.char = " " +} +Lex.prototype.build = function(){ + this.span.className = this.css() + this.span.innerHTML = this.html() +} +Lex.prototype.css = function(){ + return "f" + letters[this.fg&15] + "b" + letters[this.bg&15] +} +Lex.prototype.html = function(){ + return this.char == " " ? " " : this.char +} +Lex.prototype.irc = function(){ + if (this.bg == 1 && this.fg == 0) { +// return "\\x03" + "," + (this.bg&15) + this.char + return this.char + } + else { + return "\\x03" + (this.fg&15) + "," + (this.bg&15) + this.char + } +} +Lex.prototype.clone = function (lex){ + if (! erasing && lex.isClear()) return + this.fg = lex.fg + this.bg = lex.bg + this.char = lex.char + this.build() +} +Lex.prototype.fill = function(fg,bg){ + this.fg = fg + this.bg = bg + this.build() +} +Lex.prototype.eq = function(lex){ + return lex && this.fg == lex.fg && this.bg == lex.fg && this.char == lex.char +} +Lex.prototype.clear = function(){ + this.bg = 1 + this.fg = 0 + this.char = " " + this.build() +} +Lex.prototype.isClear = function(){ + return this.bg == 1 && this.fg == 0 && this.char == " " +} +Lex.prototype.focus = function(){ + if (focused) focused.blur() + this.span.classList.add('focused') + focused = this +} +Lex.prototype.blur = function(){ + this.span.classList.remove('focused') + focused = null +} +Lex.prototype.key = function(char, keyCode) { + console.log(keyCode, this.y, this.x) + switch (keyCode) { + case 8: + canvas.focusLex(this.y-1, this.x) + focused.char = " " + focused.build() + return + case 13: // return + canvas.focusLex(0, this.x+1) + break + case 38: // up + canvas.focusLex(this.y, this.x-1) + break + case 40: // down + canvas.focusLex(this.y, this.x+1) + break + case 37: // left + canvas.focusLex(this.y-1, this.x) + break + case 39: // right + canvas.focusLex(this.y+1, this.x) + break + default: + this.char = char + this.fg = brush.bg + this.build() + this.blur() + if (this.y < canvas.w-1) { + canvas.aa[this.x][this.y+1].focus() + } + else { + canvas.focusLex(0, this.x+1) + } + } +} +Lex.prototype.demolish = function(){ + this.span.parentNode.removeChild(this.span) + this.span = null +} diff --git a/js/matrix.js b/js/matrix.js new file mode 100644 index 0000000..ff734bf --- /dev/null +++ b/js/matrix.js @@ -0,0 +1,90 @@ +function Matrix (w,h,f){ + this.w = w + this.h = h + this.f = f + this.initialize() +} +Matrix.prototype.initialize = function(){ + var w = this.w, h = this.h, f = this.f + var aa = new Array (h) + for (var i = 0; i < h; i++) { + aa[i] = new Array (w) + for (var j = 0; j < w; j++) { + aa[i][j] = f(i,j) + } + } + this.aa = aa +} +Matrix.prototype.rebuild = function (){ + this.demolish() + this.initialize() + this.append() + this.generate && this.generate() +} +Matrix.prototype.demolish = function (){ + this.forEach(function(lex){ + lex.demolish() + }) + while (this.rapper.firstChild) { + this.rapper.removeChild(this.rapper.firstChild); + } + this.aa.forEach(function(row){ + row.length = 0 + }) + this.aa.length = 0 +} +Matrix.prototype.forEach = function(f){ + this.aa.forEach(function(row, y){ + row.forEach(function(lex, x){ + f(lex, x, y) + }) + }) +} +Matrix.prototype.focusLex = function(y,x){ + this.aa[mod(x,this.h)][mod(y,this.w)].focus() +} +Matrix.prototype.clear = function(){ + this.forEach(function(lex,x,y){ lex.clear() }) +} +Matrix.prototype.fill = function(fg, bg){ + this.fg = fg + this.bg = bg + this.forEach(function(lex,x,y){ + lex.fg = fg + lex.bg = bg + lex.build() + }) +} +Matrix.prototype.build = function(){ + this.forEach(function(lex,x,y){ + lex.build() + }) +} +Matrix.prototype.append = function(rapper){ + rapper = this.rapper = rapper || this.rapper + this.aa.forEach(function(row, y){ + var div = document.createElement("div") + row.forEach(function(lex, x) { + div.appendChild(lex.span) + }) + rapper.appendChild( div ) + }) +} +Matrix.prototype.ascii = function () { + var lines = this.aa.map(function(row, y){ + var last, line = "" + row.forEach(function(lex, x) { + if (lex.eq(last)) { + line += lex.char + } + else { + if (x > 0 && last && (last.bg != 1 || last.fg != 0)) line += "\\x03" + line += lex.irc() + last = lex + } + }) + return line.replace(/\s+$/,"") + }).filter(function(line){ return line.length > 0 }) + var txt = '/exec -out printf "' + lines.join("\\n") + '"\n' + return txt +}
\ No newline at end of file diff --git a/js/tool.js b/js/tool.js new file mode 100644 index 0000000..3b9b803 --- /dev/null +++ b/js/tool.js @@ -0,0 +1,16 @@ +function Tool (span) { + this.lex = new Lex (span) + this.span = span +} +Tool.prototype.use = function(){} +Tool.prototype.focus = function(){ + focused && focused.blur() + current_tool && current_tool.blur() + current_tool = this + this.span.classList.add('focused') + this.use() +} +Tool.prototype.blur = function(){ + current_tool = null + this.span.classList.remove('focused') +} |
