asciiblaster- draw irc art in your web browser |
git clone git://git.acid.vegas/asciiblaster.git |
Log | Files | Refs | Archive | README |
clipboard.js (9809B)
1 var clipboard = (function () { 2 3 var exports = { 4 format: "irssi", 5 importing: false, 6 visible: false, 7 canvas: document.createElement("canvas"), 8 canvas_r: document.createElement("canvas"), 9 10 bind: function () { 11 // import_ascii.addEventListener("change", exports.setFormat("ascii")) 12 // import_irssi.addEventListener("change", exports.setFormat("irssi")) 13 // import_mirc.addEventListener("change", exports.setFormat("mirc")) 14 import_button.addEventListener("click", exports.import_colorcode) 15 export_button.addEventListener("click", exports.export_data) 16 save_button.addEventListener("click", exports.save_png) 17 upload_button.addEventListener("click", exports.upload_png) 18 import_textarea.addEventListener("focus", exports.focus) 19 import_textarea.addEventListener("blur", exports.blur) 20 import_textarea.addEventListener('paste', exports.paste) 21 // import_irssi.setAttribute("checked", true) 22 }, 23 setFormat: function (name) { 24 return function () { 25 clipboard.format = name 26 if (! clipboard.importing) { clipboard.export_data() } 27 } 28 }, 29 show: function () { import_rapper.style.display = "block"; clipboard.visible = true; changed = false }, 30 hide: function () { import_rapper.style.display = "none"; clipboard.visible = false }, 31 focus: function () { 32 if (! clipboard.importing) { 33 import_textarea.focus() 34 import_textarea.select() 35 } 36 }, 37 blur: function () { 38 }, 39 40 import_mode: function () { 41 focus() 42 clipboard.importing = true 43 gallery_rapper.style.display = 'none' 44 format_el.style.display = 'none' 45 cutoff_warning_el.style.display = 'none' 46 import_buttons.style.display = "inline" 47 import_textarea.value = "" 48 }, 49 export_mode: function () { 50 focus() 51 clipboard.importing = false 52 import_buttons.style.display = "none" 53 format_el.style.display = 'inline' 54 cutoff_warning_el.style.display = 'none' 55 gallery_rapper.style.display = 'inline' 56 clipboard.export_data() 57 }, 58 59 paste: function (e) { 60 e.preventDefault() 61 // images will come through as files 62 var types = toArray(e.clipboardData.types) 63 import_textarea.value = "" 64 types.forEach(function(type, i){ 65 console.log(type) 66 // this can be text/plain or text/html.. 67 if (type.match('text/plain')) { 68 import_textarea.value = e.clipboardData.getData(type) 69 } 70 else { 71 console.error("unknown type!", item.type) 72 } 73 }) 74 }, 75 76 import_colorcode: function (data, no_undo) { 77 if (data && data.preventDefault) { 78 data = import_textarea.value 79 } 80 else { 81 data = data || import_textarea.value 82 } 83 84 var irssi_style_regex = /^\s*\/exec -out printf ("%b" )?"/; 85 86 // turn irssi style into mirc style 87 if (data.match(irssi_style_regex)){ 88 data = data.replace(/\\x03/gm, '\x03') 89 .replace(/(\\x..)+/gm, unicode.unescapeFromEscapedBytes) 90 .replace(/\\x5C/g, '\\') 91 .replace(/\\n/gm, '\n') 92 .replace(/\\`/gm, '`') 93 .replace(/\\"/gm, '"') 94 .replace(/\\\$/gm, '$') 95 .replace(irssi_style_regex, '') 96 .replace(/"\s*$/, '') 97 } 98 99 // not a colorcode 100 if (!data.match(/\x03/)) 101 return exports.import_text(); 102 103 var json = colorcode.to_json(data, {fg:0, bg:1}) 104 105 if (!no_undo) undo.new() 106 if (!no_undo) undo.save_rect(0,0, canvas.w, canvas.h) 107 if (json.w !== canvas.w || json.h !== canvas.h){ 108 if (!no_undo) undo.save_size(canvas.w, canvas.h) 109 canvas.resize(json.w, json.h, true) 110 } 111 canvas.clear() 112 113 for (var y = 0, line; line = json.lines[y]; y++){ 114 var row = canvas.aa[y] 115 for (var x = 0, char; char = line[x]; x++){ 116 var lex = row[x] 117 lex.char = String.fromCharCode(char.value) 118 lex.fg = char.fg 119 lex.bg = char.bg 120 lex.opacity = 1 121 lex.build() 122 } 123 } 124 125 current_filetool && current_filetool.blur() 126 }, 127 128 import_text: function () { 129 var data = import_textarea.value 130 var lines = data.split("\n") 131 var width = lines.reduce(function(a,b){ console.log(a,b); return Math.max(a, b.length) }, 0) 132 var height = lines.length 133 if (width > canvas.max) { 134 return alert("input too wide") 135 } 136 if (height > canvas.max) { 137 return alert("input too tall") 138 } 139 undo.new() 140 undo.save_rect(0,0, canvas.w, canvas.h) 141 canvas.clear() 142 lines.forEach(function(line, y){ 143 var row = canvas.aa[y] 144 if (! row) return 145 for (var x = 0; x < line.length; x++) { 146 var lex = row[x] 147 if (! lex) return 148 lex.char = line[x] 149 lex.fg = brush.bg 150 lex.opacity = 1 151 lex.build() 152 } 153 }) 154 // TODO: some notion of a "selected" region which cuts/clones the underlying region 155 156 // var pasted_region = new Matrix (width, height, function(x,y){ 157 // var lex = new Lex (x,y) 158 // lex.char = lines[y][x] || " " 159 // lex.build() 160 // return lex 161 // }) 162 }, 163 export_data: function () { 164 var output 165 // switch (clipboard.format) { 166 switch (controls.save_format.value) { 167 case 'ascii': 168 output = canvas.ascii() 169 break 170 case 'mirc': 171 output = canvas.mirc({cutoff: 400}) 172 break 173 case 'irssi': 174 output = canvas.irssi({cutoff: 400}) 175 break 176 case 'ansi': 177 output = canvas.ansi() 178 break 179 } 180 if (output.cutoff){ 181 cutoff_warning_el.style.display = 'block' 182 } else { 183 cutoff_warning_el.style.display = 'none' 184 } 185 import_textarea.value = output 186 clipboard.focus() 187 return output 188 }, 189 190 rotate_canvas: function(){ 191 var cr = clipboard.canvas_r, c = clipboard.canvas 192 cr.width = c.height 193 cr.height = c.width 194 var ctx = cr.getContext('2d') 195 ctx.resetTransform() 196 ctx.translate(0, cr.height) 197 ctx.rotate(-Math.PI / 2) 198 ctx.drawImage(c, 0, 0) 199 return cr 200 }, 201 202 export_canvas: function (done_fn) { 203 var opts = { 204 palette: 'mirc', 205 font: canvas.pixels ? 'fixedsys_8x8' : 'fixedsys_8x15', 206 fg: 0, 207 bg: 1, 208 canvas: clipboard.canvas 209 } 210 opts.done = function(){ 211 var c = canvas.rotated ? clipboard.rotate_canvas() : clipboard.canvas 212 if (done_fn) done_fn(c) 213 } 214 215 var start = Date.now(); 216 colorcode.to_canvas(canvas.mirc(), opts) 217 var total = Date.now() - start; 218 console.log("took " + total) 219 }, 220 221 filename: function () { 222 return [ +new Date, "ascii", user.username ].join("-") 223 }, 224 225 save_png: function () { 226 var save_fn = function(canvas_out){ 227 var filename = clipboard.filename() + ".png" 228 var blob = PNG.canvas_to_blob_with_colorcode(canvas_out, canvas.mirc()) 229 saveAs(blob, filename); 230 } 231 clipboard.export_canvas(save_fn) 232 }, 233 234 upload_png: function () { 235 var upload_fn = function(canvas_out){ 236 var blob = PNG.canvas_to_blob_with_colorcode(canvas_out, canvas.mirc()) 237 var filename = clipboard.filename() 238 var tag = 'ascii' 239 upload(blob, filename, tag, canvas.mirc()) 240 } 241 clipboard.export_canvas(upload_fn) 242 } 243 244 } 245 246 // http...?a=1&b=2&b=3 -> {a: '1', b: ['2', '3']} 247 function parse_url_search_params(url){ 248 var params = {} 249 url = url.split('?') 250 if (url.length < 2) return params 251 252 var search = url[1].split('&') 253 for (var i = 0, pair; pair = search[i]; i++){ 254 pair = pair.split('=') 255 if (pair.length < 2) continue 256 var key = pair[0] 257 var val = pair[1] 258 if (key in params){ 259 if (typeof params[key] === 'string'){ 260 params[key] = [params[key], val] 261 } 262 else params[key].push(val) 263 } 264 else params[key] = val 265 } 266 return params 267 } 268 269 function get_filetype(txt){ 270 txt = txt.split('.') 271 return txt[txt.length - 1].toLowerCase() 272 } 273 274 function fetch_url(url, f, type){ 275 type = type || 'arraybuffer' 276 url = "/cgi-bin/proxy?" + url 277 //url = "http://198.199.72.134/cors/" + url 278 var xhr = new XMLHttpRequest() 279 xhr.open('GET', url, true) 280 xhr.responseType = type 281 xhr.addEventListener('load', function(){ f(xhr.response) }) 282 xhr.send() 283 } 284 285 function load_text(txt){ 286 clipboard.import_colorcode(txt, true) 287 } 288 289 function load_png(buf){ 290 var chunks = PNG.decode(buf) 291 if (!chunks) return 292 var itxt_chunks = [] 293 for (var i=0, c; c=chunks[i]; i++){ 294 if (c.type !== 'iTXt') continue 295 var itxt = PNG.decode_itxt_chunk(c) 296 if (!itxt.keyword || itxt.keyword !== 'colorcode') continue 297 clipboard.import_colorcode(itxt.data, true) 298 } 299 } 300 301 function sally_url_convert(url){ 302 var png_regex = /^https?:\/\/jollo\.org\/den\/sallies\/([0-9]+)\/([^.]+)\.png$/ 303 var matches = url.match(png_regex) 304 if (!matches) return url 305 return 'http://jollo.org/den/sallies/' + matches[1] + '/raw-' + matches[2] + '?.txt' 306 // txt suffix to force asdf proxy 307 } 308 309 exports.load_from_location = function(){ 310 var params = parse_url_search_params(window.location + '') 311 if (!params.url) return 312 var url = params.url 313 url = sally_url_convert(url) 314 var type = get_filetype(url) 315 switch (type){ 316 case 'txt': 317 fetch_url(url, load_text, 'text') 318 break 319 case 'png': 320 fetch_url(url, load_png) 321 break 322 } 323 324 } 325 326 return exports 327 328 })() 329 330