summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2014-11-21 13:33:20 -0500
committerJules Laplace <jules@okfoc.us>2014-11-21 13:33:20 -0500
commitfea42b1513e321b6c397c914327a9a4a7d96e331 (patch)
tree0c52449d5e53fc60c30d06f75a0e7b6f9a3bd608
parent9546cd5705e723e4c39ad4b34f0e154b8ab5e904 (diff)
split up js and style a little
-rw-r--r--css/sally.css13
-rw-r--r--index.html458
-rw-r--r--js/app.js223
-rw-r--r--js/lex.js105
-rw-r--r--js/matrix.js90
-rw-r--r--js/tool.js16
6 files changed, 455 insertions, 450 deletions
diff --git a/css/sally.css b/css/sally.css
index 81b4ba6..e5b5ed7 100644
--- a/css/sally.css
+++ b/css/sally.css
@@ -25,17 +25,24 @@ a:link, a:visited {text-decoration: none; color: #3b3740}
{overflow: auto;}
-.rapper {
+.rapper, .block {
float: left;
height:auto;
width:auto;
padding:4px;
background-color: #000000;
- z-index:3;
+}
+.rapper {
white-space:pre-wrap;
word-wrap: break-word;
}
-
+.block {
+ white-space:pre-line;
+ padding-left: 30px;
+}
+.tool {
+ cursor: pointer;
+}
@media screen and (-webkit-min-device-pixel-ratio:0) {
#nvgovy{white-space:pre;}
}
diff --git a/index.html b/index.html
index 3bb5058..3cb02b1 100644
--- a/index.html
+++ b/index.html
@@ -9,6 +9,7 @@ body.grid div { border-top: 1px solid #444; border-left: 1px solid #444; }
.tool.focused, .ed.focused { color: white; text-decoration: underline; }
body.grid .focused { box-shadow: inset 0 0 2px white, inset 0 0 2px white, inset 0 0 2px white; }
</style>
+
<body class="grid">
<div>
@@ -17,455 +18,18 @@ body.grid .focused { box-shadow: inset 0 0 2px white, inset 0 0 2px white, inset
<div style="clear:both">
<div id="palette_rapper" class="rapper"></div>
<div id="brush_rapper" class="rapper"></div>
-<div id="tools_rapper" class="rapper">
-<span id="square_el" class="tool">square</span>
-<span id="circle_el" class="tool">circle</span>
-<span id="text_el" class="tool">text</span>
+<div id="tools_rapper" class="block">
+ <span id="square_el" class="tool">square</span>
+ <span id="circle_el" class="tool">circle</span>
+ <span id="text_el" class="tool">text</span>
-brush size: <span id="width_el" class="ed">5</span> x <span id="height_el" class="ed">5</span>
+ brush size: <span id="width_el" class="ed">5</span> x <span id="height_el" class="ed">5</span>
</div>
</div>
-<script>
-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 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')
-}
-
-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 == " " ? "&nbsp;" : 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
-}
-
-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 )
- })
-}
-
-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)
-}
-function ascii () {
- var lines = canvas.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
-}
-
-document.body.addEventListener('copy', function (e) {
- if (e.clipboardData) {
- e.preventDefault();
- e.clipboardData.setData(contentType, ascii());
- }
- if (window.clipboardData) {
- e.returnValue = false;
- window.clipboardData.setData(contentType, ascii());
- }
-}, false);
-
-window.cssRule = function (selector, declaration) {
- var x = document.styleSheets,y=x.length-1;
- x[y].insertRule(selector+"{"+declaration+"}",x[y].cssRules.length);
-};
-
-init()
-</script>
+</body>
+<script src="js/lex.js"></script>
+<script src="js/matrix.js"></script>
+<script src="js/tool.js"></script>
+<script src="js/app.js"></script>
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 == " " ? "&nbsp;" : 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')
+}