asciimaker- draw ascii art straight from your web browser |
git clone git://git.acid.vegas/asciimaker.git |
Log | Files | Refs | Archive |
index.html (20181B)
1 <html> 2 <head> 3 <title>ASCII Maker</title> 4 <style> 5 .cell{width:8px;height:16px;cursor:default;font-size:10pt;font-weight:700;font-family:Courier New} 6 .noDrag{-moz-user-select:none} 7 #canvas,#picker{margin:auto} 8 #drafts{position:absolute;top:5px;left:5px;font-family:Verdana;font-size:8pt} 9 #textBuffer{position:absolute;width:1px;height:1px} 10 </style> 11 <script type="text/javascript"> 12 var halt = unescape('%0F'); 13 var code = unescape('%03'); 14 var brushColour = 4; 15 var mode = 0, isDragging = 0, canvasWidth = 0, canvasHeight = 0, selected = 0, curKey = 0, tool = 0; 16 var palette = new Array('FFFFFF', '000000', '00007F', '009300', 'FF0000', '7F0000', '9C009C', 'FC7F00', 'FFFF00', '00FC00', '009393', '00FFFF', '0000FC', 'FF00FF', '7F7F7F', 'D2D2D2'); 17 var drafts = new Array(); 18 var undo = new Array(); 19 20 function generateCanvas(width, height) { 21 canvasWidth = width; 22 canvasHeight = height; 23 document.getElementById('canvas').innerHTML = ''; 24 var tableGrid = document.createElement("table"); 25 tableGrid.setAttribute('cellpadding', '0'); 26 tableGrid.setAttribute('cellspacing', '0'); 27 tableGrid.setAttribute('onmousedown', 'toggleDragging(1);'); 28 tableGrid.setAttribute('onmouseup', 'toggleDragging(0);'); 29 tableGrid.setAttribute('background', 'data/checkered.png'); 30 for (var y = 0; y < height; y++) { 31 var currentLine = document.createElement("tr"); 32 for (var x = 0; x < width; x++) { 33 var currentCell = document.createElement("td"); 34 currentCell.setAttribute('class', 'cell'); 35 currentCell.innerHTML = ' '; 36 currentCell.setAttribute('onmousemove', 'fillCell(' + (width * y + x) + ');'); 37 currentCell.setAttribute('onmousedown', 'isDragging=1;fillCell(' + (width * y + x) + ');'); 38 currentLine.appendChild(currentCell); 39 } 40 tableGrid.appendChild(currentLine); 41 } 42 document.getElementById('canvas').style.width = x * 8 + 'px'; 43 document.getElementById('canvas').appendChild(tableGrid); 44 } 45 46 function generatePalette() { 47 var paletteGrid = document.createElement("table"); 48 paletteGrid.setAttribute('cellspacing', '2'); 49 var paletteLine = document.createElement("tr"); 50 for (i = 0; i < 16; i++) { 51 var currentPalette = document.createElement('td'); 52 currentPalette.setAttribute('style', 'width: 20px; height: 20px; background-color: #' + palette[i] + ';'); 53 currentPalette.setAttribute('onclick', 'setColour(' + i + ');'); 54 paletteLine.appendChild(currentPalette); 55 } 56 paletteGrid.appendChild(paletteLine); 57 document.getElementById('picker').style.width = '360px'; 58 document.getElementById('picker').appendChild(paletteGrid); 59 } 60 61 function setColour(i) { 62 brushColour = i; 63 } 64 65 function fillCell(index) { 66 if (tool == 0) { 67 if (isDragging == 1 && mode == 0) { 68 if (curKey != 17 && curKey != 18) setBackgroundColour(index); 69 else remBackgroundColour(index); 70 } else if (isDragging == 1 && mode == 1) { 71 if (curKey == 17 || curKey == 18) { 72 setLetter(index, ''); 73 remColour(index); 74 } 75 document.getElementById('textBuffer').focus(); 76 remCursor(selected); 77 selected = index; 78 setCursor(selected); 79 if (document.getElementsByTagName('td')[selected].innerHTML != ' ' && document.getElementsByTagName('td')[selected].innerHTML != '') document.getElementsByTagName('td')[selected].style.color = palette[brushColour]; 80 } 81 } else { 82 fillArea(index); 83 } 84 } 85 86 function fillArea(index) { 87 var newSeeds = new Array(); 88 var x = index % canvasWidth; 89 var y = (index - x) / canvasWidth; 90 var c = getCellColour(x, y); 91 var x1 = getLineColourLimits(x, y, 'left'); 92 var x2 = getLineColourLimits(x, y, 'right'); 93 if (isDragging == 1) { 94 for (var m = 0; m < 2; m++) { 95 y = (index - x) / canvasWidth + m; 96 while (y >= 0 && y <= canvasHeight) { 97 if (getCellColour(x, y) != c) break; 98 var x1 = getLineColourLimits(x, y, 'left'); 99 var x2 = getLineColourLimits(x, y, 'right'); 100 for (var i = x1; i <= x2; i++) 101 if (curKey != 17 && curKey != 18) setBackgroundColour((canvasWidth * y) + i); 102 else remBackgroundColour((canvasWidth * y) + i); 103 if (m == 0) y--; 104 else y++; 105 } 106 } 107 } 108 } 109 110 function getLineColourLimits(x, y, end) { 111 var boundary = x; 112 var currentColour; 113 var targetColour = getCellColour(x, y); 114 var i = x; 115 while (i >= 0 && i < canvasWidth) { 116 currentColour = getCellColour(i, y); 117 if (currentColour == targetColour) boundary = i; 118 else break; 119 if (end == 'left') i--; 120 else i++; 121 } 122 return boundary; 123 } 124 125 function toggleMode(newMode) { 126 if (newMode != undefined) mode = newMode; 127 if (mode == 1) { 128 remCursor(selected); 129 document.getElementById('typeButton').innerHTML = 'Type'; 130 } else { 131 toggleTool(1); 132 setCursor(selected); 133 document.getElementById('textBuffer').focus(); 134 document.getElementById('typeButton').innerHTML = 'Draw'; 135 } 136 mode = (mode - 1) * -1 137 } 138 139 function toggleTool(newTool) { 140 toggleMode(1); 141 if (newTool != undefined) tool = newTool; 142 if (tool == 1) document.getElementById('toolButton').innerHTML = 'Fill'; 143 else document.getElementById('toolButton').innerHTML = 'Brush'; 144 tool = (tool - 1) * -1 145 } 146 147 function toggleDragging(bool) { 148 isDragging = bool; 149 } 150 151 function padColour(colourCode, letter) { 152 if (colourCode < 10 && isNaN(parseFloat(letter)) == false) { 153 return '0' + colourCode; 154 } 155 return colourCode; 156 } 157 158 function renderArt() { 159 var line, output = '' 160 var lastColour, lastFontColour, currentColour, currentFontColour, breakout; 161 for (var y = 0; y < canvasHeight; y++) { 162 line = ''; 163 for (var x = 0; x < canvasWidth; x++) { 164 lastColour = getCellColour(x, y); 165 lastFontColour = getFontColour(x, y); 166 if (lastFontColour >= 0 && lastColour >= 0) { 167 line += code + lastFontColour + ',' + padColour(lastColour, getCellLetter(x, y)); 168 } else if (lastFontColour >= 0 && lastColour < 0) { 169 if (x != 0) line += halt; 170 line += code + padColour(lastFontColour, getCellLetter(x, y)); 171 } else if (lastFontColour < 0 && lastColour >= 0) { 172 line += code + lastColour + ',' + padColour(lastColour, getCellLetter(x, y)); 173 } else { 174 line += getCellLetter(x, y); 175 } 176 if (lastFontColour >= 0 || lastColour >= 0) { 177 breakout = 0; 178 for (var z = x; z < canvasWidth; z++) { 179 currentColour = getCellColour(z, y); 180 currentFontColour = getFontColour(z, y); 181 if (currentFontColour == lastFontColour && currentColour == lastColour) { 182 line += getCellLetter(z, y); 183 } else { 184 x = z - 1; 185 breakout = 1; 186 break; 187 } 188 } 189 line += code; 190 if (breakout == 0) x = canvasWidth; 191 } 192 } 193 output += endtrim(line, ' ') + " \n"; 194 } 195 var remove = new RegExp(code + code, 'gi'); 196 output = output.replace(remove, code); 197 output = output.replace(/</g, '<'); 198 output = output.replace(/>/g, '>'); 199 document.getElementById('load').value = endtrim(output); 200 } 201 202 function previewArt() { 203 renderArt(); 204 document.getElementById('preview').innerHTML = ''; 205 var tempForm = document.createElement('form'); 206 tempForm.setAttribute('method', 'POST'); 207 tempForm.setAttribute('action', '/preview/preview.php'); 208 tempForm.setAttribute('target', '_blank'); 209 var tempField = document.createElement('input'); 210 tempField.setAttribute('name', 'ascii'); 211 tempField.setAttribute('type', 'hidden'); 212 tempField.value = escape(document.getElementById('load').value); 213 var rawField = document.createElement('input'); 214 rawField.setAttribute('name', 'raw'); 215 rawField.setAttribute('type', 'hidden'); 216 rawField.value = 1; 217 tempForm.appendChild(tempField); 218 tempForm.appendChild(rawField); 219 document.getElementById('preview').appendChild(tempForm); 220 document.forms[0].submit(); 221 } 222 223 function resizeArt() { 224 var x = parseFloat(prompt('wqat width? (in characters)', canvasWidth)); 225 var y = parseFloat(prompt('wqat height? (in characters)', canvasHeight)); 226 renderArt(); 227 generateCanvas(x, y); 228 drawImage(); 229 } 230 231 function loadArt() { 232 var dimensions = getAsciiWidth(); 233 generateCanvas(dimensions[0], dimensions[1]); 234 drawImage(); 235 } 236 237 function drawImage() { 238 var g_width = 0; 239 var lines = endtrim(document.getElementById('load').value, "\n"); 240 lines = lines.split("\n"); 241 for (var y in lines) { 242 var index = y * canvasWidth; 243 var last_foreground = 16; 244 var last_background = 16; 245 var blocks = lines[y].split(code); 246 for (var b in blocks) { 247 if (blocks[b].length > 0) { 248 var colours = getColoursFromLine(blocks[b], blocks.length, last_foreground, last_background); 249 last_background = colours[1]; 250 for (var i = 0; i < colours[3].length; i++) { 251 if (colours[3].charCodeAt(i) == 15) { 252 last_background = 16; 253 } else if (colours[3].charCodeAt(i) > 31 && colours[3].charCodeAt(i) < 127) { 254 document.getElementsByTagName('td')[index].style.color = palette[parseFloat(colours[0])]; 255 if (colours[1] < 16) document.getElementsByTagName('td')[index].style.backgroundColor = palette[parseFloat(colours[1])]; 256 document.getElementsByTagName('td')[index].innerHTML = colours[3].charAt(i); 257 index++; 258 } 259 } 260 } 261 } 262 } 263 } 264 265 function endtrim(str, chars) { 266 chars = chars || "\\s"; 267 return str.replace(new RegExp("[" + chars + "]+$", "g"), ""); 268 } 269 270 function getColoursFromLine(line, block_count, last_foreground, last_background) { 271 var colours = new Array(); 272 if (block_count > 1) { 273 var chunks = line.split(',', 2); 274 for (var c in chunks) { 275 var current = ''; 276 for (var i = 0; i < 2; i++) { 277 if (isNaN(parseFloat(chunks[c].charAt(i))) == false) current += chunks[c].charAt(i); 278 } 279 if (isNaN(parseFloat(current)) == false) colours[colours.length] = current; 280 } 281 } 282 colours[3] = line.substr(colours.join(',').length); 283 if (typeof(colours[0]) != 'undefined' && typeof(colours[1]) == 'undefined') colours[1] = last_background; 284 if (typeof(colours[0]) == 'undefined') colours[0] = last_foreground; 285 return colours; 286 } 287 288 function getAsciiWidth() { 289 var g_width = 0; 290 var lines = endtrim(document.getElementById('load').value, "\n"); 291 lines = lines.split("\n"); 292 for (var y in lines) { 293 var l_width = 0; 294 var blocks = lines[y].split(code); 295 for (var b in blocks) { 296 if (blocks[b].length > 0) { 297 var colours = getColoursFromLine(blocks[b], blocks.length); 298 for (var i = 0; i < colours[3].length; i++) { 299 if (colours[3].charCodeAt(i) > 31 && colours[3].charCodeAt(i) < 127) l_width++; 300 } 301 } 302 } 303 if (l_width > g_width) g_width = l_width; 304 } 305 return new Array(g_width, lines.length); 306 } 307 308 function getCellColour(x, y) { 309 var colour = document.getElementsByTagName('td')[(canvasWidth * y + x)].style.backgroundColor; 310 return ircFromHex(rgbConvert(colour)); 311 } 312 313 function getFontColour(x, y) { 314 var colour = document.getElementsByTagName('td')[(canvasWidth * y + x)].style.color; 315 return ircFromHex(rgbConvert(colour)); 316 } 317 318 function getCellLetter(x, y) { 319 var letter = document.getElementsByTagName('td')[(canvasWidth * y + x)].innerHTML; 320 if (letter == '') letter = ' '; 321 return letter; 322 } 323 324 function rgbConvert(str) { 325 if (navigator.userAgent.match('Opera') == null) { 326 str = str.replace(/rgb\(|\)/g, "").split(","); 327 str[0] = parseInt(str[0], 10).toString(16).toUpperCase(); 328 str[1] = parseInt(str[1], 10).toString(16).toUpperCase(); 329 str[2] = parseInt(str[2], 10).toString(16).toUpperCase(); 330 str[0] = (str[0].length == 1) ? '0' + str[0] : str[0]; 331 str[1] = (str[1].length == 1) ? '0' + str[1] : str[1]; 332 str[2] = (str[2].length == 1) ? '0' + str[2] : str[2]; 333 return str.join(""); 334 } else { 335 return str.replace(/#/g, '').toUpperCase(); 336 } 337 } 338 339 function ircFromHex(hex) { 340 for (var i = 0; i < 16; i++) { 341 if (palette[i] == hex) return i; 342 } 343 return -1; 344 } 345 document.onmousemove = function moveBuffer(e) { 346 var y = e.clientY + document.body.scrollTop + 5; 347 if (y < (window.innerHeight + window.scrollMaxY - 30)) { 348 document.getElementById('textBuffer').style.left = '0px'; 349 document.getElementById('textBuffer').style.top = y + 'px'; 350 } 351 } 352 document.onkeydown = function setKey(e) { 353 var code; 354 if (window.event) code = window.event.keyCode; 355 else if (e) code = e.which; 356 curKey = code; 357 if (mode == 0) { 358 if (code == 38) // up 359 shiftArt('up'); 360 else if (code == 40) // down 361 shiftArt('down'); 362 else if (code == 37) // left 363 shiftArt('left'); 364 else if (code == 39) // right 365 shiftArt('right'); 366 } 367 if (curKey == 27) loadLastUndo(); 368 } 369 document.onkeyup = function handleKey(e) { 370 var code; 371 if (window.event) code = window.event.keyCode; 372 else if (e) code = e.which; 373 curKey = 0; 374 if (mode == 1) { 375 if (code == 8) { 376 remCursor(selected); 377 selected--; 378 setCursor(selected); 379 setLetter(selected, ''); 380 remColour(selected); 381 } else if (code == 38 && (selected - canvasWidth) >= 0) // up 382 moveCursor(selected - canvasWidth); 383 else if (code == 40 && (selected + canvasWidth) < canvasWidth * canvasHeight) // down 384 moveCursor(selected + canvasWidth); 385 else if (code == 37 && (selected - 1) >= 0) // left 386 moveCursor(selected - 1); 387 else if (code == 39 && (selected + 1) < canvasWidth * canvasHeight) // right 388 moveCursor(selected + 1); 389 else { 390 var data = document.getElementById('textBuffer').value; 391 for (var i = 0; i < data.length; i++) { 392 remCursor(selected); 393 setCursor(selected + 1); 394 setLetter(selected, data.charAt(i)); 395 selected++; 396 } 397 document.getElementById('textBuffer').value = ''; 398 } 399 } 400 } 401 402 function setCursor(index) { 403 document.getElementsByTagName('td')[index].style.backgroundImage = 'url(cursor.png)'; 404 } 405 406 function remCursor(index) { 407 document.getElementsByTagName('td')[index].style.backgroundImage = ''; 408 } 409 410 function moveCursor(index) { 411 remCursor(selected); 412 selected = index; 413 setCursor(selected); 414 } 415 416 function setLetter(index, data) { 417 document.getElementsByTagName('td')[index].style.color = palette[brushColour]; 418 document.getElementsByTagName('td')[index].innerHTML = data; 419 } 420 421 function remColour(index) { 422 document.getElementsByTagName('td')[index].style.color = ''; 423 } 424 425 function setBackgroundColour(index) { 426 if (rgbConvert(document.getElementsByTagName('td')[index].style.backgroundColor) != palette[brushColour]) { 427 saveStateUndo(index); 428 document.getElementsByTagName('td')[index].style.backgroundColor = palette[brushColour]; 429 } 430 } 431 432 function remBackgroundColour(index) { 433 if (document.getElementsByTagName('td')[index].style.backgroundColor != '') { 434 saveStateUndo(index); 435 document.getElementsByTagName('td')[index].style.backgroundColor = ''; 436 } 437 } 438 439 function saveStateUndo(index) { 440 if (undo.length > 50000) undo.splice(0, 1); 441 var i = undo.length; 442 undo[i] = new Array(); 443 undo[i][0] = index; 444 undo[i][1] = document.getElementsByTagName('td')[index].style.color; 445 undo[i][2] = document.getElementsByTagName('td')[index].style.backgroundColor; 446 undo[i][3] = document.getElementsByTagName('td')[index].innerHTML; 447 document.getElementById('undoButton').disabled = 0; 448 } 449 450 function loadLastUndo() { 451 if (undo.length > 0) { 452 var currentUndo = undo[undo.length - 1]; 453 document.getElementsByTagName('td')[currentUndo[0]].style.color = currentUndo[1]; 454 document.getElementsByTagName('td')[currentUndo[0]].style.backgroundColor = currentUndo[2]; 455 document.getElementsByTagName('td')[currentUndo[0]].innerHTML = currentUndo[3]; 456 undo.splice(undo.length - 1, 1); 457 if (undo.length <= 0) document.getElementById('undoButton').disabled = 1; 458 } else { 459 document.getElementById('undoButton').disabled = 1; 460 } 461 } 462 463 function addDraft() { 464 var d = new Date(); 465 var i = drafts.length; 466 renderArt(); 467 drafts[i] = new Array(); 468 drafts[i][0] = document.getElementById('load').value; 469 drafts[i][1] = d.toUTCString(); 470 drawDrafts(); 471 } 472 473 function drawDrafts() { 474 document.getElementById('drafts').innerHTML = ''; 475 for (var i in drafts) document.getElementById('drafts').innerHTML += '#' + i + ' <a style=\'cursor: pointer;\' onclick=\'loadDraft(' + i + ');\'>' + drafts[i][1] + "</a><br />\n"; 476 } 477 478 function loadDraft(index) { 479 document.getElementById('load').value = drafts[index][0]; 480 loadArt(); 481 } 482 483 function copyArt() { 484 copy(document.getElementById('load')); 485 } 486 487 function shiftArt(direction) { 488 var newLoc; 489 if (direction == 'down' || direction == 'right') var i = (canvasWidth * canvasHeight) - 1; 490 else var i = 0; 491 while (i >= 0 && i < (canvasWidth * canvasHeight)) { 492 if (direction == 'up' || direction == 'down') newLoc = i - canvasWidth; 493 else if (direction == 'left' || (direction == 'right')) newLoc = i - 1; 494 var newCell = document.getElementsByTagName('td')[newLoc]; 495 var oldCell = document.getElementsByTagName('td')[i]; 496 if (newLoc >= 0 && newLoc < (canvasWidth * canvasHeight)) { 497 if (direction == 'up' || direction == 'left') { 498 newCell.style.color = oldCell.style.color; 499 newCell.style.backgroundColor = oldCell.style.backgroundColor; 500 newCell.innerHTML = oldCell.innerHTML; 501 } else if (direction == 'down' || direction == 'right') { 502 oldCell.style.color = newCell.style.color; 503 oldCell.style.backgroundColor = newCell.style.backgroundColor; 504 oldCell.innerHTML = newCell.innerHTML; 505 } 506 } 507 if (direction == 'up' || direction == 'left') i++; 508 else if (direction == 'down' || direction == 'right') i--; 509 } 510 } 511 512 function copy(inElement) { 513 if (inElement.createTextRange) { 514 var range = inElement.createTextRange(); 515 if (range && BodyLoaded == 1) range.execCommand('Copy'); 516 } else { 517 var flashcopier = 'flashcopier'; 518 if (!document.getElementById(flashcopier)) { 519 var divholder = document.createElement('div'); 520 divholder.id = flashcopier; 521 document.body.appendChild(divholder); 522 } 523 document.getElementById(flashcopier).innerHTML = ''; 524 var divinfo = '<embed src="data/clipboard.swf" FlashVars="clipboard=' + escape(inElement.value) + '" width="0" height="0" type="application/x-shockwave-flash"></embed>'; 525 document.getElementById(flashcopier).innerHTML = divinfo; 526 } 527 } 528 </script> 529 </head> 530 <body onload='generateCanvas(80,24); generatePalette();' onkeydown='if(mode == 1) document.getElementById("textBuffer").focus();'> 531 <center> 532 <b>ASCII Maker</b> 533 <br><small><i>(<a href="https://github.com/ircart/asciimaker">source</a>)</i></small> 534 <br><br> 535 </center> 536 <div class='noDrag' id='canvas'></div> 537 <div class='noDrag' id='picker'></div> 538 <div id='preview'></div> 539 <div class='drafts' id='drafts'></div> 540 <p align='center'> 541 <button onclick='addDraft();'>Save</button> 542 <button onclick='loadArt();'>Load</button> 543 <button onclick='generateCanvas(canvasWidth, canvasHeight);'>Clear</button> 544 <button onclick='renderArt();'>Render</button> 545 <button onclick='copyArt();'>Copy</button> 546 <button onclick='toggleMode();' id='typeButton'>Type</button> 547 <button onclick='toggleTool();' id='toolButton'>Fill</button> 548 <button onclick='resizeArt();'>Resize</button> 549 <button onclick='loadLastUndo();' id='undoButton' DISABLED>Undo</button> 550 <br> 551 <textarea id='load' cols='30' rows='3' readonly></textarea><br /> 552 <input type='text' id='textBuffer' onkeydown='if(mode != 1) return false;' style='opacity: 0;'><br /> 553 </p> 554 </body> 555 </html>