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