aboutsummaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
Diffstat (limited to 'static')
-rw-r--r--static/css/buri.css23
-rw-r--r--static/css/cyber.css39
-rw-r--r--static/css/dickgirl.css23
-rw-r--r--static/css/easymodo.css25
-rw-r--r--static/css/futaba.css22
-rw-r--r--static/css/guro.css24
-rw-r--r--static/css/ib.css72
-rw-r--r--static/css/img/0back.pngbin0 -> 148 bytes
-rw-r--r--static/css/img/0info.pngbin0 -> 284 bytes
-rw-r--r--static/css/img/0pc.pngbin0 -> 276 bytes
-rw-r--r--static/css/img/ba.gifbin0 -> 856 bytes
-rw-r--r--static/css/img/barra_dulce.pngbin0 -> 1266 bytes
-rw-r--r--static/css/img/bg_deportes.gifbin0 -> 3584 bytes
-rw-r--r--static/css/img/bg_madera.pngbin0 -> 4216 bytes
-rw-r--r--static/css/img/bg_oculto.gifbin0 -> 871 bytes
-rw-r--r--static/css/img/bgtb.gifbin0 -> 854 bytes
-rw-r--r--static/css/img/checked.pngbin0 -> 110 bytes
-rw-r--r--static/css/img/cyb.pngbin0 -> 4844 bytes
-rw-r--r--static/css/img/cyba.pngbin0 -> 201 bytes
-rw-r--r--static/css/img/fondo2012.gifbin0 -> 72620 bytes
-rw-r--r--static/css/img/green.gifbin0 -> 37408 bytes
-rw-r--r--static/css/img/hand.pngbin0 -> 213 bytes
-rw-r--r--static/css/img/luz.gifbin0 -> 3413 bytes
-rw-r--r--static/css/img/muro.jpgbin0 -> 37725 bytes
-rw-r--r--static/css/img/nieve.pngbin0 -> 2394 bytes
-rw-r--r--static/css/img/picnicbdy.gifbin0 -> 1049 bytes
-rw-r--r--static/css/img/picnicbg.gifbin0 -> 10945 bytes
-rw-r--r--static/css/img/picnicbtm.gifbin0 -> 3923 bytes
-rw-r--r--static/css/img/picnicbtn.gifbin0 -> 436 bytes
-rw-r--r--static/css/img/picnicfg.gifbin0 -> 1044 bytes
-rw-r--r--static/css/img/picnichr.gifbin0 -> 1368 bytes
-rw-r--r--static/css/img/picnicmid.gifbin0 -> 9502 bytes
-rw-r--r--static/css/img/picnicthr1.gifbin0 -> 12688 bytes
-rw-r--r--static/css/img/picnicthr2.gifbin0 -> 2946 bytes
-rw-r--r--static/css/img/picnicthr3.gifbin0 -> 12154 bytes
-rw-r--r--static/css/img/picnictop.gifbin0 -> 6939 bytes
-rw-r--r--static/css/img/scan.pngbin0 -> 182 bytes
-rw-r--r--static/css/img/scroller1.gifbin0 -> 3456 bytes
-rw-r--r--static/css/img/tanasinn.gifbin0 -> 1176 bytes
-rw-r--r--static/css/img/vndb1.jpgbin0 -> 36419 bytes
-rw-r--r--static/css/img/vndb2.jpgbin0 -> 4366 bytes
-rw-r--r--static/css/img/vndb3.pngbin0 -> 2791 bytes
-rw-r--r--static/css/kraut.css24
-rw-r--r--static/css/mobile.css129
-rw-r--r--static/css/night.css22
-rw-r--r--static/css/photon.css22
-rw-r--r--static/css/putaba.css46
-rw-r--r--static/css/red.css21
-rw-r--r--static/css/rene.css22
-rw-r--r--static/css/spc/base.css269
-rw-r--r--static/css/spc/halloween.css47
-rw-r--r--static/css/spc/layout.css58
-rw-r--r--static/css/spc/navidad.css161
-rw-r--r--static/css/spc/skeleton.css242
-rw-r--r--static/css/spc/valentin.css170
-rw-r--r--static/css/spc/valentin2.css177
-rw-r--r--static/css/txt/4am.css42
-rw-r--r--static/css/txt/amber.css44
-rw-r--r--static/css/txt/ayashii.css52
-rw-r--r--static/css/txt/baisano.css43
-rw-r--r--static/css/txt/bbs.css95
-rw-r--r--static/css/txt/bios.css51
-rw-r--r--static/css/txt/blue moon.css61
-rw-r--r--static/css/txt/ciber.css55
-rw-r--r--static/css/txt/futanari.css49
-rw-r--r--static/css/txt/headline.css41
-rw-r--r--static/css/txt/postal.css47
-rw-r--r--static/css/txt/sjis.css1
-rw-r--r--static/css/txt/ventanas.css48
-rw-r--r--static/css/vndb.css30
-rw-r--r--static/ico/1372836.gifbin0 -> 374 bytes
-rw-r--r--static/ico/1k.gifbin0 -> 101 bytes
-rw-r--r--static/ico/2-1.gifbin0 -> 1012 bytes
-rw-r--r--static/ico/2ppa.gifbin0 -> 285 bytes
-rw-r--r--static/ico/2syobo_2.gifbin0 -> 270 bytes
-rw-r--r--static/ico/3-2.gifbin0 -> 19802 bytes
-rw-r--r--static/ico/3.gifbin0 -> 1006 bytes
-rw-r--r--static/ico/3na.gifbin0 -> 324 bytes
-rw-r--r--static/ico/4-2.gifbin0 -> 1107 bytes
-rw-r--r--static/ico/4248688.gifbin0 -> 8947 bytes
-rw-r--r--static/ico/5007629.gifbin0 -> 14263 bytes
-rw-r--r--static/ico/5296219.gifbin0 -> 4028 bytes
-rw-r--r--static/ico/5ta.gifbin0 -> 364 bytes
-rw-r--r--static/ico/6396408.gifbin0 -> 8590 bytes
-rw-r--r--static/ico/6za.gifbin0 -> 395 bytes
-rw-r--r--static/ico/8028885.gifbin0 -> 41133 bytes
-rw-r--r--static/ico/8toushinnomonar16.gifbin0 -> 118 bytes
-rw-r--r--static/ico/8toushinnomonar32.gifbin0 -> 247 bytes
-rw-r--r--static/ico/ace.gifbin0 -> 317 bytes
-rw-r--r--static/ico/af1.gifbin0 -> 254 bytes
-rw-r--r--static/ico/af2.gifbin0 -> 228 bytes
-rw-r--r--static/ico/ahya_xmas_2.gifbin0 -> 227 bytes
-rw-r--r--static/ico/aka.gifbin0 -> 307 bytes
-rw-r--r--static/ico/ame.gifbin0 -> 224 bytes
-rw-r--r--static/ico/anime_buun02.gifbin0 -> 2036 bytes
-rw-r--r--static/ico/anime_charhan01.gifbin0 -> 2257 bytes
-rw-r--r--static/ico/anime_charhan02.gifbin0 -> 10274 bytes
-rw-r--r--static/ico/anime_giko01.gifbin0 -> 2183 bytes
-rw-r--r--static/ico/anime_giko04.gifbin0 -> 1516 bytes
-rw-r--r--static/ico/anime_giko10.gifbin0 -> 2250 bytes
-rw-r--r--static/ico/anime_giko11.gifbin0 -> 2291 bytes
-rw-r--r--static/ico/anime_giko12.gifbin0 -> 1760 bytes
-rw-r--r--static/ico/anime_giko13.gifbin0 -> 3135 bytes
-rw-r--r--static/ico/anime_hossyu01.gifbin0 -> 1300 bytes
-rw-r--r--static/ico/anime_imanouchi01.gifbin0 -> 1459 bytes
-rw-r--r--static/ico/anime_iyou02.gifbin0 -> 3351 bytes
-rw-r--r--static/ico/anime_jien01.gifbin0 -> 3345 bytes
-rw-r--r--static/ico/anime_jien02.gifbin0 -> 3403 bytes
-rw-r--r--static/ico/anime_jien03.gifbin0 -> 3231 bytes
-rw-r--r--static/ico/anime_jyorujyu01.gifbin0 -> 1431 bytes
-rw-r--r--static/ico/anime_jyorujyu02.gifbin0 -> 1441 bytes
-rw-r--r--static/ico/anime_jyorujyu03.gifbin0 -> 1450 bytes
-rw-r--r--static/ico/anime_kukkuru01.gifbin0 -> 1665 bytes
-rw-r--r--static/ico/anime_kuma01.gifbin0 -> 2099 bytes
-rw-r--r--static/ico/anime_kumaface01.gifbin0 -> 3924 bytes
-rw-r--r--static/ico/anime_loop.gifbin0 -> 20749 bytes
-rw-r--r--static/ico/anime_marara02.gifbin0 -> 1925 bytes
-rw-r--r--static/ico/anime_matanki01.gifbin0 -> 1392 bytes
-rw-r--r--static/ico/anime_matanki02.gifbin0 -> 4616 bytes
-rw-r--r--static/ico/anime_miruna01.gifbin0 -> 1567 bytes
-rw-r--r--static/ico/anime_monar02.gifbin0 -> 1594 bytes
-rw-r--r--static/ico/anime_monar03.gifbin0 -> 2564 bytes
-rw-r--r--static/ico/anime_monar05.gifbin0 -> 5846 bytes
-rw-r--r--static/ico/anime_morara01.gifbin0 -> 1576 bytes
-rw-r--r--static/ico/anime_morara02.gifbin0 -> 1734 bytes
-rw-r--r--static/ico/anime_morara04.gifbin0 -> 1634 bytes
-rw-r--r--static/ico/anime_nokar01.gifbin0 -> 2334 bytes
-rw-r--r--static/ico/anime_okashi01.gifbin0 -> 5999 bytes
-rw-r--r--static/ico/anime_okashi02.gifbin0 -> 4348 bytes
-rw-r--r--static/ico/anime_onigiri04.gifbin0 -> 8654 bytes
-rw-r--r--static/ico/anime_saitama01.gifbin0 -> 1440 bytes
-rw-r--r--static/ico/anime_saitama02.gifbin0 -> 1348 bytes
-rw-r--r--static/ico/anime_saitama03.gifbin0 -> 1454 bytes
-rw-r--r--static/ico/anime_sasuga01.gifbin0 -> 1546 bytes
-rw-r--r--static/ico/anime_sasuga03.gifbin0 -> 9729 bytes
-rw-r--r--static/ico/anime_sasuga04.gifbin0 -> 16392 bytes
-rw-r--r--static/ico/anime_shii01.gifbin0 -> 11664 bytes
-rw-r--r--static/ico/anime_shii02.gifbin0 -> 8324 bytes
-rw-r--r--static/ico/anime_shii03.gifbin0 -> 1506 bytes
-rw-r--r--static/ico/anime_syobon01.gifbin0 -> 2156 bytes
-rw-r--r--static/ico/anime_syobon03.gifbin0 -> 2361 bytes
-rw-r--r--static/ico/anime_tarn01.gifbin0 -> 3754 bytes
-rw-r--r--static/ico/anime_uwan01.gifbin0 -> 1966 bytes
-rw-r--r--static/ico/anime_uwan02.gifbin0 -> 1441 bytes
-rw-r--r--static/ico/anime_uwan03.gifbin0 -> 2216 bytes
-rw-r--r--static/ico/anime_youkanman01.gifbin0 -> 1915 bytes
-rw-r--r--static/ico/anime_youkanman02.gifbin0 -> 1882 bytes
-rw-r--r--static/ico/anime_youkanman03.gifbin0 -> 1365 bytes
-rw-r--r--static/ico/anime_zonu01.gifbin0 -> 1426 bytes
-rw-r--r--static/ico/anime_zonu02.gifbin0 -> 1476 bytes
-rw-r--r--static/ico/aramaki.gifbin0 -> 236 bytes
-rw-r--r--static/ico/aroeri-na32.gifbin0 -> 268 bytes
-rw-r--r--static/ico/asopasomaso.gifbin0 -> 247 bytes
-rw-r--r--static/ico/bikyakusan32.gifbin0 -> 213 bytes
-rw-r--r--static/ico/bs.gifbin0 -> 378 bytes
-rw-r--r--static/ico/button1_03.gifbin0 -> 218 bytes
-rw-r--r--static/ico/buun.gifbin0 -> 251 bytes
-rw-r--r--static/ico/chahan.gifbin0 -> 279 bytes
-rw-r--r--static/ico/dokuo1.gifbin0 -> 414 bytes
-rw-r--r--static/ico/file2_01.gifbin0 -> 282 bytes
-rw-r--r--static/ico/fujisan.gifbin0 -> 216 bytes
-rw-r--r--static/ico/fuun.gifbin0 -> 244 bytes
-rw-r--r--static/ico/gaku.gifbin0 -> 196 bytes
-rw-r--r--static/ico/gaku2.gifbin0 -> 252 bytes
-rw-r--r--static/ico/gaku3.gifbin0 -> 199 bytes
-rw-r--r--static/ico/gekisya1.gifbin0 -> 333 bytes
-rw-r--r--static/ico/giko1.gifbin0 -> 407 bytes
-rw-r--r--static/ico/gikog_gomibako.gifbin0 -> 233 bytes
-rw-r--r--static/ico/gikog_gyunyupack.gifbin0 -> 277 bytes
-rw-r--r--static/ico/gikog_pimiento.gifbin0 -> 279 bytes
-rw-r--r--static/ico/gikoinu.gifbin0 -> 252 bytes
-rw-r--r--static/ico/gikoneko.gifbin0 -> 997 bytes
-rw-r--r--static/ico/gikoneko2.gifbin0 -> 1021 bytes
-rw-r--r--static/ico/gikoneko_1.gifbin0 -> 200 bytes
-rw-r--r--static/ico/gocchin_face.gifbin0 -> 256 bytes
-rw-r--r--static/ico/gomiopen.gifbin0 -> 425 bytes
-rw-r--r--static/ico/goo_1.gifbin0 -> 209 bytes
-rw-r--r--static/ico/goo_3.gifbin0 -> 213 bytes
-rw-r--r--static/ico/gya-.gifbin0 -> 129 bytes
-rw-r--r--static/ico/hagenin-shuriken.gifbin0 -> 8609 bytes
-rw-r--r--static/ico/hagurumaou.gifbin0 -> 283 bytes
-rw-r--r--static/ico/hikky.gifbin0 -> 246 bytes
-rw-r--r--static/ico/hikky_xmas_2.gifbin0 -> 250 bytes
-rw-r--r--static/ico/hyou.gifbin0 -> 212 bytes
-rw-r--r--static/ico/iirasan_face.gifbin0 -> 283 bytes
-rw-r--r--static/ico/imanouchi_1.gifbin0 -> 232 bytes
-rw-r--r--static/ico/iyahoo.gifbin0 -> 1456 bytes
-rw-r--r--static/ico/iyou.gifbin0 -> 233 bytes
-rw-r--r--static/ico/jisakujien_2.gifbin0 -> 181 bytes
-rw-r--r--static/ico/jisakujien_xmas.gifbin0 -> 219 bytes
-rw-r--r--static/ico/kantoku1.gifbin0 -> 314 bytes
-rw-r--r--static/ico/kappappa1.gifbin0 -> 416 bytes
-rw-r--r--static/ico/kasa-ri.gifbin0 -> 196 bytes
-rw-r--r--static/ico/kashiwamo-chi32.gifbin0 -> 352 bytes
-rw-r--r--static/ico/kinokorusensei32.gifbin0 -> 337 bytes
-rw-r--r--static/ico/kita_.gifbin0 -> 260 bytes
-rw-r--r--static/ico/kodomona.gifbin0 -> 237 bytes
-rw-r--r--static/ico/konkon_folder.gifbin0 -> 373 bytes
-rw-r--r--static/ico/kossorisan.gifbin0 -> 99 bytes
-rw-r--r--static/ico/kotatu.gifbin0 -> 248 bytes
-rw-r--r--static/ico/kuma.gifbin0 -> 3875 bytes
-rw-r--r--static/ico/kuma2.gifbin0 -> 484 bytes
-rw-r--r--static/ico/maimai.gifbin0 -> 327 bytes
-rw-r--r--static/ico/makotan2_folder.gifbin0 -> 389 bytes
-rw-r--r--static/ico/mona.gifbin0 -> 254 bytes
-rw-r--r--static/ico/mona_shiri.gifbin0 -> 238 bytes
-rw-r--r--static/ico/mona_tya.gifbin0 -> 298 bytes
-rw-r--r--static/ico/monaazarashi_1.gifbin0 -> 168 bytes
-rw-r--r--static/ico/namaetukenai.gifbin0 -> 3331 bytes
-rw-r--r--static/ico/naoruyo.gifbin0 -> 257 bytes
-rw-r--r--static/ico/nida.gifbin0 -> 254 bytes
-rw-r--r--static/ico/nigete.gifbin0 -> 2304 bytes
-rw-r--r--static/ico/nono_ie.gifbin0 -> 365 bytes
-rw-r--r--static/ico/nurupo_ga_2.gifbin0 -> 1270 bytes
-rw-r--r--static/ico/onigiri_seito.gifbin0 -> 288 bytes
-rw-r--r--static/ico/otiketu48.gifbin0 -> 378 bytes
-rw-r--r--static/ico/pc3.gifbin0 -> 288 bytes
-rw-r--r--static/ico/pgya.gifbin0 -> 288 bytes
-rw-r--r--static/ico/sasuga1.gifbin0 -> 15680 bytes
-rw-r--r--static/ico/seito_2.gifbin0 -> 216 bytes
-rw-r--r--static/ico/soon.gifbin0 -> 245 bytes
-rw-r--r--static/ico/tasukete.gifbin0 -> 312 bytes
-rw-r--r--static/ico/torimasu1.gifbin0 -> 317 bytes
-rw-r--r--static/ico/torimasu2.gifbin0 -> 313 bytes
-rw-r--r--static/ico/u_ame.gifbin0 -> 3608 bytes
-rw-r--r--static/ico/u_hoshi.gifbin0 -> 3076 bytes
-rw-r--r--static/ico/u_naoruyo_bath.gifbin0 -> 4552 bytes
-rw-r--r--static/ico/u_okotowari_a.gifbin0 -> 6831 bytes
-rw-r--r--static/ico/u_sofa.gifbin0 -> 1280 bytes
-rw-r--r--static/ico/wakannai1.gifbin0 -> 304 bytes
-rw-r--r--static/ico/yakimochi.gifbin0 -> 242 bytes
-rw-r--r--static/ico/youkan.gifbin0 -> 254 bytes
-rw-r--r--static/ico/zonu_1.gifbin0 -> 179 bytes
-rw-r--r--static/ico/zuzagiko48.gifbin0 -> 368 bytes
-rw-r--r--static/img/anarkia.jpgbin0 -> 35677 bytes
-rw-r--r--static/img/bai.jpgbin0 -> 38030 bytes
-rw-r--r--static/img/cero.gifbin0 -> 80262 bytes
-rw-r--r--static/img/default.pngbin0 -> 9073 bytes
-rw-r--r--static/img/juegos1.jpgbin0 -> 43984 bytes
-rw-r--r--static/img/juegos2.jpgbin0 -> 35649 bytes
-rw-r--r--static/img/juegos3.pngbin0 -> 10301 bytes
-rw-r--r--static/img/juegos4.gifbin0 -> 24664 bytes
-rw-r--r--static/img/letras1.pngbin0 -> 52461 bytes
-rw-r--r--static/img/letras2.pngbin0 -> 69712 bytes
-rw-r--r--static/img/letras3.pngbin0 -> 97055 bytes
-rw-r--r--static/img/letras4.jpgbin0 -> 46084 bytes
-rw-r--r--static/img/letras5.jpgbin0 -> 50947 bytes
-rw-r--r--static/img/musica1.jpgbin0 -> 24487 bytes
-rw-r--r--static/img/noticias.pngbin0 -> 13249 bytes
-rw-r--r--static/img/old/2d_1.jpgbin0 -> 29384 bytes
-rw-r--r--static/img/old/2d_2.jpgbin0 -> 36070 bytes
-rw-r--r--static/img/old/2d_3.pngbin0 -> 5899 bytes
-rw-r--r--static/img/old/2d_4.jpgbin0 -> 29392 bytes
-rw-r--r--static/img/old/argentina1.pngbin0 -> 27794 bytes
-rw-r--r--static/img/old/chile1.pngbin0 -> 44923 bytes
-rw-r--r--static/img/old/chile2.jpgbin0 -> 44202 bytes
-rw-r--r--static/img/old/g0.jpgbin0 -> 39681 bytes
-rw-r--r--static/img/old/g1.jpgbin0 -> 45641 bytes
-rw-r--r--static/img/old/g2.jpgbin0 -> 38041 bytes
-rw-r--r--static/img/old/g3.jpgbin0 -> 52934 bytes
-rw-r--r--static/img/old/g4.jpgbin0 -> 36197 bytes
-rw-r--r--static/img/old/g5.jpgbin0 -> 23641 bytes
-rw-r--r--static/img/old/peli.jpgbin0 -> 36293 bytes
-rw-r--r--static/img/old/salon2d_3.jpgbin0 -> 35496 bytes
-rw-r--r--static/img/old/salon2d_4.pngbin0 -> 4978 bytes
-rw-r--r--static/img/old/salon2d_5.jpgbin0 -> 25550 bytes
-rw-r--r--static/img/old/zine.pngbin0 -> 75774 bytes
-rw-r--r--static/img/salon2d_1.pngbin0 -> 15409 bytes
-rw-r--r--static/img/salon2d_3.jpgbin0 -> 35496 bytes
-rw-r--r--static/img/salon2d_4.pngbin0 -> 4978 bytes
-rw-r--r--static/img/salon2d_5.jpgbin0 -> 25550 bytes
-rw-r--r--static/img/tech1.pngbin0 -> 7802 bytes
-rw-r--r--static/img/tech2.jpgbin0 -> 36871 bytes
-rw-r--r--static/img/tech3.pngbin0 -> 42940 bytes
-rw-r--r--static/img/tech4.jpgbin0 -> 48759 bytes
-rw-r--r--static/img/tech5.jpgbin0 -> 37524 bytes
-rw-r--r--static/img/tech6.pngbin0 -> 17938 bytes
-rw-r--r--static/img/tv1.pngbin0 -> 3501 bytes
-rw-r--r--static/img/weird-al.jpgbin0 -> 14523 bytes
-rw-r--r--static/img/world.gifbin0 -> 100563 bytes
-rw-r--r--static/img/zonavip1.jpgbin0 -> 45584 bytes
-rw-r--r--static/img/zonavip2.gifbin0 -> 38269 bytes
-rw-r--r--static/img/zonavip3.pngbin0 -> 85601 bytes
-rw-r--r--static/img/zonavip4.jpgbin0 -> 41923 bytes
-rw-r--r--static/img/zonavip5.gifbin0 -> 35591 bytes
-rw-r--r--static/img/zonavip6.pngbin0 -> 13149 bytes
-rw-r--r--static/img/zonavip7.gifbin0 -> 50028 bytes
-rw-r--r--static/img/zonavip8.pngbin0 -> 53463 bytes
-rw-r--r--static/img/zonavip9.gifbin0 -> 19603 bytes
-rw-r--r--static/img/zonavip9.jpgbin0 -> 46773 bytes
-rw-r--r--static/img/zonavip_halloween.jpgbin0 -> 38379 bytes
-rw-r--r--static/img/zonavip_nav.jpgbin0 -> 51171 bytes
-rw-r--r--static/js/aquiencitas.js168
-rw-r--r--static/js/autorefresh.js275
-rw-r--r--static/js/home.js173
-rw-r--r--static/js/jquery.js545
-rw-r--r--static/js/manage.js22
-rw-r--r--static/js/mobile.js447
-rw-r--r--static/js/paintbbs/PaintBBS-1.1.11.css535
-rw-r--r--static/js/paintbbs/PaintBBS-1.1.11.js5686
-rw-r--r--static/js/paintbbs/PaintBBS-1.3.4.css547
-rw-r--r--static/js/paintbbs/PaintBBS-1.3.4.js6171
-rwxr-xr-xstatic/js/palette_selfy.js972
-rw-r--r--static/js/shobon.js408
-rw-r--r--static/js/tegaki/tegaki.css187
-rw-r--r--static/js/tegaki/tegaki.js1947
-rw-r--r--static/js/weabot.js456
-rw-r--r--static/js/weabotxt.js299
-rw-r--r--static/js/wpaint/.gitignore3
-rw-r--r--static/js/wpaint/README.md421
-rw-r--r--static/js/wpaint/bai.js23
-rw-r--r--static/js/wpaint/demo/demo.css266
-rw-r--r--static/js/wpaint/demo/img/facebook-icon.pngbin0 -> 274 bytes
-rw-r--r--static/js/wpaint/demo/img/favicon.icobin0 -> 1150 bytes
-rw-r--r--static/js/wpaint/demo/img/forkme_right_darkblue.pngbin0 -> 7791 bytes
-rw-r--r--static/js/wpaint/demo/img/github-icon.pngbin0 -> 596 bytes
-rw-r--r--static/js/wpaint/demo/img/googleplus-icon.pngbin0 -> 522 bytes
-rw-r--r--static/js/wpaint/demo/img/linkedin-icon.pngbin0 -> 380 bytes
-rw-r--r--static/js/wpaint/demo/img/rss-icon.pngbin0 -> 521 bytes
-rw-r--r--static/js/wpaint/demo/img/stumbleupon-icon.pngbin0 -> 537 bytes
-rw-r--r--static/js/wpaint/demo/img/twitter-icon.pngbin0 -> 514 bytes
-rw-r--r--static/js/wpaint/demo/img/websanova-logo-small-full-black.pngbin0 -> 1028 bytes
-rw-r--r--static/js/wpaint/demo/img/youtube-icon.pngbin0 -> 587 bytes
-rw-r--r--static/js/wpaint/gruntfile.js90
-rw-r--r--static/js/wpaint/index.html136
-rw-r--r--static/js/wpaint/lib/jquery.1.10.2.min.js6
-rw-r--r--static/js/wpaint/lib/jquery.ui.core.1.10.3.min.js4
-rw-r--r--static/js/wpaint/lib/jquery.ui.draggable.1.10.3.min.js4
-rw-r--r--static/js/wpaint/lib/jquery.ui.mouse.1.10.3.min.js4
-rw-r--r--static/js/wpaint/lib/jquery.ui.widget.1.10.3.min.js4
-rw-r--r--static/js/wpaint/lib/mixins.styl7
-rw-r--r--static/js/wpaint/lib/wColorPicker.min.css42
-rw-r--r--static/js/wpaint/lib/wColorPicker.min.js2
-rw-r--r--static/js/wpaint/package.json25
-rw-r--r--static/js/wpaint/plugins/file/img/icons-menu-main-file.pngbin0 -> 835 bytes
-rw-r--r--static/js/wpaint/plugins/file/src/wPaint.menu.main.file.js75
-rw-r--r--static/js/wpaint/plugins/file/wPaint.menu.main.file.min.js1
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-bucket.pngbin0 -> 450 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-crosshair.pngbin0 -> 208 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-dropper.pngbin0 -> 403 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser1.pngbin0 -> 193 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser10.pngbin0 -> 247 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser2.pngbin0 -> 200 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser3.pngbin0 -> 206 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser4.pngbin0 -> 209 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser5.pngbin0 -> 225 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser6.pngbin0 -> 229 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser7.pngbin0 -> 236 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser8.pngbin0 -> 240 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-eraser9.pngbin0 -> 244 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/cursor-pencil.pngbin0 -> 449 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/icon-group-arrow.pngbin0 -> 208 bytes
-rw-r--r--static/js/wpaint/plugins/main/img/icons-menu-main.pngbin0 -> 2836 bytes
-rw-r--r--static/js/wpaint/plugins/main/src/fillArea.min.js1
-rw-r--r--static/js/wpaint/plugins/main/src/wPaint.menu.main.js338
-rw-r--r--static/js/wpaint/plugins/main/wPaint.menu.main.min.js1
-rw-r--r--static/js/wpaint/plugins/shapes/img/icons-menu-main-shapes.pngbin0 -> 903 bytes
-rw-r--r--static/js/wpaint/plugins/shapes/src/shapes.min.js1
-rw-r--r--static/js/wpaint/plugins/shapes/src/wPaint.menu.main.shapes.js207
-rw-r--r--static/js/wpaint/plugins/shapes/wPaint.menu.main.shapes.min.js1
-rw-r--r--static/js/wpaint/plugins/text/img/icons-menu-text.pngbin0 -> 802 bytes
-rw-r--r--static/js/wpaint/plugins/text/src/wPaint.menu.text.js227
-rw-r--r--static/js/wpaint/plugins/text/wPaint.menu.text.min.js1
-rw-r--r--static/js/wpaint/src/wPaint.css348
-rw-r--r--static/js/wpaint/src/wPaint.js1181
-rw-r--r--static/js/wpaint/src/wPaint.utils.js70
-rw-r--r--static/js/wpaint/test/dev.html123
-rw-r--r--static/js/wpaint/test/fullscreen.html79
-rw-r--r--static/js/wpaint/test/upload.php11
-rw-r--r--static/js/wpaint/test/uploads/test1.pngbin0 -> 432 bytes
-rw-r--r--static/js/wpaint/test/uploads/test2.pngbin0 -> 462 bytes
-rw-r--r--static/js/wpaint/test/uploads/test3.pngbin0 -> 454 bytes
-rw-r--r--static/js/wpaint/test/uploads/wPaint.pngbin0 -> 3096 bytes
-rw-r--r--static/js/wpaint/wPaint.jquery.json38
-rw-r--r--static/js/wpaint/wPaint.min.css66
-rw-r--r--static/js/wpaint/wPaint.min.js1
-rw-r--r--static/meta/bbs.pngbin0 -> 7192 bytes
-rw-r--r--static/meta/faq_1.pngbin0 -> 18358 bytes
-rw-r--r--static/meta/faq_2.pngbin0 -> 12504 bytes
-rw-r--r--static/meta/faq_3.pngbin0 -> 19818 bytes
-rw-r--r--static/meta/ib.pngbin0 -> 10709 bytes
-rw-r--r--static/meta/portada_6.jpgbin0 -> 368440 bytes
-rw-r--r--static/meta/portada_7.jpgbin0 -> 51433 bytes
-rw-r--r--static/meta/portada_8.jpgbin0 -> 266858 bytes
-rw-r--r--static/meta/portada_asp.gifbin0 -> 441933 bytes
-rw-r--r--static/meta/portada_cap1.jpgbin0 -> 101119 bytes
-rw-r--r--static/meta/portada_orig5.jpgbin0 -> 67175 bytes
-rw-r--r--static/meta/portada_toesca.jpgbin0 -> 35123 bytes
-rw-r--r--static/meta/portadaphil.jpgbin0 -> 102067 bytes
-rw-r--r--static/meta/primeraportada.pngbin0 -> 385869 bytes
-rw-r--r--static/meta/sanvalentin2013.jpgbin0 -> 98509 bytes
-rw-r--r--static/meta/welcome.gifbin0 -> 238888 bytes
-rw-r--r--static/meta/welcome.jpgbin0 -> 28985 bytes
-rw-r--r--static/mime/epub.pngbin0 -> 1320 bytes
-rw-r--r--static/mime/epub_small.pngbin0 -> 1019 bytes
-rw-r--r--static/mime/mod.pngbin0 -> 1362 bytes
-rw-r--r--static/mime/mod_small.pngbin0 -> 1058 bytes
-rw-r--r--static/mime/pdf.pngbin0 -> 1264 bytes
-rw-r--r--static/mime/pdf_small.pngbin0 -> 984 bytes
-rw-r--r--static/mime/s3m.pngbin0 -> 1397 bytes
-rw-r--r--static/mime/s3m_small.pngbin0 -> 1104 bytes
-rw-r--r--static/mime/swf.pngbin0 -> 1375 bytes
-rw-r--r--static/mime/swf_small.pngbin0 -> 1067 bytes
-rw-r--r--static/mime/torrent.pngbin0 -> 1377 bytes
-rw-r--r--static/mime/torrent_small.pngbin0 -> 1070 bytes
-rw-r--r--static/mime/xm.pngbin0 -> 1318 bytes
-rw-r--r--static/mime/xm_small.pngbin0 -> 1011 bytes
407 files changed, 24942 insertions, 0 deletions
diff --git a/static/css/buri.css b/static/css/buri.css
new file mode 100644
index 0000000..b8c1eb5
--- /dev/null
+++ b/static/css/buri.css
@@ -0,0 +1,23 @@
+html,body{background:#EEF2FF;color:#000;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif}
+a,a .name,a .name b,.nav label:hover{color:#34345C}
+a.rep{color:#000;text-decoration:underline}
+a:visited{color:#34345C}
+a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#DD0000}
+.replymode,.extramode{color:#FFF}
+.replymode{background:#0010E0}
+.extramode{background:#0040E0}
+.postblock{background:#9988EE;color:#000}
+.q{color:#789922}
+.fs{text-decoration:none}
+.subj{color:#0F0C5D;font-weight:bold}
+.name{color:#228854}
+.name b{color:#117743}
+.reply,#q-p{background:#D6DAF0;color:#000}
+.omitted,.abbrev{color:#707070}
+.highlight{background:#c1c6e2}
+.managertable td{background:#9AD2F6;color:#000}
+.managertable th{background:#0F8FE1;color:#000}
+#catalog .thread:hover{background:#D6DAF0;box-shadow:0 0 5px 5px #D6DAF0}
+#catalog .replies{color:#555555;font-weight:bold}
+.yt{background:#E3E6F5;border:1px solid #C1C6E7}
+.quoted{border-color:#EEF2FF;color:#707070} \ No newline at end of file
diff --git a/static/css/cyber.css b/static/css/cyber.css
new file mode 100644
index 0000000..e9732bc
--- /dev/null
+++ b/static/css/cyber.css
@@ -0,0 +1,39 @@
+html,body{background:#000 url('img/cyb.png');color:#61CE3C;font-family:monospace}
+a,a .name,a .name b,.nav label{color:#C80B63}
+.reflink a,.rep,.hsbn,#main_nav a{color:#FFF}
+a:hover,a:hover .name,a:hover .name b,.nav label:hover,#main_nav a:hover{color:#F00}
+.reflink a:hover{text-decoration:underline}
+hr{display:none}
+.thread hr{border:0;border-top:1px solid #61CE3C;display:block}
+input,input[type="text"],input[type="password"],textarea{background:#1A1A1A;border:0;color:#61CE3C}
+input[type="submit"]{border:1px outset #999}
+input[type="submit"]:active{border-style:inset}
+#main_nav{background:#1A1A1A;border-bottom:double 3px #989898;color:#989898;margin:-10px -10px 0;padding:10px}
+.logo{color:#C00}
+.replymode,.extramode{color:#FFF;text-shadow:1px 1px #000}
+.replymode{background:#C00;box-shadow:5px 5px #989898;margin-bottom:1em}
+.extramode{background:#001eff;}
+.postform,.oekform{background:#2b2b2b;border:1px solid #989898;box-shadow:5px 5px #989898;padding:1px}
+.postblock{background:#2e8b57;color:#FFF}
+.q{color:#93e0e3}
+.quoted{color:#707070}
+.fs,.info{color:#989898;text-decoration:none}
+.subj{color:#7b68ee;font-weight:bold}
+.name{color:#FBDE2D}
+.name b{color:#989898}
+.omitted,.abbrev{color:#428C29}
+.thread{border:solid 1px #7b68ee;background:#1A1A1A;box-shadow:5px 5px #7b68ee;margin-top:1em;margin-bottom:1em;padding:5px}
+.reply,#q-p{background:#2b2b2b;border:1px solid #2e8b57 !important;box-shadow:5px 5px #2e8b57}
+.thread table{margin:0;margin-bottom:10px;margin-right:10px}
+.thumb{border:1px solid #4D4D4D;box-shadow:3px 3px #4D4D4D;margin-bottom:5px}
+.reply.highlight{border-color:#93e0e3 !important;box-shadow:5px 5px #93e0e3}
+.pg,.userdelete,.nav{background:#2b2b2b;border:1px solid #2e8b57;box-shadow:5px 5px #2e8b57;color:#89A}
+.nav{padding:4px}
+#adminmenu table{margin-bottom:10px}
+.managertable td{background:#2B2B2B;color:#FFF}
+.managertable th{background:#1A1A1A;color:#FFF}
+#catalog .thread{border:1px solid #61CE3C;border-radius:0;box-shadow:none}
+#catalog .thread:hover{background:#383838}
+#catalog .replies{color:#428C29;font-weight:bold}
+.yt{background:#222;border:1px solid;box-shadow:2px 2px}
+.quoted{border-color:#2e8b57;color:#989898} \ No newline at end of file
diff --git a/static/css/dickgirl.css b/static/css/dickgirl.css
new file mode 100644
index 0000000..ba0bcc4
--- /dev/null
+++ b/static/css/dickgirl.css
@@ -0,0 +1,23 @@
+html,body{background:#1B3345;color:#FFF;font-family:initial}
+a,a .name,.nav label{color:#EFD279}
+a.rep{color:#FFF}
+a:hover,a:hover .name,.nav label:hover{color:#D00}
+.logo{color:#CCFFCC}
+.replymode,.extramode{color:#FFF}
+.replymode{background:#1D7548}
+.extramode{background:#0040E0}
+.postblock{background:#95CBE9;color:#2C5700}
+.q{color:#BDF46C}
+.fs{text-decoration:none}
+.subj{color:#DE9D7F;font-weight:bold}
+.name{color:#AFD775}
+.omitted{color:#909090}
+.reply,#q-p{background:#3B6B94;color:#fff}
+.abbrev{color:#BBB}
+.highlight{background:#5B8BB4}
+.managertable td{background:#3B6B94;color:#FFF}
+.managertable th{background:#AAF;color:#FFF}
+#catalog .thread:hover{background:#3B6B94;box-shadow:0 0 5px 5px #3B6B94}
+#catalog .replies{color:#AAA;font-weight:bold}
+.yt{background:#2F587A;border:1px solid #1B2933}
+.quoted{border-color:#1B3345} \ No newline at end of file
diff --git a/static/css/easymodo.css b/static/css/easymodo.css
new file mode 100644
index 0000000..eaa88a8
--- /dev/null
+++ b/static/css/easymodo.css
@@ -0,0 +1,25 @@
+html,body{background:#EEFFF2;color:#000;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif}
+.rep{color:#000}
+a,a .name,a .name b,.nav label{color:#34345c}
+a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#D00}
+.reflink a:hover{text-decoration:underline}
+.replymode,.extramode{color:#FFF}
+.replymode{background:#E04000}
+.extramode{background:#0040E0}
+.postform,.oekform{background:#cce1cf;border:1px solid #CCE1CF;padding:1px}
+.postblock{background:#98c1a9}
+.q{color:#789922}
+.quoted{color:#707070}
+.fs{text-decoration:none}
+.subj{color:#0f0c5d;font-weight:bold}
+.name{color:#228854}
+.name b{color:#117743}
+.omitted,.abbrev{color:#707070}
+.reply,#q-p,.pg{background:#d6f0da}
+.highlight{background:#d6bad0}
+.managertable td{background:#cce1cf}
+.managertable th{background:#b8caba}
+#catalog .thread:hover{background:#d6f0da;box-shadow:0 0 5px 5px #d6f0da}
+#catalog .replies{color:#707070;font-weight:bold}
+.yt{background:#c2d6c5;border:1px solid #7a877c;color:#000}
+.quoted{border-color:#EEFFF2} \ No newline at end of file
diff --git a/static/css/futaba.css b/static/css/futaba.css
new file mode 100644
index 0000000..f90af88
--- /dev/null
+++ b/static/css/futaba.css
@@ -0,0 +1,22 @@
+html,body{background:#FFE;color:#800000;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif}
+a,a .name,a .name b,.nav label{color:#0000EE}
+a.rep{color:#800000;text-decoration:underline}
+a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#D00}
+.replymode,.extramode{color:#FFF}
+.replymode{background:#E04000}
+.extramode{background:#0040E0}
+.postblock{background:#EEAA88}
+.q{color:#789922}
+.subj{color:#CC1105;font-weight:bold}
+.name{color:#228854}
+.name b{color:#117743}
+.omitted{color:#707070}
+.reply,#q-p{background:#F0E0D6}
+.abbrev{color:#707070}
+.highlight{background:#F0C0B0}
+.managertable td{background:#EEEECC;color:#800000}
+.managertable th{background:#AAAA66;color:#400000}
+#catalog .thread:hover{background:#F0E0D6;box-shadow:0 0 5px 5px #F0E0D6}
+#catalog .replies{color:#909090;font-weight:bold}
+.yt{background:#F2E5DD;border:1px solid #E7CFC1;color:#500000}
+.quoted{border-color:#FFE} \ No newline at end of file
diff --git a/static/css/guro.css b/static/css/guro.css
new file mode 100644
index 0000000..c938675
--- /dev/null
+++ b/static/css/guro.css
@@ -0,0 +1,24 @@
+html,body{background:#eddad2;color:#000;font-family:arial,helvetica,"nimbus sans l",sans-serif}
+.rep{color:#000}
+a,a .name,a .name b,.nav label{color:#af0a0f}
+a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#d00}
+.logo{color:#af0a0f}
+.replymode,.extramode{background:#57463f;color:#fff}
+.postblock,.reply{background:#d9af9e;border:1px solid #ca927b}
+input,input[type="text"],input[type="password"],textarea{background:#e6cbc0;border:1px solid #ca927b}
+input[type="submit"],input[type="button"]{border-style:outset;padding:3px 10px}
+input[type="submit"]:active,input[type="button"]:active{border-style:inset}
+.q{color:#707070}
+.subj{color:#0f0c5d;font-weight:bold}
+.name{color:#117743}
+.name b{color:#228854}
+.omitted,.abbrev{color:#444}
+#q-p{background:#d9af9e;border:0}
+.highlight{background:#5b5f69}
+.managertable td{background:#e6cbc0}
+.managertable th{background:#d9af9e}
+hr{border:none;border-top:1px solid #d9af9e;height:0}
+#catalog .thread:hover{background:#d9af9e;box-shadow:0 0 5px 5px #d9af9e}
+#catalog .replies{color:#555;font-weight:bold}
+.yt{background:#c39e8e;border:1px solid #8d6656}
+.quoted{border-color:#ca927b} \ No newline at end of file
diff --git a/static/css/ib.css b/static/css/ib.css
new file mode 100644
index 0000000..1609e4d
--- /dev/null
+++ b/static/css/ib.css
@@ -0,0 +1,72 @@
+*{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;word-wrap:break-word}
+html,body{font-family:arial,helvetica,"nimbus sans l",sans-serif}
+html{margin:0;padding:0}
+body{margin:0;padding:10px;font-size:16px}
+blockquote{line-height:20px}
+.spoil{background:#000;color:#000}.spoil:hover{color:#fff}
+.postarea table{margin:0 auto;text-align:left}
+#main_nav{font-size:14px;line-height:1.3em;margin-bottom:.5em;text-align:center}
+#main_nav span{display:inline-block}
+#main_nav #sel,#main_nav .cur_brd,#main_nav #cur_stl{font-weight:bold}
+.logo{font-size:160%;font-weight:bold;margin:8px 0;text-align:center}
+input[type="text"],input[type="password"],textarea{background:#FFF;border:1px inset gray;padding:3px}
+.postform input{max-width:250px}
+.postform input[name="subject"]{max-width:300px}
+.postform textarea{width:400px;height:125px}
+.postblock{font-weight:bold;padding:3px}
+.oekform{display:inline-block;margin-bottom:.5em}
+.rules{width:468px;font-size:13px}
+.rules ul{margin:4px 0 0;padding:0}
+.rules li{margin-left:1em}
+.thread{margin-right:170px}
+.thread table{border-collapse:collapse;margin:4px 0}
+.reply .info{padding-right:50px}
+.hsbn{font-size:120%}
+.thumb{border:none;float:left;margin:0 20px}
+.ell{font-family:Mona,IPAMonaPGothic,Monapo,'MS PGothic',YOzFontAA97;vertical-align:top;width:20px}
+.deleted{color:#777}
+.reflink a{color:inherit;text-decoration:none}
+.reply .fs,#q-p .fs{margin-left:20px}
+.pg{border:1px solid;border-spacing:2px;display:table}
+.pg span{border:1px inset;display:table-cell}
+.pg span input{padding:.4em 1em}
+.replymode,.extramode{font-weight:bold;text-align:center;padding:2px;margin:3px 0}
+.name em{color:#009;font-style:normal}
+.quoted{border-top:1px solid;clear:both;font-size:12px;line-height:1;margin:0 -1px;padding:4px}
+.thumbpreview{display:inline-block;max-height:50px;height:auto;max-width:75px;width:auto;vertical-align:middle}
+#catalog{text-align:center}
+#cat_search{border:1px inset gray;padding:0;width:125px}
+#catalog .thread{border-radius:4px;display:inline-block;font-size:14px;margin:5px;overflow:hidden;padding:2px;position:relative;vertical-align:top;max-height:275px;width:175px}
+#catalog.enlarged .thread{margin:10px 5px;max-height:375px;width:275px}
+#catalog .thread a img{border-radius:3px;margin-bottom:2px}
+#catalog.enlarged .thread a img{min-width:150px;min-height:150px;max-width:250px;max-height:250px}
+#catalog .subj{font-size:16px}
+#catalog p{margin:0}
+.yt{font-size:12px;display:inline-block;line-height:13px;margin:2px 0;padding:5px;text-decoration:none}
+.yt b{font-size:14px}
+.yt .pvw{width:100px;height:60px;overflow:hidden;float:left;margin-right:5px}
+.yt .pvw img{margin-top:-15px;margin-left:-10px}
+.cut{clear:both}
+.nav label{text-decoration:underline}
+.userdel{float:right;text-align:center;white-space:nowrap}
+.footer{clear:both;margin-top:8px;text-align:center}
+.managertable th,.managertable td{padding:3px}
+#q-p{position:absolute;border:1px dotted gray}
+@media(max-width:900px){.thread{margin-right:0}}
+@media(max-width:720px){
+ body{font-size:15px;padding:4px}
+ .postblock{font-size:14px;white-space:nowrap}
+ .pass,.ell,.thumbmsg{display:none}
+ .thread table,#postform input[type="text"],#postform input[type="submit"],#postform textarea,#postform input[type="file"],.rules{max-width:100%;width:100%}
+ .info,.fs .tt,.omitted{font-size:14px}
+ .date{font-size:13px}
+ .reply .info{padding-right:0}
+ .fs,.rules{font-size:12px}
+ .fs span{display:none}
+ .reply .fs{margin-left:4px}
+ .thumb{margin:0 8px 0 4px;max-width:100px;max-height:100px;width:auto;height:auto}
+ blockquote{margin:8px!important}
+ .userdel{float:none}
+ .pg{margin-top:0.5em;text-align:center;width:100%}
+ .pg span,.pg input{display:block;width:100%}
+} \ No newline at end of file
diff --git a/static/css/img/0back.png b/static/css/img/0back.png
new file mode 100644
index 0000000..231a44d
--- /dev/null
+++ b/static/css/img/0back.png
Binary files differ
diff --git a/static/css/img/0info.png b/static/css/img/0info.png
new file mode 100644
index 0000000..31ce6be
--- /dev/null
+++ b/static/css/img/0info.png
Binary files differ
diff --git a/static/css/img/0pc.png b/static/css/img/0pc.png
new file mode 100644
index 0000000..f894f66
--- /dev/null
+++ b/static/css/img/0pc.png
Binary files differ
diff --git a/static/css/img/ba.gif b/static/css/img/ba.gif
new file mode 100644
index 0000000..fa1d375
--- /dev/null
+++ b/static/css/img/ba.gif
Binary files differ
diff --git a/static/css/img/barra_dulce.png b/static/css/img/barra_dulce.png
new file mode 100644
index 0000000..c872a7e
--- /dev/null
+++ b/static/css/img/barra_dulce.png
Binary files differ
diff --git a/static/css/img/bg_deportes.gif b/static/css/img/bg_deportes.gif
new file mode 100644
index 0000000..1d107e5
--- /dev/null
+++ b/static/css/img/bg_deportes.gif
Binary files differ
diff --git a/static/css/img/bg_madera.png b/static/css/img/bg_madera.png
new file mode 100644
index 0000000..1e98769
--- /dev/null
+++ b/static/css/img/bg_madera.png
Binary files differ
diff --git a/static/css/img/bg_oculto.gif b/static/css/img/bg_oculto.gif
new file mode 100644
index 0000000..65a3744
--- /dev/null
+++ b/static/css/img/bg_oculto.gif
Binary files differ
diff --git a/static/css/img/bgtb.gif b/static/css/img/bgtb.gif
new file mode 100644
index 0000000..c9f675c
--- /dev/null
+++ b/static/css/img/bgtb.gif
Binary files differ
diff --git a/static/css/img/checked.png b/static/css/img/checked.png
new file mode 100644
index 0000000..67332b0
--- /dev/null
+++ b/static/css/img/checked.png
Binary files differ
diff --git a/static/css/img/cyb.png b/static/css/img/cyb.png
new file mode 100644
index 0000000..a75a55f
--- /dev/null
+++ b/static/css/img/cyb.png
Binary files differ
diff --git a/static/css/img/cyba.png b/static/css/img/cyba.png
new file mode 100644
index 0000000..c79e9b2
--- /dev/null
+++ b/static/css/img/cyba.png
Binary files differ
diff --git a/static/css/img/fondo2012.gif b/static/css/img/fondo2012.gif
new file mode 100644
index 0000000..d31e6a3
--- /dev/null
+++ b/static/css/img/fondo2012.gif
Binary files differ
diff --git a/static/css/img/green.gif b/static/css/img/green.gif
new file mode 100644
index 0000000..9d4963c
--- /dev/null
+++ b/static/css/img/green.gif
Binary files differ
diff --git a/static/css/img/hand.png b/static/css/img/hand.png
new file mode 100644
index 0000000..291411c
--- /dev/null
+++ b/static/css/img/hand.png
Binary files differ
diff --git a/static/css/img/luz.gif b/static/css/img/luz.gif
new file mode 100644
index 0000000..f8667cf
--- /dev/null
+++ b/static/css/img/luz.gif
Binary files differ
diff --git a/static/css/img/muro.jpg b/static/css/img/muro.jpg
new file mode 100644
index 0000000..54dd86b
--- /dev/null
+++ b/static/css/img/muro.jpg
Binary files differ
diff --git a/static/css/img/nieve.png b/static/css/img/nieve.png
new file mode 100644
index 0000000..ba8fc25
--- /dev/null
+++ b/static/css/img/nieve.png
Binary files differ
diff --git a/static/css/img/picnicbdy.gif b/static/css/img/picnicbdy.gif
new file mode 100644
index 0000000..f0c30bc
--- /dev/null
+++ b/static/css/img/picnicbdy.gif
Binary files differ
diff --git a/static/css/img/picnicbg.gif b/static/css/img/picnicbg.gif
new file mode 100644
index 0000000..4c6aa64
--- /dev/null
+++ b/static/css/img/picnicbg.gif
Binary files differ
diff --git a/static/css/img/picnicbtm.gif b/static/css/img/picnicbtm.gif
new file mode 100644
index 0000000..a380890
--- /dev/null
+++ b/static/css/img/picnicbtm.gif
Binary files differ
diff --git a/static/css/img/picnicbtn.gif b/static/css/img/picnicbtn.gif
new file mode 100644
index 0000000..b7fd7fe
--- /dev/null
+++ b/static/css/img/picnicbtn.gif
Binary files differ
diff --git a/static/css/img/picnicfg.gif b/static/css/img/picnicfg.gif
new file mode 100644
index 0000000..435ab0f
--- /dev/null
+++ b/static/css/img/picnicfg.gif
Binary files differ
diff --git a/static/css/img/picnichr.gif b/static/css/img/picnichr.gif
new file mode 100644
index 0000000..b50ccb1
--- /dev/null
+++ b/static/css/img/picnichr.gif
Binary files differ
diff --git a/static/css/img/picnicmid.gif b/static/css/img/picnicmid.gif
new file mode 100644
index 0000000..de2beb4
--- /dev/null
+++ b/static/css/img/picnicmid.gif
Binary files differ
diff --git a/static/css/img/picnicthr1.gif b/static/css/img/picnicthr1.gif
new file mode 100644
index 0000000..c9a967f
--- /dev/null
+++ b/static/css/img/picnicthr1.gif
Binary files differ
diff --git a/static/css/img/picnicthr2.gif b/static/css/img/picnicthr2.gif
new file mode 100644
index 0000000..cbe13fb
--- /dev/null
+++ b/static/css/img/picnicthr2.gif
Binary files differ
diff --git a/static/css/img/picnicthr3.gif b/static/css/img/picnicthr3.gif
new file mode 100644
index 0000000..55c22c1
--- /dev/null
+++ b/static/css/img/picnicthr3.gif
Binary files differ
diff --git a/static/css/img/picnictop.gif b/static/css/img/picnictop.gif
new file mode 100644
index 0000000..91ccc5e
--- /dev/null
+++ b/static/css/img/picnictop.gif
Binary files differ
diff --git a/static/css/img/scan.png b/static/css/img/scan.png
new file mode 100644
index 0000000..6632095
--- /dev/null
+++ b/static/css/img/scan.png
Binary files differ
diff --git a/static/css/img/scroller1.gif b/static/css/img/scroller1.gif
new file mode 100644
index 0000000..633d7c1
--- /dev/null
+++ b/static/css/img/scroller1.gif
Binary files differ
diff --git a/static/css/img/tanasinn.gif b/static/css/img/tanasinn.gif
new file mode 100644
index 0000000..466614b
--- /dev/null
+++ b/static/css/img/tanasinn.gif
Binary files differ
diff --git a/static/css/img/vndb1.jpg b/static/css/img/vndb1.jpg
new file mode 100644
index 0000000..f91e414
--- /dev/null
+++ b/static/css/img/vndb1.jpg
Binary files differ
diff --git a/static/css/img/vndb2.jpg b/static/css/img/vndb2.jpg
new file mode 100644
index 0000000..e1dff0c
--- /dev/null
+++ b/static/css/img/vndb2.jpg
Binary files differ
diff --git a/static/css/img/vndb3.png b/static/css/img/vndb3.png
new file mode 100644
index 0000000..d31bc8f
--- /dev/null
+++ b/static/css/img/vndb3.png
Binary files differ
diff --git a/static/css/kraut.css b/static/css/kraut.css
new file mode 100644
index 0000000..a9e82da
--- /dev/null
+++ b/static/css/kraut.css
@@ -0,0 +1,24 @@
+html,body{background:#eee;color:#000;font-family:arial,helvetica,"nimbus sans l",sans-serif}
+.rep{background:#313370;border:1px solid #6569e5;border-radius:3px;color:#bdbee4;display:inline-block;font-size:14px;font-weight:bold;padding:1px;text-decoration:none}
+a,a .name,.nav label{color:#229}
+a:hover,a:hover .name,.nav label:hover{color:#922}
+#main_nav{background:#bbd;margin:-10px -10px 0;padding:10px}
+.replymode,.extramode{background:#313370;color:#fff}
+.postblock{background:#313370;color:#fff}
+.q{color:#077}
+.reply .fs{font-style:italic}
+.fs a{font-style:normal}
+.subj{color:#c33;font-weight:bold}
+.name{color:#33c}
+.omitted,.abbrev{color:#666}
+.reply,#q-p{background:#aac}
+.thumb{background:#ddd;border:1px solid #aaa}
+.reply .thumb{background:#99b;border:1px solid #aaf}
+#q-p{border:1px solid #003099;box-shadow:5px 5px #333}
+.highlight{background:#aac;/*border:2px dashed #448*/}
+.managertable td{background:#ddd}
+.managertable th{background:#313370;color:#fff}
+#catalog .thread:hover{background:#aac;box-shadow:0 0 5px 5px #aac}
+#catalog .replies{color:#888;font-weight:bold}
+.yt{background:#99b;border:1px solid #313370;color:#000}
+.quoted{border-color:#eee;color:#077} \ No newline at end of file
diff --git a/static/css/mobile.css b/static/css/mobile.css
new file mode 100644
index 0000000..9921d3a
--- /dev/null
+++ b/static/css/mobile.css
@@ -0,0 +1,129 @@
+*{box-sizing:border-box;word-wrap:break-word}
+body,input,textarea{color:#000;margin:0 auto;max-width:700px;padding:0}
+body,textarea{font-family:arial,sans-serif;font-size:16px}
+.txt{background:#efefef}
+.img{background:#1a1d22;color:#e0e0e0}
+br{line-height:0.5em}
+a{text-decoration:none}
+.txt a{color:#00c}
+.txt a:active{color:#f00}
+.img a{color:#b0ccde}
+.img a:hover{color:#5c6a74}
+.txt a.num{color:#222}
+.img .num{color:#a3a3a3;float:right}
+h1{font-size:18px}
+.txt h1{margin-left:2px}
+.img h1{color:#a6b8d8;margin:0 0 5px}
+h1 span{font-weight:400}
+h2{color:#a6b8d8;font-size:14px;margin:0;}
+h3,h4{clear:both;font-size:12px;font-weight:400;line-height:1;margin:10px 0}
+h3 em{font-weight:700;font-style:normal}
+h4{text-align:right}
+.txt h3,h4{color:#777}
+.txt h3.del,.txt h3.del a.num{color:#afafaf}
+.img h3{color:#a3a3a3;margin:0 0 5px}
+.img h3.del{color:#606060;margin-bottom:0}
+.prev h3{clear:none;margin:0}
+hr{margin:.25em 0}m
+.img hr{border:none;border-top:1px solid #333;height:0}
+.top{background:#444;color:#fff;font-size:32px;font-weight:700;line-height:1;min-height:30px;padding:10px 2px}
+.top a{color:#fff!important;float:right;font-size:14px;margin-top:-10px;padding-top:10px;text-align:center;height:50px;width:50px}
+.top a img{height:18px;width:18px}
+.bar{font-weight:bold;overflow-y:hidden;overflow-x:auto;white-space:nowrap;width:100%}
+.txt .bar{background:#ccc}
+.img .bar{background:#050607}
+.bar a{padding:8px;display:inline-block}
+.txt .bar a{color:#000}
+.img .bar a{color:#e0e0e0}
+.txt .bar a.sel{background:#efefef}
+.img .bar a.sel{background:#1a1d22}
+.ord{overflow-y:hidden;overflow-x:auto;white-space:nowrap;width:100%}
+.txt .ord{border-top:1px solid #f8f8f8;border-bottom:1px solid #ddd;color:#000}
+.img .ord{border-top:1px solid #444;border-bottom:1px solid #111;color:#e0e0e0}
+.ord span{display:inline-block;font-weight:bold;padding:7px 10px}
+.ord a{display:inline-block;padding:7px 10px}
+.ord a.sel:before{content:'✓ '}
+.txt .ord a{border-left:1px solid #f8f8f8;border-right:1px solid #ddd;color:#000}
+.img .ord a{border-left:1px solid #444;border-right:1px solid #111;color:#e0e0e0}
+.txt .ord a:hover{background:#dcdcdc}
+.img .ord a:hover{background:#14161a}
+.nav{text-align:center}
+.list a{display:block;padding:10px 5px}
+.txt .list a{border-top:1px solid #f8f8f8;border-bottom:1px solid #ddd;color:#000}
+.txt .list a:hover{background:#dcdcdc;color:#000}
+.img .list a{border-top:1px solid #444;border-bottom:1px solid #111;color:#e0e0e0;overflow:hidden}
+.img .list a:hover{background:#14161a}
+.list div{font-size:90%;font-weight:700;margin-top:3px;text-align:right}
+.list div span{font-weight:400}
+.list div span span{font-weight:700;color:red}
+.list .info{display:block;font-size:75%;margin-top:3px}
+.txt .list .info{color:#777}
+.img .list .info{color:#a3a3a3}
+.list .info span{float:right}
+.txt .nav{border-top:1px solid #c6c7c8}
+.img .nav{border-top:1px solid #333}
+.nav div{display:table;width:100%}
+.txt .nav div{border-bottom:1px solid #c6c7c8}
+.img .nav div{border-bottom:1px solid #333}
+.nav div a{display:table-cell;padding:6px 0;width:33%}
+.txt .nav div a,#nav2 a{border-right:1px solid #c6c7c8;color:#000}
+.img .nav div a{border-right:1px solid #333;color:#e0e0e0}
+.txt .nav div a:last-child,.img .nav div a:last-child{border-right:0}
+#nav2{overflow-y:auto;padding:3px;text-align:center;white-space:nowrap;width:100%}
+#nav2 a{border:1px solid #c6c7c8;border-radius:5px;display:inline-block;padding:4px}
+.msg{line-height:1.2em}
+.msg a{border:1px solid;border-radius:10px;display:inline-block;font-size:12px;margin:2px 0;padding:4px}
+.msg a[href^="/"]{border-radius:5px;font-size:inherit;padding:2px 4px}
+.thm{color:grey!important;font-size:12px;float:left;line-height:12px;margin-right:5px;text-align:center}
+.thm img{margin-bottom:2px}
+.mnu{transform:rotate(90deg);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);float:left;font-weight:bold;line-height:1}
+.txt a.mnu{color:#777;position:relative;left:2px}
+.img .mnu{color:#a3a3a3;margin-right:3px}
+#mnu-list{border:1px solid #111;border-bottom:0;box-shadow:1px 1px #000;display:inline-block;position:absolute}
+.txt #mnu-list{background:#E6E6E6}
+.img #mnu-list{background:#2A2D37}
+#mnu-list a{border-bottom:1px solid #111;color:inherit;display:block;padding:5px}
+.txt #mnu-list a:hover{background:#DDD}
+.img #mnu-list a:hover{background:#1E212B}
+.search input{background:#fff;border-top:1px solid #f8f8f8;border-right:0;border-bottom:1px solid #ddd;border-left:0;padding:8px;width:100%}
+.fld,#post,textarea{background:#fff;border:none;width:100%}
+.img .fld,.img textarea{border-bottom:1px solid #1a1d22}
+.txt .fld,.txt textarea{border-bottom:1px solid #efefef}
+input[type="text"].fld{font-size:12px;padding:4px 0}
+input[type="file"].fld{color:#000;padding:2px 0;width:100%}
+input[type="text"].imp{font-size:16px;font-weight:700}
+.file{display:table;width:100%}.file .fld{display:table-cell}
+.file label{color:#000;padding-left:5px;vertical-align:middle;white-space:nowrap;width:auto}
+#post{background:#fefefe;background:-webkit-linear-gradient(#fefefe,#e7e8e9);background:-o-linear-gradient(#fefefe,#e7e8e9);background:-moz-linear-gradient(#fefefe,#e7e8e9);background:linear-gradient(#fefefe,#e7e8e9);border-top:1px solid #c6c7c8;border-bottom:1px solid #c6c7c8;box-shadow:0 1px #fff,0 -1px #fff;display:block;padding:12px 0}
+#post:active{background:#e7e8e9;background:-webkit-linear-gradient(#e7e8e9,#fefefe);background:-o-linear-gradient(#e7e8e9,#fefefe);background:-moz-linear-gradient(#e7e8e9,#fefefe);background:linear-gradient(#e7e8e9,#fefefe)}
+#post:disabled{background:#fefefe;background:-webkit-linear-gradient(#fefefe,#e7e8e9);background:-o-linear-gradient(#fefefe,#e7e8e9);background:-moz-linear-gradient(#fefefe,#e7e8e9);background:linear-gradient(#fefefe,#e7e8e9);color:gray;text-shadow:1px 1px #fff}
+.img form{margin:5px 0}.img #post{margin-top:5px}
+.txt form{margin:10px 0}.txt #post{margin-top:10px}
+.img .cat{border:1px solid #373a44;color:#e0e0e0;display:inline-block;font-size:12px;height:150px;margin:3px;overflow:hidden;position:relative;padding:2px;text-align:center;vertical-align:top;width:130px}
+.img .cat:hover{color:#fff;background:#373a44}
+.img .cat img{margin-bottom:2px}
+.img .prev{border-bottom:1px solid #333;font-size:14px;margin:8px 0;overflow:hidden;padding:0 5px 8px}
+.img .prev .pst{margin-top:5px;margin-bottom:0}
+.img .first,.img .pst{display:block;padding:5px;overflow:hidden}
+.img .pst{background:#373a44;margin-bottom:5px}
+.img .q{color:#789922}
+.img .yt{background:#292c33;border:1px solid #5e6b7d;color:#e0e0e0}
+#n{display:block;padding:6px 0;text-align:center}
+.txt #n{border-top:1px solid #c6c7c8;color:#000}
+.img #n{border-top:1px solid #333;color:#e0e0e0}
+.txt #thread{margin-top:8px}
+.txt .msg a{background:#e9e9e9;border-color:#ccc}
+.txt .msg a:active{border-color:red}
+.txt .pst{border-top:1px solid #c6c7c8;padding:0 2px}
+.txt .q{color:#666}
+.txt .yt{background:#ddd;border:1px solid gray!important}
+.rules{font-size:12px;text-align:center}
+.txt .rules{margin:10px}.img .rules{margin:5px}
+.stop{font-size:75%;line-height:3em;padding:2px}
+.warn{font-size:75%;padding:5px 2px}
+.yellow{background:#ff0;color:#000}
+.red{background:red;color:#fff}
+.yt{border-radius:0!important;line-height:1.2em!important;margin:2px 0;padding:4px!important}
+.yt .pvw{float:left;height:60px;margin-right:4px;overflow:hidden;width:100px}
+.yt .pvw img{margin-top:-15px;margin-left:-10px}
+.yt b{font-size:115%} \ No newline at end of file
diff --git a/static/css/night.css b/static/css/night.css
new file mode 100644
index 0000000..ba3ee7b
--- /dev/null
+++ b/static/css/night.css
@@ -0,0 +1,22 @@
+html,body{background:#171e24;color:#979ea3;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif}
+a,a .name,.nav label{color:#c0c4c8}
+a.rep{color:#979ea3;text-decoration:underline}
+a:hover,a:hover .name,.nav label:hover{color:#888c90}
+.replymode,.extramode{color:#DDD}
+.replymode{background:#B40D00}
+.extramode{background:#001f6e}
+.postblock{background:#2b3843}
+.q{color:#789922}
+.subj{background:inherit;color:#962e5f;font-weight:bold}
+.name{color:#5f962e}
+.name a{color:#2e5f96}
+.name a:hover{color:#426fa0}
+.reply{background:#2F3D48;border:1px solid #1c242b}
+.abbrev{color:#707070}
+.highlight{background:#1D1D21;border:1px solid #111}
+hr{border:none;border-top:1px solid #979ea3;height:0}
+#catalog .thread:hover{background:#2F3D48;box-shadow:0 0 5px 5px #2F3D48}
+#catalog .replies{color:#909090;font-weight:bold}
+.yt{background:#52626D;border:1px solid #131D25}
+#q-p{background:#2F3D48}
+.quoted{border-color:#171e24} \ No newline at end of file
diff --git a/static/css/photon.css b/static/css/photon.css
new file mode 100644
index 0000000..7be906a
--- /dev/null
+++ b/static/css/photon.css
@@ -0,0 +1,22 @@
+html,body{background:#EEE;color:#333;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif}
+.rep{color:#333}
+a,a .name,a .name b,.logo,.nav label{color:#F60}
+a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#0066FF}
+.replymode,.extramode{color:#2266AA;border:solid 1px #CCC;background:#DDD}
+.postblock{background:#DDD;color:#024;border:1px solid #CCC;}
+.q{color:#789922}
+.fs,.abbrev{color:#666;text-decoration:none}
+.subj{color:#111;font-weight:bold}
+.name{color:#F30}
+.name b{color:#004A99}
+.omitted{color:#707070}
+.reply{background:#DDD;border:1px solid #CCC}
+.highlight{background:#CCC}
+.managertable td{background:#DDD;color:#024}
+.managertable th{background:#CCC;color:#024}
+hr{border:none;border-top:1px solid #BBB;height:0}
+#catalog .thread:hover{background:#DDD;box-shadow:0 0 5px 5px #DDD}
+#catalog .replies{color:#888;font-weight:bold}
+.yt{background:#E9E9E9;border:1px solid #BBB;color:#333}
+#q-p{background:#DDD}
+.quoted{border-color:#CCC} \ No newline at end of file
diff --git a/static/css/putaba.css b/static/css/putaba.css
new file mode 100644
index 0000000..840d5fd
--- /dev/null
+++ b/static/css/putaba.css
@@ -0,0 +1,46 @@
+html,body{background:#fff url('img/fondo2012.gif');font-family:"courier new",courier,monospace;color:#000}
+a,.reflink a,.nav label{color:#fff;text-decoration:none;background:#f60}
+a.rep{text-decoration:underline}
+a:hover,.reflink a:hover,.nav label:hover{background:#f00}
+a .name,a .name b{background:#0cf;color:#903}
+a:hover .name,a:hover .name b{background:#f33;color:#fff}
+input[type="button"],input[type="submit"]{background:#eff931;background:-moz-linear-gradient(top, #eff931 0%, #c9e800 100%);border:1px solid #d3de27;color:#333;padding:3px 10px}
+input,input[type="text"],input[type="password"],textarea,.searchbar input{background:#cf0;border:1px solid #000}
+#main_nav a{color:#000;background:#0cf}
+#main_nav a:hover{color:#fff;background:#90f}
+#main_nav span a{color:#fff;background:#f03}
+#main_nav span a:hover{background:#cf0}
+.replymode,.extramode{background:url('img/bgtb.gif');color:#000}
+hr,.ell{display:none}
+.thread hr{display:block}
+.thread,.userdelete,.postform,.oekform{background:#fff;box-shadow:1px 1px 1px rgba(50, 50, 50, 0.5);margin:0 10px 10px;padding:10px;overflow:auto}
+.postarea table{margin:0 auto 10px}
+.info,.fs{text-transform:uppercase}
+.thread label{background:#ff0}
+.thread label a,.thread label a:hover{background:#00ccff;color:#990033}
+.rules{letter-spacing:-0.5px}
+.rules li{margin-left:0.5em}
+.rules a{background:#f06;color:#fff}
+.rules a:hover{color:#cf0}
+.postblock{background:#ff0}
+.q{color:#789922}
+.subj{font-weight:bold;color:#909;background:#cf0;letter-spacing:-1px}
+.name{color:black;background:white}
+.name b{color:white;background:black}
+.date{background:#ff0}
+.omitted,.hsbn,.hsbn:hover{color:#ff3fff;background:#5500aa;display:inline-block}
+.reply,#q-p{background:#e6e6e6}
+.abbrev{color:#707070}
+.highlight{background:#ccc}
+.userdelete{padding:5px}
+input[type="submit"].psei{background:#ff6600;color:white;border:none;padding:0.4em 1em}
+.nav{float:left}
+.managertable td,.pg{background:#fff}
+.managertable th{background:#ddd}
+#catalog .thread:hover{background:#e6e6e6}
+#catalog .replies{background:#00ffff;color:#909090;font-weight:bold}
+.yt{background:#f7f7f7;border:1px solid #999;color:#000}
+.yt:hover{background:#efefef}
+.footer{background:#000;color:#fff}
+.footer a,.footer a:hover{background:#000}
+.quoted{border-color:#fff} \ No newline at end of file
diff --git a/static/css/red.css b/static/css/red.css
new file mode 100644
index 0000000..ad3159a
--- /dev/null
+++ b/static/css/red.css
@@ -0,0 +1,21 @@
+html,body{font-family:Georgia,"URW Bookman L",serif;background:#FFF2F2;color:#800000}
+a,a .name,.nav label{color:#00E}
+a:hover,a:hover .name,.nav label:hover{color:#D00}
+.rep{color:#800000}
+.replymode,.extramode{color:#FFF}
+.replymode{background:#E04000}
+.extramode{background:#0040E0}
+.postblock{background:#F99}
+.q{color:#789922}
+.name{color:#036}
+.omitted,.abbrev{color:#707070}
+.reply,#q-p{background:#FBB}
+.subj{color:#CC1105;font-weight:bold}
+.highlight{background:#F0E0D6}
+.managertable td{background:#FED0D0}
+.managertable th{background:#FA4A4A;color:#400000}
+#catalog .thread:hover{background:#FBB}
+#catalog .thread:hover{background:#FBB;box-shadow:0 0 5px 5px #FBB}
+#catalog .replies{color:#909090;font-weight:bold}
+.yt{background:#FED8D8;border:1px solid #FE9B9B;color:#500000}
+.quoted{border-color:#FFF2F2} \ No newline at end of file
diff --git a/static/css/rene.css b/static/css/rene.css
new file mode 100644
index 0000000..7126099
--- /dev/null
+++ b/static/css/rene.css
@@ -0,0 +1,22 @@
+html,body{background:#1a1d22;color:#e0e0e0;font-family:arial,helvetica,"nimbus sans l",sans-serif}
+.rep{color:#e0e0e0}
+a,a .name,.nav label{color:#b0ccde}
+a:hover,a:hover .name,.nav label:hover{color:#5c6a74}
+.replymode,.extramode{color:#fff}
+.replymode{background:#2b2b2b}
+.extramode{background:#333}
+.postblock{background:#28282d;border:1px solid #333;color:#ddd}
+.q{color:#789922}
+.fs{text-decoration:none}
+.subj{color:#a6b8d8;font-weight:bold}
+.name,.omitted{color:#a3a3a3}
+.reply,#q-p{background:#373a44}
+.abbrev{color:#777}
+.highlight{background:#5b5f69}
+.managertable td{background:#64697b}
+.managertable th{background:#252830;color:#f8f8f8}
+hr{border:none;border-top:1px dotted #696969;height:0}
+#catalog .thread:hover{background:#373a44;box-shadow:0 0 5px 5px #373a44}
+#catalog .replies{color:#909090;font-weight:bold}
+.yt{background:#292c33;border:1px solid #5e6b7d;color:#e0e0e0}
+.quoted{border-color:#1a1d22;color:#aaa} \ No newline at end of file
diff --git a/static/css/spc/base.css b/static/css/spc/base.css
new file mode 100644
index 0000000..bb30a24
--- /dev/null
+++ b/static/css/spc/base.css
@@ -0,0 +1,269 @@
+/*
+* Skeleton V1.2
+* Copyright 2011, Dave Gamache
+* www.getskeleton.com
+* Free to use under the MIT license.
+* http://www.opensource.org/licenses/mit-license.php
+* 6/20/2012
+*/
+
+
+/* Table of Content
+==================================================
+ #Reset & Basics
+ #Basic Styles
+ #Site Styles
+ #Typography
+ #Links
+ #Lists
+ #Images
+ #Buttons
+ #Forms
+ #Misc */
+
+
+/* #Reset & Basics (Inspired by E. Meyers)
+================================================== */
+ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline; }
+ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
+ display: block; }
+ body {
+ line-height: 1; }
+ ol, ul {
+ list-style: none; }
+ blockquote, q {
+ quotes: none; }
+ blockquote:before, blockquote:after,
+ q:before, q:after {
+ content: '';
+ content: none; }
+ table {
+ border-collapse: collapse;
+ border-spacing: 0; }
+
+
+/* #Basic Styles
+================================================== */
+ body {
+ background: #fff;
+ font: 14px/21px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #444;
+ -webkit-font-smoothing: antialiased; /* Fix for webkit rendering */
+ -webkit-text-size-adjust: 100%;
+ }
+
+
+/* #Typography
+================================================== */
+ h1, h2, h3, h4, h5, h6 {
+ color: #181818;
+ font-family: "Georgia", "Times New Roman", serif;
+ font-weight: normal; }
+ h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; }
+ h1 { font-size: 46px; line-height: 50px; margin-bottom: 14px;}
+ h2 { font-size: 35px; line-height: 40px; margin-bottom: 10px; }
+ h3 { font-size: 28px; line-height: 34px; margin-bottom: 8px; }
+ h4 { font-size: 21px; line-height: 30px; margin-bottom: 4px; }
+ h5 { font-size: 17px; line-height: 24px; }
+ h6 { font-size: 14px; line-height: 21px; }
+ .subheader { color: #777; }
+
+ p { margin: 0 0 20px 0; }
+ p img { margin: 0; }
+ p.lead { font-size: 21px; line-height: 27px; color: #777; }
+
+ em { font-style: italic; }
+ strong { font-weight: bold; color: #333; }
+ small { font-size: 60%; }
+
+/* Blockquotes */
+ blockquote, blockquote p { font-size: 17px; line-height: 24px; color: #777; font-style: italic; }
+ blockquote { margin: 0 0 20px; padding: 9px 20px 0 19px; border-left: 1px solid #ddd; }
+ blockquote cite { display: block; font-size: 12px; color: #555; }
+ blockquote cite:before { content: "\2014 \0020"; }
+ blockquote cite a, blockquote cite a:visited, blockquote cite a:visited { color: #555; }
+
+ hr { border: solid #ccc; border-width: 1px 0 0; clear: both; margin: 30px 0 30px; height: 0; }
+
+
+/* #Links
+================================================== */
+ a, a:visited { color: #333; text-decoration: underline; outline: 0; }
+ a:hover, a:focus { color: #000; }
+ p a, p a:visited { line-height: inherit; }
+
+
+/* #Lists
+================================================== */
+ ul, ol { margin-bottom: 20px; }
+ ul { list-style: none outside; }
+ ol { list-style: decimal; }
+ ol, ul.square, ul.circle, ul.disc { margin-left: 30px; }
+ ul.square { list-style: square outside; }
+ ul.circle { list-style: circle outside; }
+ ul.disc { list-style: disc outside; }
+ ul ul, ul ol,
+ ol ol, ol ul { margin: 4px 0 5px 30px; font-size: 90%; }
+ ul ul li, ul ol li,
+ ol ol li, ol ul li { margin-bottom: 6px; }
+ li { line-height: 18px; margin-bottom: 12px; }
+ ul.large li { line-height: 21px; }
+ li p { line-height: 21px; }
+
+/* #Images
+================================================== */
+
+ img.scale-with-grid {
+ max-width: 100%;
+ height: auto; }
+
+
+/* #Buttons
+================================================== */
+
+ .button,
+ button,
+ input[type="submit"],
+ input[type="reset"],
+ input[type="button"] {
+ background: #eee; /* Old browsers */
+ background: #eee -moz-linear-gradient(top, rgba(255,255,255,.2) 0%, rgba(0,0,0,.2) 100%); /* FF3.6+ */
+ background: #eee -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.2)), color-stop(100%,rgba(0,0,0,.2))); /* Chrome,Safari4+ */
+ background: #eee -webkit-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Chrome10+,Safari5.1+ */
+ background: #eee -o-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Opera11.10+ */
+ background: #eee -ms-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* IE10+ */
+ background: #eee linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* W3C */
+ border: 1px solid #aaa;
+ border-top: 1px solid #ccc;
+ border-left: 1px solid #ccc;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ color: #444;
+ display: inline-block;
+ font-size: 11px;
+ font-weight: bold;
+ text-decoration: none;
+ text-shadow: 0 1px rgba(255, 255, 255, .75);
+ cursor: pointer;
+ margin-bottom: 20px;
+ line-height: normal;
+ padding: 8px 10px;
+ font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; }
+
+ .button:hover,
+ button:hover,
+ input[type="submit"]:hover,
+ input[type="reset"]:hover,
+ input[type="button"]:hover {
+ color: #222;
+ background: #ddd; /* Old browsers */
+ background: #ddd -moz-linear-gradient(top, rgba(255,255,255,.3) 0%, rgba(0,0,0,.3) 100%); /* FF3.6+ */
+ background: #ddd -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.3)), color-stop(100%,rgba(0,0,0,.3))); /* Chrome,Safari4+ */
+ background: #ddd -webkit-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Chrome10+,Safari5.1+ */
+ background: #ddd -o-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Opera11.10+ */
+ background: #ddd -ms-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* IE10+ */
+ background: #ddd linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* W3C */
+ border: 1px solid #888;
+ border-top: 1px solid #aaa;
+ border-left: 1px solid #aaa; }
+
+ .button:active,
+ button:active,
+ input[type="submit"]:active,
+ input[type="reset"]:active,
+ input[type="button"]:active {
+ border: 1px solid #666;
+ background: #ccc; /* Old browsers */
+ background: #ccc -moz-linear-gradient(top, rgba(255,255,255,.35) 0%, rgba(10,10,10,.4) 100%); /* FF3.6+ */
+ background: #ccc -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.35)), color-stop(100%,rgba(10,10,10,.4))); /* Chrome,Safari4+ */
+ background: #ccc -webkit-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Chrome10+,Safari5.1+ */
+ background: #ccc -o-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Opera11.10+ */
+ background: #ccc -ms-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* IE10+ */
+ background: #ccc linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* W3C */ }
+
+ .button.full-width,
+ button.full-width,
+ input[type="submit"].full-width,
+ input[type="reset"].full-width,
+ input[type="button"].full-width {
+ width: 100%;
+ padding-left: 0 !important;
+ padding-right: 0 !important;
+ text-align: center; }
+
+ /* Fix for odd Mozilla border & padding issues */
+ button::-moz-focus-inner,
+ input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+ }
+
+
+/* #Forms
+================================================== */
+
+ form {
+ margin-bottom: 20px; }
+ fieldset {
+ margin-bottom: 20px; }
+ input[type="text"],
+ input[type="password"],
+ input[type="email"],
+ textarea,
+ select {
+ border: 1px solid #ccc;
+ padding: 6px 4px;
+ outline: none;
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+ font: 13px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color: #777;
+ margin: 0;
+ width: 210px;
+ max-width: 100%;
+ display: block;
+ margin-bottom: 20px;
+ background: #fff; }
+ select {
+ padding: 0; }
+ input[type="text"]:focus,
+ input[type="password"]:focus,
+ input[type="email"]:focus,
+ textarea:focus {
+ border: 1px solid #aaa;
+ color: #444;
+ -moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
+ -webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
+ box-shadow: 0 0 3px rgba(0,0,0,.2); }
+ textarea {
+ min-height: 60px; }
+ label,
+ legend {
+ display: block;
+ font-weight: bold;
+ font-size: 13px; }
+ select {
+ width: 220px; }
+ input[type="checkbox"] {
+ display: inline; }
+ label span,
+ legend span {
+ font-weight: normal;
+ font-size: 13px;
+ color: #444; }
+
+/* #Misc
+================================================== */
+ .remove-bottom { margin-bottom: 0 !important; }
+ .half-bottom { margin-bottom: 10px !important; }
+ .add-bottom { margin-bottom: 20px !important; }
+
+
diff --git a/static/css/spc/halloween.css b/static/css/spc/halloween.css
new file mode 100644
index 0000000..6870152
--- /dev/null
+++ b/static/css/spc/halloween.css
@@ -0,0 +1,47 @@
+body,textarea,h2 small,.del a{color:#FA5923}
+body.mainpage,body.threads{background:#000 url('../img/bg_madera.png');}
+body.threadpage{background:#111}
+a,#n2{color:#F00}
+a:active,a:active .name,#n2:active{color:#f60}
+hr{border:0;border-top:1px solid #900;border-bottom: 1px solid #500000}
+input[type=submit]:active,input[type=button]:active,a:active{filter:blur(2px)}
+h1{text-shadow:0 4px 1px #300000,0 6px 1px #400000,0 8px 1px #500000,0 10px 1px #600000,0 12px 1px #700000,0 14px 1px #800000,0 16px 1px #900000,0 18px 1px #A00000,0 20px 1px #B00000,0 22px 1px #C00000,0 24px 1px #D00000,0 26px 1px #E00000,0 28px 1px #F00000,0 30px 1px #FA0000,0 32px 1px #FB0000,0 34px 1px #FC0000,0 36px 1px #FD0000,0 38px 1px #FE0000,0 40px 2px #F00}
+.threads h1{margin-bottom:35px}
+h2{margin-bottom:3px}
+h2 a{color:#32cd32}
+h3{color:#F00}
+h3 span{color:#900}
+#main_nav{background:#000}
+.outerbox{background:#000;border:1px outset #FF4500;color:#FFA500}
+.innerbox{border:1px inset #FF4500}
+#threadlist{background:#330e00;border:1px inset #FF4500}
+.mainpage .thread,#content{background:#111;border:1px outset #914400}
+.name,a .name,.abbrev{color:#f90}
+.name em{color:#111e6c}
+.msg{color:#fa6a39;margin:4px 40px 24px}
+a.thumb{margin-top:4px}
+.q{color:#875384}
+.yt{background:#240000;border:1px solid #FF4500}
+.deleted{color:#592a56;margin-bottom:24px}
+.outerbox input,.outerbox textarea{background:#222;color:#FFA500;border:1px solid #FF4500}
+.outerbox input:focus,.outerbox textarea:focus{background:#401100}
+.outerbox input[type=submit],.outerbox input[type=button]{background:#000;box-shadow:0 0 5px #FF4500}
+.threadpage input,.threadpage textarea,.thread input,.thread textarea{background:#0C050D;border:1px solid #FA5923;color:#FA5923}
+.threadpage input:focus,.threadpage textarea:focus,.thread input:focus,.thread textarea:focus{background:#290c0a}
+.threadpage input[type=submit],.threadpage input[type=button],.thread input[type=submit],.thread input[type=button]{background:#0C050D}
+#q-p{background:#160901;border:1px solid #521;box-shadow:0 0 5px #521}
+#q-p .msg,#q-p a.thumb{margin-bottom:8px}
+#createbox{display:flex}
+#createbox .extrabox{border:1px inset grey;margin:7px 0 7px 7px;float:left;width:40px;height:auto;flex:0 1 40px;-webkit-flex:0 1 40px}
+#createbox .innerbox{flex:0 1 100%;-webkit-flex:0 1 100%}
+form .msg{border:1px dotted #FA5923;background:#000}
+#footer{text-shadow:0 0 2px}
+#content.list{padding:7px}
+#content.list #header div{background:#2d0000;border-top:1px inset #914400}
+#content.list .row:nth-child(odd),#content.grid .row:hover{background:#000}
+#content.list .row div:first-child{border-left:1px inset #914400}
+#content.list .row div:last-child{border-right:1px inset #914400}
+#content.list .row:last-child div{border-bottom:1px inset #914400}
+#content.grid{border:1px outset #914400;padding:1px}
+#content.grid .row{border:1px inset #914400;margin:1px}
+@media screen and (max-width:480px){.msg{margin:4px 20px 12px}} \ No newline at end of file
diff --git a/static/css/spc/layout.css b/static/css/spc/layout.css
new file mode 100644
index 0000000..b99f451
--- /dev/null
+++ b/static/css/spc/layout.css
@@ -0,0 +1,58 @@
+/*
+* Skeleton V1.2
+* Copyright 2011, Dave Gamache
+* www.getskeleton.com
+* Free to use under the MIT license.
+* http://www.opensource.org/licenses/mit-license.php
+* 6/20/2012
+*/
+
+/* Table of Content
+==================================================
+ #Site Styles
+ #Page Styles
+ #Media Queries
+ #Font-Face */
+
+/* #Site Styles
+================================================== */
+
+/* #Page Styles
+================================================== */
+
+/* #Media Queries
+================================================== */
+
+ /* Smaller than standard 960 (devices and browsers) */
+ @media only screen and (max-width: 959px) {}
+
+ /* Tablet Portrait size to standard 960 (devices and browsers) */
+ @media only screen and (min-width: 768px) and (max-width: 959px) {}
+
+ /* All Mobile Sizes (devices and browser) */
+ @media only screen and (max-width: 767px) {}
+
+ /* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
+ @media only screen and (min-width: 480px) and (max-width: 767px) {}
+
+ /* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
+ @media only screen and (max-width: 479px) {}
+
+
+/* #Font-Face
+================================================== */
+/* This is the proper syntax for an @font-face file
+ Just create a "fonts" folder at the root,
+ copy your FontName into code below and remove
+ comment brackets */
+
+/* @font-face {
+ font-family: 'FontName';
+ src: url('../fonts/FontName.eot');
+ src: url('../fonts/FontName.eot?iefix') format('eot'),
+ url('../fonts/FontName.woff') format('woff'),
+ url('../fonts/FontName.ttf') format('truetype'),
+ url('../fonts/FontName.svg#webfontZam02nTh') format('svg');
+ font-weight: normal;
+ font-style: normal; }
+*/ \ No newline at end of file
diff --git a/static/css/spc/navidad.css b/static/css/spc/navidad.css
new file mode 100644
index 0000000..4d90c6a
--- /dev/null
+++ b/static/css/spc/navidad.css
@@ -0,0 +1,161 @@
+html, body {
+ background:#004608;
+ color:#fff;
+}
+a {
+ color:#EFD279;
+}
+a.rep {
+ color:#fff;
+}
+a:hover {
+ color:#DD0000;
+}
+.reflink a:hover{
+ font-weight: bold;
+}
+.adminbar {
+ text-align:right;
+ clear:both;
+ float:right;
+}
+.logo {
+ clear:both;
+ text-align:center;
+ font-size:2em;
+ color:#CCFFCC;
+ width:100%;
+}
+.replymode {
+ background:#078B26;
+ text-align:center;
+ padding:2px;
+ color:#FFFFFF;
+ width:100%;
+}
+.catalogmode {
+ background:#0040E0;
+ text-align:center;
+ padding:2px;
+ color:#FFFFFF;
+ width:100%;
+}
+.rules {
+ /*font-size:0.7em;*/
+ width: 468px;
+ font-size: 10px;
+ font-family: sans-serif;
+}
+.rules li {
+ margin-left: 1em;
+ /*text-indent: 0em;*/
+}
+.postblock {
+ background:#B00000;
+ color:#FFF;
+ font-weight:800;
+}
+.footer {
+ text-align:center;
+ font-size:12px;
+ font-family:serif;
+}
+.passvalid {
+ background:#EEAA88;
+ text-align:center;
+ width:100%;
+ color:#ffffff;
+}
+.dellist {
+ font-weight: bold;
+ text-align:center;
+}
+.delbuttons {
+ text-align:center;
+ padding-bottom:4px;
+
+}
+.managehead {
+ background:#AAAA66;
+ color:#400000;
+ padding:0px;
+}
+.postlists {
+ background:#FFFFFF;
+ width:100%;
+ padding:0px;
+ color:#800000;
+}
+.row1 {
+ background:#EEEECC;
+ color:#800000;
+}
+.row2 {
+ background:#DDDDAA;
+ color:#800000;
+}
+.q {
+ background:inherit;
+ color:#BDF46C;
+}
+.filesize {
+ text-decoration:none;
+}
+.filetitle {
+ background:inherit;
+ font-size:1.3em;
+ color:#E91F1F;
+ font-weight:800;
+}
+.postername {
+ color:#AFD775;
+ font-weight:bold;
+}
+.postertrip {
+ color:#AFD775;
+}
+.oldpost {
+ color:#CC1105;
+ font-weight:800;
+}
+.omittedposts {
+ color:#909090;
+}
+.reply {
+ background: #078B26;
+ color: #fff;
+}
+.replyhl {
+ background: #F0C0B0;
+ color: #800000;
+}
+.replytitle {
+ font-size: 1.2em;
+ color:#CC1105;
+ font-weight:800;
+}
+.commentpostername {
+ color:#117743;
+ font-weight:800;
+}
+.thumbnailmsg {
+ font-size: small;
+ color:#800000;
+}
+
+.abbrev {
+ color:#707070;
+}
+.highlight {
+ /*background:#95CBE9;*/
+ background: #5B8BB4;
+ /*color:#2C5700;*/
+ /*border: 2px dashed #070;*/
+ border: 2px dashed #AFD775;
+}
+.banned {
+ color:#F99C64;
+}
+.administrator {
+ color:#C00 !important;
+}
diff --git a/static/css/spc/skeleton.css b/static/css/spc/skeleton.css
new file mode 100644
index 0000000..049db08
--- /dev/null
+++ b/static/css/spc/skeleton.css
@@ -0,0 +1,242 @@
+/*
+* Skeleton V1.2
+* Copyright 2011, Dave Gamache
+* www.getskeleton.com
+* Free to use under the MIT license.
+* http://www.opensource.org/licenses/mit-license.php
+* 6/20/2012
+*/
+
+
+/* Table of Contents
+==================================================
+ #Base 960 Grid
+ #Tablet (Portrait)
+ #Mobile (Portrait)
+ #Mobile (Landscape)
+ #Clearing */
+
+
+
+/* #Base 960 Grid
+================================================== */
+
+ .container { position: relative; width: 960px; margin: 0 auto; padding: 0; }
+ .container .column,
+ .container .columns { float: left; display: inline; margin-left: 10px; margin-right: 10px; }
+ .row { margin-bottom: 20px; }
+
+ /* Nested Column Classes */
+ .column.alpha, .columns.alpha { margin-left: 0; }
+ .column.omega, .columns.omega { margin-right: 0; }
+
+ /* Base Grid */
+ .container .one.column,
+ .container .one.columns { width: 40px; }
+ .container .two.columns { width: 100px; }
+ .container .three.columns { width: 160px; }
+ .container .four.columns { width: 220px; }
+ .container .five.columns { width: 280px; }
+ .container .six.columns { width: 340px; }
+ .container .seven.columns { width: 400px; }
+ .container .eight.columns { width: 460px; }
+ .container .nine.columns { width: 520px; }
+ .container .ten.columns { width: 580px; }
+ .container .eleven.columns { width: 640px; }
+ .container .twelve.columns { width: 700px; }
+ .container .thirteen.columns { width: 760px; }
+ .container .fourteen.columns { width: 820px; }
+ .container .fifteen.columns { width: 880px; }
+ .container .sixteen.columns { width: 940px; }
+
+ .container .one-third.column { width: 300px; }
+ .container .two-thirds.column { width: 620px; }
+
+ /* Offsets */
+ .container .offset-by-one { padding-left: 60px; }
+ .container .offset-by-two { padding-left: 120px; }
+ .container .offset-by-three { padding-left: 180px; }
+ .container .offset-by-four { padding-left: 240px; }
+ .container .offset-by-five { padding-left: 300px; }
+ .container .offset-by-six { padding-left: 360px; }
+ .container .offset-by-seven { padding-left: 420px; }
+ .container .offset-by-eight { padding-left: 480px; }
+ .container .offset-by-nine { padding-left: 540px; }
+ .container .offset-by-ten { padding-left: 600px; }
+ .container .offset-by-eleven { padding-left: 660px; }
+ .container .offset-by-twelve { padding-left: 720px; }
+ .container .offset-by-thirteen { padding-left: 780px; }
+ .container .offset-by-fourteen { padding-left: 840px; }
+ .container .offset-by-fifteen { padding-left: 900px; }
+
+
+
+/* #Tablet (Portrait)
+================================================== */
+
+ /* Note: Design for a width of 768px */
+
+ @media only screen and (min-width: 768px) and (max-width: 959px) {
+ .container { width: 768px; }
+ .container .column,
+ .container .columns { margin-left: 10px; margin-right: 10px; }
+ .column.alpha, .columns.alpha { margin-left: 0; margin-right: 10px; }
+ .column.omega, .columns.omega { margin-right: 0; margin-left: 10px; }
+ .alpha.omega { margin-left: 0; margin-right: 0; }
+
+ .container .one.column,
+ .container .one.columns { width: 28px; }
+ .container .two.columns { width: 76px; }
+ .container .three.columns { width: 124px; }
+ .container .four.columns { width: 172px; }
+ .container .five.columns { width: 220px; }
+ .container .six.columns { width: 268px; }
+ .container .seven.columns { width: 316px; }
+ .container .eight.columns { width: 364px; }
+ .container .nine.columns { width: 412px; }
+ .container .ten.columns { width: 460px; }
+ .container .eleven.columns { width: 508px; }
+ .container .twelve.columns { width: 556px; }
+ .container .thirteen.columns { width: 604px; }
+ .container .fourteen.columns { width: 652px; }
+ .container .fifteen.columns { width: 700px; }
+ .container .sixteen.columns { width: 748px; }
+
+ .container .one-third.column { width: 236px; }
+ .container .two-thirds.column { width: 492px; }
+
+ /* Offsets */
+ .container .offset-by-one { padding-left: 48px; }
+ .container .offset-by-two { padding-left: 96px; }
+ .container .offset-by-three { padding-left: 144px; }
+ .container .offset-by-four { padding-left: 192px; }
+ .container .offset-by-five { padding-left: 240px; }
+ .container .offset-by-six { padding-left: 288px; }
+ .container .offset-by-seven { padding-left: 336px; }
+ .container .offset-by-eight { padding-left: 384px; }
+ .container .offset-by-nine { padding-left: 432px; }
+ .container .offset-by-ten { padding-left: 480px; }
+ .container .offset-by-eleven { padding-left: 528px; }
+ .container .offset-by-twelve { padding-left: 576px; }
+ .container .offset-by-thirteen { padding-left: 624px; }
+ .container .offset-by-fourteen { padding-left: 672px; }
+ .container .offset-by-fifteen { padding-left: 720px; }
+ }
+
+
+/* #Mobile (Portrait)
+================================================== */
+
+ /* Note: Design for a width of 320px */
+
+ @media only screen and (max-width: 767px) {
+ .container { width: 300px; }
+ .container .columns,
+ .container .column { margin: 0; }
+
+ .container .one.column,
+ .container .one.columns,
+ .container .two.columns,
+ .container .three.columns,
+ .container .four.columns,
+ .container .five.columns,
+ .container .six.columns,
+ .container .seven.columns,
+ .container .eight.columns,
+ .container .nine.columns,
+ .container .ten.columns,
+ .container .eleven.columns,
+ .container .twelve.columns,
+ .container .thirteen.columns,
+ .container .fourteen.columns,
+ .container .fifteen.columns,
+ .container .sixteen.columns,
+ .container .one-third.column,
+ .container .two-thirds.column { width: 300px; }
+
+ /* Offsets */
+ .container .offset-by-one,
+ .container .offset-by-two,
+ .container .offset-by-three,
+ .container .offset-by-four,
+ .container .offset-by-five,
+ .container .offset-by-six,
+ .container .offset-by-seven,
+ .container .offset-by-eight,
+ .container .offset-by-nine,
+ .container .offset-by-ten,
+ .container .offset-by-eleven,
+ .container .offset-by-twelve,
+ .container .offset-by-thirteen,
+ .container .offset-by-fourteen,
+ .container .offset-by-fifteen { padding-left: 0; }
+
+ }
+
+
+/* #Mobile (Landscape)
+================================================== */
+
+ /* Note: Design for a width of 480px */
+
+ @media only screen and (min-width: 480px) and (max-width: 767px) {
+ .container { width: 420px; }
+ .container .columns,
+ .container .column { margin: 0; }
+
+ .container .one.column,
+ .container .one.columns,
+ .container .two.columns,
+ .container .three.columns,
+ .container .four.columns,
+ .container .five.columns,
+ .container .six.columns,
+ .container .seven.columns,
+ .container .eight.columns,
+ .container .nine.columns,
+ .container .ten.columns,
+ .container .eleven.columns,
+ .container .twelve.columns,
+ .container .thirteen.columns,
+ .container .fourteen.columns,
+ .container .fifteen.columns,
+ .container .sixteen.columns,
+ .container .one-third.column,
+ .container .two-thirds.column { width: 420px; }
+ }
+
+
+/* #Clearing
+================================================== */
+
+ /* Self Clearing Goodness */
+ .container:after { content: "\0020"; display: block; height: 0; clear: both; visibility: hidden; }
+
+ /* Use clearfix class on parent to clear nested columns,
+ or wrap each row of columns in a <div class="row"> */
+ .clearfix:before,
+ .clearfix:after,
+ .row:before,
+ .row:after {
+ content: '\0020';
+ display: block;
+ overflow: hidden;
+ visibility: hidden;
+ width: 0;
+ height: 0; }
+ .row:after,
+ .clearfix:after {
+ clear: both; }
+ .row,
+ .clearfix {
+ zoom: 1; }
+
+ /* You can also use a <br class="clear" /> to clear columns */
+ .clear {
+ clear: both;
+ display: block;
+ overflow: hidden;
+ visibility: hidden;
+ width: 0;
+ height: 0;
+ } \ No newline at end of file
diff --git a/static/css/spc/valentin.css b/static/css/spc/valentin.css
new file mode 100644
index 0000000..bbbc6c1
--- /dev/null
+++ b/static/css/spc/valentin.css
@@ -0,0 +1,170 @@
+html, body {
+ /*background:#940BFE;*/
+ background: url('img/corazoncitos.gif');
+ color:#fff;
+}
+a {
+ color:#EFD279;
+}
+a.rep {
+ color:#fff;
+}
+a:hover {
+ color:#DD0000;
+}
+.reflink a:hover{
+ font-weight: bold;
+}
+.adminbar {
+ text-align:right;
+ clear:both;
+ float:right;
+}
+.logo {
+ clear:both;
+ text-align:center;
+ font-size:2em;
+ color:#CCFFCC;
+ width:100%;
+}
+.replymode {
+ background:#0BBEB8;
+ text-align:center;
+ padding:2px;
+ color:#FFFFFF;
+ width:100%;
+}
+.extramode {
+ background:#0040E0;
+ text-align:center;
+ padding:2px;
+ color:#FFFFFF;
+ width:100%;
+}
+.rules {
+ /*font-size:0.7em;*/
+ width: 468px;
+ font-size: 11px;
+ font-family: sans-serif;
+}
+.rules li {
+ margin-left: 1em;
+ /*text-indent: 0em;*/
+}
+.postblock {
+ background:#95CBE9;
+ color:#2C5700;
+ font-weight:800;
+}
+.footer {
+ text-align:center;
+ font-size:12px;
+ font-family:serif;
+}
+.passvalid {
+ background:#EEAA88;
+ text-align:center;
+ width:100%;
+ color:#ffffff;
+}
+.dellist {
+ font-weight: bold;
+ text-align:center;
+}
+.delbuttons {
+ text-align:center;
+ padding-bottom:4px;
+
+}
+.managehead {
+ background:#AAAA66;
+ color:#400000;
+ padding:0px;
+}
+.postlists {
+ background:#FFFFFF;
+ width:100%;
+ padding:0px;
+ color:#800000;
+}
+.row1 {
+ background:#EEEECC;
+ color:#800000;
+}
+.row2 {
+ background:#DDDDAA;
+ color:#800000;
+}
+.q {
+ background:inherit;
+ color:#BDF46C;
+}
+.filesize {
+ text-decoration:none;
+}
+.filetitle {
+ background:inherit;
+ font-size:1.3em;
+ color:#DE9D7F;
+ font-weight:800;
+}
+.postername {
+ color:#AFD775;
+ font-weight:bold;
+}
+.postertrip {
+ color:#AFD775;
+}
+.oldpost {
+ color:#CC1105;
+ font-weight:800;
+}
+.omittedposts {
+ color:#909090;
+}
+.reply {
+ background: #FE0BDF;
+ color: #fff;
+}
+.replyhl {
+ background: #F0C0B0;
+ color: #800000;
+}
+.replytitle {
+ font-size: 1.2em;
+ color:#CC1105;
+ font-weight:800;
+}
+.commentpostername {
+ color:#117743;
+ font-weight:800;
+}
+.thumbnailmsg {
+ font-size: small;
+ color:#800000;
+}
+
+.abbrev {
+ color:#707070;
+}
+.highlight {
+ /*background:#95CBE9;*/
+ background: #5B8BB4;
+ /*color:#2C5700;*/
+ /*border: 2px dashed #070;*/
+ border: 2px dashed #AFD775;
+}
+.banned {
+ color:#F99C64;
+}
+.administrator {
+ color:#C00 !important;
+}
+.managertable td {
+ background:#3B6B94;
+ color:#FFF;
+}
+.managertable th {
+ background:#AAF;
+ color:#FFF;
+} \ No newline at end of file
diff --git a/static/css/spc/valentin2.css b/static/css/spc/valentin2.css
new file mode 100644
index 0000000..189611c
--- /dev/null
+++ b/static/css/spc/valentin2.css
@@ -0,0 +1,177 @@
+html, body {
+ background:url('img/hearts1.gif');
+ color:#000;
+}
+a {
+ color:#2D89D0;
+}
+a.rep {
+ color:#000;
+}
+a:hover {
+ color:#DD0000;
+}
+.reflink a:hover{
+ font-weight: bold;
+}
+.adminbar {
+ text-align:right;
+ clear:both;
+ float:right;
+}
+.logo {
+ clear:both;
+ text-align:center;
+ font-size:2em;
+ color:#B35692;
+ width:100%;
+}
+.replymode {
+ background:#1D7548;
+ text-align:center;
+ font-weight: bold;
+ padding:2px;
+ color:#FFFFFF;
+ width:100%;
+}
+.extramode {
+ background:#0040E0;
+ text-align:center;
+ font-weight: bold;
+ padding:2px;
+ color:#FFFFFF;
+ width:100%;
+}
+.rules {
+ /*font-size:0.7em;*/
+ width: 468px;
+ font-size: 11px;
+ font-family: sans-serif;
+}
+.rules li {
+ margin-left: 1em;
+ /*text-indent: 0em;*/
+}
+.postblock {
+ background:#FF7BD1;
+ color:#666;
+ font-weight:800;
+}
+.footer {
+ text-align:center;
+ font-size:12px;
+ font-family:serif;
+}
+.passvalid {
+ background:#EEAA88;
+ text-align:center;
+ width:100%;
+ color:#ffffff;
+}
+.dellist {
+ font-weight: bold;
+ text-align:center;
+}
+.delbuttons {
+ text-align:center;
+ padding-bottom:4px;
+
+}
+.managehead {
+ background:#AAAA66;
+ color:#400000;
+ padding:0px;
+}
+.postlists {
+ background:#FFFFFF;
+ width:100%;
+ padding:0px;
+ color:#800000;
+}
+.row1 {
+ background:#EEEECC;
+ color:#800000;
+}
+.row2 {
+ background:#DDDDAA;
+ color:#800000;
+}
+.q {
+ background:inherit;
+ color:#3D343C;
+}
+blockquote blockquote {
+ background:inherit;
+ color:#6D940C;
+}
+.filesize {
+ text-decoration:none;
+}
+.filetitle {
+ background:inherit;
+ font-size:1.3em;
+ color:#DC3D90;
+ font-weight:800;
+}
+.postername {
+ color:#C000D6;
+ font-weight:bold;
+}
+.postertrip {
+ color:#C000D;
+}
+.oldpost {
+ color:#CC1105;
+ font-weight:800;
+}
+.omittedposts {
+ color:#909090;
+}
+.reply {
+ background: url('img/hearts2.jpg');
+ border: 1px solid #BBF;
+ color: #333;
+}
+.replyhl {
+ background: #F0C0B0;
+ color: #800000;
+}
+.replytitle {
+ font-size: 1.2em;
+ color:#DE9D7F;
+ font-weight:800;
+}
+.commentpostername {
+ color:#117743;
+ font-weight:800;
+}
+.thumbnailmsg {
+ font-size: small;
+ color:#000;
+ margin: 0;
+}
+
+.abbrev {
+ color:#707070;
+}
+.highlight {
+ /*background:#95CBE9;*/
+ background: #5B8BB4;
+ /*color:#2C5700;*/
+ /*border: 2px dashed #070;*/
+ border: 2px dashed #AFD775;
+}
+.banned {
+ color:#F99C64;
+}
+.administrator {
+ color:#C00 !important;
+}
+.managertable td {
+ background:#3B6B94;
+ color:#FFF;
+}
+.managertable th {
+ background:#AAF;
+ color:#FFF;
+}
diff --git a/static/css/txt/4am.css b/static/css/txt/4am.css
new file mode 100644
index 0000000..c3f06b4
--- /dev/null
+++ b/static/css/txt/4am.css
@@ -0,0 +1,42 @@
+body{background:#222 url('/bg2.gif');color:#CED1CF}
+body.threadpage{background-image:none}
+a,a .name,#n2{color:#81A2BE;text-decoration:none}
+a:hover,a:focus,#n2:active{text-decoration:underline}
+hr{border:1px inset #111}
+input[type="text"],input[type="submit"],input[type="button"],textarea,button{background:#383838;border:1px solid #4B4E55;color:#e8e8e8}
+input[type="submit"],input[type="button"],button{background:#333;padding:2px 10px}
+input[type="submit"]:active,input[type="button"]:active,button:active{background:#232323}
+h1{color:#dc9656;font-size:26px;margin-top:-5px;text-align:center}
+h2 a{color:#C66}
+h2 span{color:#999}
+h3{color:#ab4642}
+h3 span{color:#999}
+h4{color:#c1c5c2}
+#main_nav{background:#000;color:#7cafc2;z-index:9}
+.banner{-webkit-filter:grayscale(60%);filter:grayscale(60%)}
+.outerbox{background:#111213;border:1px solid #4B4E55;color:#777879}
+#titlebox .threadnav{margin:-6px}
+#threadlist{background:#0e0e0e;border:1px solid #4B4E55}
+.mainpage .thread,#content{background:#1D1F21;border:3px double #4B4E55;color:#CED1CF;opacity:.9}
+.threadpage .thread{color:#CED1CF}
+.name,.abbrev{color:#B5BD68}
+.name em{color:#88f}
+.del a{color:#ab4642}
+h4 .date,.quoted{color:#4e4e4e}
+.msg{margin:4px 40px 24px}
+a.thumb{margin-top:4px}
+.q{color:#666}
+.yt{background:#383838;border:1px solid gray;color:#e8e8e8}
+.yt:hover{text-decoration:none}
+.deleted{color:#999;margin-bottom:12px}
+#q-p{background:#222;border:1px solid #999}
+#q-p .msg,#q-p a.thumb{margin-bottom:8px}
+.lastposts #n2{text-decoration:none}
+.size{color:#ab4642}
+form .msg{background:#383838;border:1px dotted #000}
+#footer{color:#f7ca88}
+.threads h1{text-align:left}
+#content.list #header div{background:#111213}
+#content.list .row:nth-child(odd),#content.grid .row:hover{background:#191B1D}
+#content.grid{border:1px solid #4B4E55;padding:1px}
+#content.grid .row{border:1px solid #4B4E55;margin:1px} \ No newline at end of file
diff --git a/static/css/txt/amber.css b/static/css/txt/amber.css
new file mode 100644
index 0000000..3de2dd5
--- /dev/null
+++ b/static/css/txt/amber.css
@@ -0,0 +1,44 @@
+body{background:#000;text-shadow:1px 1px #000,0 0 10px}
+body,a,h2 a,h3,#n2{color:#f9690e}
+a:active,#n2:active{color:#FF9F3F}
+h4{background:#f9690e;color:#000;padding:0 7px;text-shadow:none}
+.threadpage h4{padding:0 3px}
+h4 a,.name,.name a{color:#000}
+h1:after,h2 a:after,h3:after{content:"_";animation:blink 1s infinite}@keyframes blink{from,to{opacity:0}50%{opacity:1}}
+h2,.thread .threadnav{margin:7px}
+h3{margin:8px 0}
+h3 span,.size,.abbrev{color:#f00}
+hr{background:#f9690e;border:0;height:1px;box-shadow:0 0 10px #f9690e}
+.spoil{background:#f9690e;color:#f9690e;text-shadow:none}.spoil:hover{color:#000}
+input[type=submit],input[type=button],button{padding:2px 10px}
+input,button{font-family:monospace}
+input,input[type="text"],textarea,button{background:#000;border:1px solid #f9690e;color:#f9690e;text-shadow:1px 1px #000}
+input[type="text"]:focus,textarea:focus{background:#3a1903}
+input[type=submit]:active,input[type=button]:active,button:active{background:#f9690e;color#000}
+#main_nav{background:#000;box-shadow: 0 0 10px}
+.outerbox,.innerbox{border:1px solid #f9690e}
+#threadlist{border:3px double #f9690e}
+.mainpage .thread,.thread .innerbox{border:1px solid #f9690e}
+.thread .innerbox,.threadpage,#q-p{background:#000 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gkRBxEEIxazLgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAGklEQVQI12NkYGD4z4AEmBjQAAsvK6oAhgoAQ6UBGwQB8rcAAAAASUVORK5CYII=')}
+.thread .innerbox{padding:0}
+.name em{color:#ff0}
+.q{color:#d4b300}
+.deleted{background:none;border-color:#f9690e;border-style:solid;border-width:1px 0;color:inherit}
+.yt{background:#000;border:1px solid #f9690e}
+.mainpage .postform{border-top:1px solid #f9690e;padding:1em 0 1em 40px}
+.formpad{padding:0}
+form .msg{border:1px dotted #f9690e;background:#000;color:#f9690e}
+#q-p{border:1px solid #000;padding:0}
+#q-p .reply{border:3px double #f9690e}
+#q-p .reply h4{padding:1px}
+#footer a{color:#f9690e}
+#content{border:3px double #f9690e}
+#content.list #header{background:#451d04}
+#content.list .row:nth-child(odd){background:#251002}
+#content.grid{border:1px solid #f9690e}
+#content.grid .row{border:1px solid #f9690e}
+#content.grid .row:hover{background:#251002;border-color:#f9690e}
+@media(max-width:720px){
+ div.msg{margin:.5em}
+ .mainpage .postform{padding:.5em}
+} \ No newline at end of file
diff --git a/static/css/txt/ayashii.css b/static/css/txt/ayashii.css
new file mode 100644
index 0000000..b7e5fc0
--- /dev/null
+++ b/static/css/txt/ayashii.css
@@ -0,0 +1,52 @@
+body{background:#004040;color:#FFF}
+a,a .name,#n2:active{color:#EFE}
+a:active,a:active .name,#n2:active{color:#F00}
+h2:before{content:"â—† "}
+h2{display:inline-block;margin:0;margin-bottom:.5em}
+h2 span{font-weight:initial;font-size:24px;margin-left:4px;display:inline-block;float:right}
+h3{margin-bottom:.5em;padding-bottom:.5em}
+h4:before{content:">";color:#FFFFFE;display:inline-block;font-size:16px;width:40px}
+.first h4:before{content:none}
+input[type=submit],input[type=button],button{border:1px outset #FFF;background:#DDD;color:#000;padding:2px 10px}
+input[type=submit]:active,input[type=button]:active,button:active{border-style:inset}
+#main_nav,.banner{background:inherit;text-align:left;padding-left:2.5%}
+#titlebox{margin-bottom:1em;margin-top:5px}
+.threadnav a{margin-left:4px}
+.innerbox{margin:0;padding:0}
+.innerbox,.mainpage .thread,.deleted,#content{margin-bottom:1em;padding-bottom:1em}
+.innerbox,.mainpage .thread,.reply,.deleted,h3,#content{border-bottom:2px groove gray}
+.links,#listmenu{text-align:left}
+#threadbox{margin-bottom:1em}
+#threadlinks{text-align:left;margin-bottom:.5em}
+#threadlist{background:#003535;border:1px inset gray}
+.reply{clear:both;margin-bottom:1em;overflow:hidden}
+.name em{color:#009}
+.quoted{font-size:9pt}
+.del a{color:#FFF}
+.first .msg{margin:1em 40px}
+.msg{margin:1em 60px}
+.q{color:#99b3b3}
+.yt{border:1px solid #FFF}
+.abbrev{margin-top:1em}
+.deleted{text-decoration:line-through}
+#q-p{background:#004040;border:1px solid #DDD}
+#q-p h4:before{display:none}
+#q-p .reply:last-child{border:0;margin-bottom:0}
+.postform,.formpad{padding-left:0}
+.size{color:#FFF;margin-top:-6px}
+form .msg{border:1px dotted #FFF}
+#footer{margin-bottom:1em;margin-top:1em;text-align:right}
+.threads .outerbox{margin-top:1em}
+#content.list #header div{background:#001e1e}
+#content.list .row:nth-child(odd){background:#003535}
+#content.grid{border-width:2px 2px 0 0}
+#content.grid .row{border-width:0 0 2px 2px}
+#content.grid,#content.grid .row{border-style:groove;border-color:gray}
+.threads #footer{text-align:center}
+@media(max-width:720px){
+ body.mainpage,body.threads{margin:8px}
+ h2 span{margin-left:0;float:none}
+ .reply{margin-bottom:.5em}
+ h4:before{font-size:12px;width:20px}
+ div.msg{margin:.5em 0 .5em 20px}
+} \ No newline at end of file
diff --git a/static/css/txt/baisano.css b/static/css/txt/baisano.css
new file mode 100644
index 0000000..82043dd
--- /dev/null
+++ b/static/css/txt/baisano.css
@@ -0,0 +1,43 @@
+body,textarea{color:#000}
+body.mainpage,body.threads{background:#c5ad99 url(../img/muro.jpg)}
+body.threadpage{background:#EFEFEF}
+a,a .name,#n2{color:#00F}
+a:active,a:active .name,#n2:active{color:#f00}
+h2{margin-bottom:3px}
+h2 a{color:#F00}
+h3{color:#F00}
+h3 span{color:#000}
+.mainpage h4:hover{background:#FFEFEF}
+h4.hidden{background:#CCC}
+.mainpage h4.hidden:hover{background:#DCC}
+#main_nav{background:#FFF}
+.outerbox{background:#CFC;border:1px outset #FFF}
+.innerbox{border:1px inset #FFF}
+#threadlist{background:#BEB;border:1px inset #FFF}
+.mainpage .thread,#content{background:#EFEFEF;border:1px outset #FFF}
+.name,.abbrev{color:green}
+.name em{color:#009}
+.del a{color:#000}
+.msg{margin:4px 40px 24px}
+a.thumb{margin-top:4px}
+.q{color:#666}
+.yt{background:#DDD;border:1px solid #AAA}
+.deleted{color:#AFAFAF;margin-bottom:24px}
+#q-p{background:#EFEFEF;border:1px solid #999}
+#q-p .msg,#q-p a.thumb{margin-bottom:8px}
+#createbox{display:flex}
+#createbox .extrabox{border:1px inset #FFF;margin:7px 0 7px 7px;float:left;width:40px;height:auto;flex:0 1 40px;-webkit-flex:0 1 40px}
+#createbox .innerbox{flex:0 1 100%;-webkit-flex:0 1 100%}
+form .msg{border:1px dotted #000;background:#EFEFEF}
+#footer{color:#333}
+#content.list{padding:7px}
+#content.list #header div{background:#CCC;border-top:1px inset #FFF}
+#content.list .row:nth-child(odd),#content.grid .row:hover{background:#FFF}
+#content.list .row div:first-child{border-left:1px inset #FFF}
+#content.list .row div:last-child{border-right:1px inset #FFF}
+#content.list .row:last-child div{border-bottom:1px inset #FFF}
+#content.grid{border:1px outset #FFF;padding:1px}
+#content.grid .row{border:1px inset #FFF;margin:1px}
+@media(max-width:720px){
+ .extrabox{display:none}
+} \ No newline at end of file
diff --git a/static/css/txt/bbs.css b/static/css/txt/bbs.css
new file mode 100644
index 0000000..0ae6041
--- /dev/null
+++ b/static/css/txt/bbs.css
@@ -0,0 +1,95 @@
+*{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;word-wrap:break-word}
+body,textarea{font-family:arial,helvetica,sans-serif;font-size:16px}
+body.mainpage,body.threads{margin:0}
+body.threadpage{margin:8px}
+h1,h5{font-size:18px;margin:0}
+h2{font-size:16px;margin:0 0 7px}
+h2 span{margin-right:2px}
+h2 a{font-size:24px;text-decoration:none}
+h3{font-size:19px;font-weight:normal;margin:8px 0}
+h4{clear:both;font-weight:normal;margin:0}
+h5{margin-bottom:8px}
+input[type="text"],textarea{background:#FFF;border:1px inset #DDD;color:#000}
+.banner{display:block;margin:0 auto}
+#rules{line-height:1.25em;margin:8px 0}
+.spoil{background:#000;color:#000}.spoil:hover{color:#fff}
+code{font-size:14px}
+pre{line-height:125%;margin:8px 0;white-space:pre-wrap}
+#main_nav .cur_brd,#cur_stl,.locked{font-weight:bold}
+#main_nav{font-size:14px;padding:4px 0;text-align:center;width:100%}
+#main_nav a,#thread_nav a,#threadlinks a,.threadlinks a,label{display:inline-block}
+.outerbox,.mainpage .thread,#footer,#content{margin-bottom:1em;margin-left:2.5%;margin-right:2.5%}
+.innerbox{padding:7px;margin:7px}
+.threadnav{float:right;font-family:mona,monapo,ipamonapgothic,monapo,'ms pgothic',yozfontaa97}
+#search input{margin-right:2px}
+#search input[type="text"]{padding:4px;max-width:500px;width:100%}
+.links{font-size:14px;text-align:center}
+#threadlinks{margin-bottom:7px;text-align:center}
+#threadlinks a{margin:0 4px}
+#threadlist{font-size:14px;line-height:1;max-height:11em;padding:7px;overflow-y:scroll}
+#threadlist a{text-decoration:none}
+#thread_nav{padding-left:6px}
+.mainpage .postform,.formpad{padding-left:40px}
+.reply{clear:both;line-height:1.25em;overflow:hidden}
+.num{color:inherit!important;font-weight:bold;text-decoration:none}
+.name em{font-style:normal}
+.del{visibility:hidden}
+.reply:hover .del{visibility:visible}
+.quoted{font-size:12px;line-height:1}
+.msg{margin:1em 40px}
+.msg hr{margin-left:0;max-width:500px}
+a.thumb{cursor:zoom-in;font-size:14px;float:left;margin:1em 20px;text-align:center;text-decoration:none;color:gray!important}
+a.yt{margin:2px 0;display:inline-block;font-size:12px;line-height:1.2em;padding:5px;text-decoration:none}
+a.yt .pvw{width:100px;height:60px;overflow:hidden;float:left;margin-right:5px}
+a.yt .pvw img{margin-top:-15px;margin-left:-10px}
+a.yt b{font-size:115%}
+.deleted{margin-bottom:1em}
+#q-p{margin-right:1em;padding:8px 8px 0;position:absolute}
+#q-p .del,#q-p .quoted,#q-p .thumb div{display:none}
+.size{color:#f00;font-family:arial,sans-serif;font-weight:bold;margin-bottom:8px}
+.lastposts{text-align:center;line-height:1}
+.lastposts #n2{text-decoration:underline}
+.threadpage .threadlinks{margin:8px 0}
+#createbox input,#createbox textarea{width:100%}
+.pblock{text-align:right;white-space:nowrap}
+form .msg{margin:0;padding:8px 2px;text-align:left}
+.end,#search{margin-top:8px}
+.warn{padding:1px}
+.stop{padding:1em 1px}
+.yellow{background:#ff0;color:#000}
+.red{background:#f00;color:#fff}
+#listmenu{margin-top:7px;text-align:center}
+#content a{text-decoration:none}
+#content a:hover{text-decoration:underline}
+#content.list a{display:block;line-height:1}
+#content.list .row{display:table-row}
+#content.list .row div{display:table-cell;padding:5px}
+#content.list .row div.thread{padding:0}#content.list .row div.thread a{padding:5px}
+#content.list .pos,#content.list .com{text-align:right}
+#content.list #header div{font-weight:bold;text-align:center;white-space:nowrap}
+#content.grid{display:flex;flex-flow:row wrap;justify-content:space-around}
+#content.grid .row{flex:1 1 auto;padding:5px}
+#content.grid .row div{display:inline}
+@media(min-height:999px){#threadlist{max-height:16em}}
+@media(max-width:720px){
+ body{font-size:15px}
+ .banner{width:100%!important;height:auto!important;margin-top:1em}
+ .outerbox,.mainpage .thread,#footer,#content{margin:1em 0}
+ br{line-height:.5em}
+ h2 a{font-size:19px}
+ h4,h2 span,#rules{font-size:12px}
+ .pblock,#footer,.end{font-size:14px}
+ #threadlist{overflow-x:auto;white-space:nowrap}
+ .size,.postform br{display:none}
+ .num{margin:-10px;padding:10px;position:relative}
+ .del{visibility:visible}
+ div.msg{margin:.5em 0}
+ .mainpage .postform,.formpad,#thread_nav{padding-left:0}
+ .postform>span{display:table;width:100%}
+ .postform span>*{display:table-cell;font-size:14px;margin-bottom:2px;white-space:nowrap}
+ .postform input,textarea{width:100%}
+ .postform textarea{height:100px}
+ form,#thread_nav,#footer,.end,.locked{text-align:center}
+ #footer a{display:block}
+ #content.list .row div{padding:0 2px}
+} \ No newline at end of file
diff --git a/static/css/txt/bios.css b/static/css/txt/bios.css
new file mode 100644
index 0000000..41e7f38
--- /dev/null
+++ b/static/css/txt/bios.css
@@ -0,0 +1,51 @@
+body,textarea,.lastposts #counter{background:#00a;color:#fff}
+a,a .name,.lastposts #n2{color:#ff0;text-decoration:none}
+a:focus,a:active,a:active .name,#n2:active{background:#f00;color:#fff}
+.mainpage .threadlinks a:before,#threadlinks a:before,.lastposts a:before,.lastposts label:before{content:'â–¶ '}
+input[type="text"],textarea{background:#00a;border:1px solid #fff;color:#fff}
+input[type="submit"],input[type="button"],button{background:#fff;border:0;color:#000;padding:3px 11px}
+input[type="submit"]:active,input[type="button"]:active,button:active{background:#000;color:#fff}
+::selection{background:#fff;color:#000}
+::-moz-selection{background:#fff;color:#000}
+hr{display:none}
+h2,.thread .threadnav{margin:.75em}
+h3{background:#fff;color:#00a;margin:0;padding:2px 8px}
+h3 span{background:#00a;color:#fff;padding:2px}
+#main_nav,#thread_nav{background:linear-gradient(270deg, #0000ff, #000000, #0000ff);background-position:0% 50%;-webkit-animation:bios 6s linear infinite;-moz-animation:bios 6s linear infinite;animation:bios 6s linear infinite;background-size:500% 500%}
+@-webkit-keyframes bios{0%{background-position:0% 0%}50%{background-position:250% 0%}100%{background-position:500% 0%}}
+@-moz-keyframes bios{0%{background-position:0% 0%}50%{background-position:250% 0%}100%{background-position:500% 0%}}
+@keyframes bios{0%{background-position:0% 0%}50%{background-position:250% 0%}100%{background-position:500% 0%}}
+#main_nav a,#thread_nav a,.threadpage .threadlinks a{color:#fff;text-decoration:underline}
+#main_nav .cur_brd{background:#fff;color:#00a;padding:1px;text-decoration:none}
+#thread_nav{margin:-8px -8px 8px;padding:6px 16px}
+.innerbox{border:1px solid #fff;margin:3px;padding:.75em}
+.innerbox.links{border-top:0;margin-top:-3px}
+#cur_stl{background:#ff0;color:#00a}
+.outerbox,.mainpage .thread,#threadlist,#content{border:1px solid #fff}
+.thread .innerbox{padding:0}
+.threadpage .thread{border-color:#fff;border-style:double;border-width:4px 4px 1px}
+.reply{border-top:1px solid #FFF;padding:.5em .75em 0}
+.threadpage .reply{padding:.5em .5em 0}
+.name em{background:#fff;color:#00f}
+.q,.deleted,.abbrev{color:#5cf;margin-bottom:24px}
+.size{margin-left:.5em}
+.yt{border:1px solid #ff0}
+.yt:active{background:#f00;border:1px solid #f00;color:#fff}
+#q-p{background:#00a;border:1px solid #fff}
+#q-p .msg,#q-p a.thumb{margin-bottom:8px}
+.lastposts{border-color:#fff;border-style:double;border-width:0 4px;color:#00a;padding:.5em}
+.mainpage .threadlinks{margin-top:.75em}
+.threadpage .threadlinks{margin-top:0}
+.threadpage .postform{border-color:#fff;border-style:double;border-width:1px 4px 4px;padding:.5em}
+.formpad{padding-left:0}
+.mainpage .postform{border-top:1px solid #fff;padding:.75em}
+form .msg{border:3px double #fff}
+#content.list{border:4px double #fff}
+#content.list #header div{border-bottom:1px solid #fff}
+#content.grid{border:1px solid #fff;padding:2px}
+#content.grid .row{border:1px solid #fff;margin:2px}
+@media(max-width:720px){
+ body.threadpage{margin:8px 0}
+ h2{margin-bottom:.5em}
+ #thread_nav{margin:-8px 0px 8px}
+} \ No newline at end of file
diff --git a/static/css/txt/blue moon.css b/static/css/txt/blue moon.css
new file mode 100644
index 0000000..271fe9a
--- /dev/null
+++ b/static/css/txt/blue moon.css
@@ -0,0 +1,61 @@
+body.threadpage{margin-top:0}
+body{background:#6B7B8D;color:#FFF}
+a,#n2:active,h3 span{color:#AFB9C5}
+a:active,form a:active,#n2:active{color:#EEE}
+#main_nav a,.reply a,form a,#q-p a,.row a{color:#49525D}
+#main_nav a:active,.reply a:active,#q-p a:active,a:active .name,.row a:active{color:#8C9FB4}
+h2{color:#EEE;line-height:1;margin:0 0 10px}
+h2 a{color:#EEE}
+h3{color:#EEE;margin:0.7em 0}
+h4{background:#DDD;padding-bottom:5px}
+hr{display:none}
+input[type=text],textarea{background:#EEE;border:1px inset #444}
+input[type=submit],input[type=button],button{background:#000;color:#FFF;border:1px outset #444;padding:2px 10px}
+input[type=submit]:active,input[type=button]:active,button:active{border-style:inset}
+#main_nav{background:#FFF;color:#6B7B8D}
+#titlebox .innerbox:first-child{margin-bottom:5px}
+.outerbox{background:#49525D;padding:5px}
+.innerbox{margin:0;padding:10px}
+.links{padding-top:5px}
+#threadbox{margin-bottom:19px;margin-top:19px}
+#threadlist{background:#3e4247;border:1px inset #B6C2CF}
+.mainpage .thread{background:#49525D}
+.threadpage .thread{background:#49525D;padding:1px 10px}
+#thread_nav{background:#49525D;margin-bottom:2px;padding:7px 10px}
+.postform,#createbox form,h5{background:#8C9FB4;color:#49525D;padding:10px}
+h5{margin:0;padding-bottom:0}
+.mainpage .postform{margin-top:10px}
+.reply{background:#FFF;border-top:3px solid #DDD;border-right:10px solid #DDD;border-bottom:3px solid #DDD;border-left:10px solid #DDD;color:#000}
+.first{border-top:6px solid #DDD}
+.name,a .name{color:#2B3037}
+.name em{color:#009}
+.del a{color:#000}
+.msg,a.thumb{background:#FFF;color:#000080;margin:10px}
+.msg hr{display:block}
+.abbrev a{color:#000080}
+.abbrev,.q{color:#697685}
+.threadpage .postform{margin-top:2px;border:10px solid #49525D}
+.yt{background:#EEE;border:1px solid gray}
+.deleted{background:#DDD;color:#AFAFAF;margin-bottom:0;padding:3px 10px}
+#q-p{background:#FFF;color:#000;border:1px solid #49525D;padding:0}
+form .msg{border:1px inset #DDD;margin:0;padding:.5em 0.15em}
+.size{color:#8C9FB4;margin:5px 0}
+.lastposts{background:#49525D;color:#AFB9C5;margin-top:2px;padding:.5em}
+.threadpage .threadlinks{margin:0}
+.warn,.stop{padding-left:10px;margin:2px 0}
+#footer a{color:#FFF}
+#content{background:#FFF;border:10px solid #49525D;color:#000080}
+#content.list #header div{background:#2c2c32;color:#EEE}
+#content.list .row:nth-child(odd),#content.grid .row:hover{background:#E7E7FF}
+#content.grid .row{border:1px solid #DDD}
+@media(max-width:720px){
+ body.threadpage{margin:0 0 8px}
+ .innerbox,.postform,#createbox form,h5{padding:6px;padding-left:6px}
+ h2{margin-bottom:6px}
+ .threadpage .thread{padding:1px 6px 6px}
+ .mainpage .postform{margin-top:6px;padding-left:6px}
+ .reply{border-left-width:6px;border-right-width:6px}
+ .threadpage .postform{border-width:6px}
+ .msg,a.thumb{margin:6px}
+ .thread form{margin-top:6px}
+} \ No newline at end of file
diff --git a/static/css/txt/ciber.css b/static/css/txt/ciber.css
new file mode 100644
index 0000000..45fce17
--- /dev/null
+++ b/static/css/txt/ciber.css
@@ -0,0 +1,55 @@
+body{background:#000 url('../img/cyb.png');text-shadow:1px 1px #000}
+body,h3{color:#BA55D3}
+a,h2 a,#n2{color:#DB43B5}
+a:active,#n2:active{color:#F0F}
+h4{background:#2A4A75;padding:0 7px;text-shadow:0 2px #000}
+.threadpage h4{padding:0 3px}
+h4,h4 a,.name,.name a{color:#9370DB}
+h1,h2 a,h3,h5{text-shadow:1px 1px #000,0 0 10px}
+h1:after,h2 a:after,h3:after{content:"_";animation:blink 1s infinite}@keyframes blink{from,to{opacity:0}50%{opacity:1}}
+h2,.thread .threadnav{margin:7px}
+h3{margin:8px 0}
+h3 span,.size,.abbrev{color:#639}
+hr{background:#2A4A75;border:0;height:1px;box-shadow:0 0 10px #2A4A75}
+.spoil{background:#2A4A75;color:#2A4A75;text-shadow:none}.spoil:hover{color:#000}
+input[type=submit],input[type=button],button{padding:2px 10px}
+input:active,input:focus,textarea:active,textarea:focus,button:active,button:active{box-shadow:0 0 15px}
+.outerbox input,.outerbox textarea{background:#002f00;border:1px solid #68F855;color:#68F855}
+.outerbox input[type=submit],.outerbox input[type=button],.outerbox button{background:#0F0;border:3px outset #0F0;color:#000}
+.outerbox input[type=submit]:active,.outerbox input[type=button]:active,.outerbox button:active{background:#0C0;border-style:inset}
+.threadpage input,.threadpage textarea,.thread input,.thread textarea{background:#000;border:1px solid #2A4A75;color:#2A4A75;text-shadow:1px 1px #000}
+.threadpage input[type=submit]:active,.threadpage input[type=button]:active,.thread input[type=submit]:active,.thread input[type=button]:active{border-color:#d21cea;color:#d21cea}
+#main_nav{background:#000;box-shadow:0 0 10px #68F855}
+.outerbox{background:#111;color:#5FE44E;border:3px outset #0F0;background:#0C0}
+.outerbox a,#main_nav a,#footer a{color:#68F855}
+.outerbox a:active,#main_nav a:active,#footer a:active{color:#ef6177}
+#threadlist{background:rgba(26,26,26,.5);border:3px solid #0C0}
+.innerbox{border:3px inset #0F0}
+.outerbox .innerbox{background:#000 url('../img/green.gif')}
+.mainpage .thread,.thread .innerbox{border:1px solid #2A4A75}
+.mainpage .thread{background:#2A4A75;box-shadow:0 0 5px 5px #2A4A75}
+.thread .innerbox,.threadpage,#q-p,form .msg{background:#000 url(' data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAIAAAAW4yFwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAAWSURBVHjaYrDk0GLm/88FAAAA//8DAATaAYeGqOFRAAAAAElFTkSuQmCC')}
+.thread .innerbox{padding:0}
+.name em{color:#4B0082}
+.q{color:#9932CC}
+.deleted{background:none;border-color:#2A4A75;border-style:solid;border-width:1px 0;color:inherit}
+.yt{background:#000;border:1px solid #2A4A75}
+.mainpage .postform{border-top:1px solid #2A4A75;padding:1em 0 1em 40px}
+.formpad{padding:0}
+form .msg{border:1px dotted #2A4A75;color:#2A4A75}
+#q-p{border:1px solid #000;padding:0}
+#q-p .reply{border:3px double #2A4A75}
+#q-p .reply h4{padding:1px}
+#footer{color:#0C0;text-shadow:0 0 5px #0F0}
+#footer a{color:#989898}
+#content{background:#000;border:3px double #d500fb;color:#39c8df}#content a{color:#d500fb}
+#content.list #header{text-shadow:0 0 5px}
+#content.list .row:nth-child(odd){background:#200020}
+#content.grid{border:2px solid #141937}
+#content.grid .row{border:2px solid #141937}
+#content.grid .row:hover{background:#27151D;border-color:#9B1937}
+#content .row:hover a{text-shadow:0 0 5px}
+@media(max-width:720px){
+ div.msg{margin:.5em}
+ .mainpage .postform{padding:.5em}
+} \ No newline at end of file
diff --git a/static/css/txt/futanari.css b/static/css/txt/futanari.css
new file mode 100644
index 0000000..2606f03
--- /dev/null
+++ b/static/css/txt/futanari.css
@@ -0,0 +1,49 @@
+body{background:#13334c;color:#edf9fc}
+body.threadpage,body.threads{margin-top:0}
+a,a .name,#n2{color:#efd279}
+a:active,a:active .name,#n2:active{color:#d00}
+h1{background:#5b8bb4;margin:-10px -10px 10px;padding:10px}
+h2 span{color:#aaa;margin-right:2px}
+h2 a,h2 a:active{color:#de9d7f;text-decoration:none}
+h3{color:#de9d7f;margin:0.7em 0}
+h3 span{color:#909090}
+hr{display:none}
+input,input[type="text"],textarea,button{border:1px solid #3b6b94}
+input[type=submit],input[type=button],button{background:#aaf;color:#2c5700;padding:2px 10px}
+input[type="submit"]:active,input[type="button"]:active,button:active{background:#88c}
+#main_nav{background:#1d7548}
+#titlebox{margin-bottom:0}
+.outerbox{background:#3b6b94}
+.innerbox{margin:0;padding:10px}
+.links{background:#5b8bb4}
+#threadlist{background:#154a72;border:1px inset #1b3345}
+.mainpage .thread{padding:5px}
+#thread_nav{background:#1d7548;padding:6px}
+.name{color:#afd775}
+.name em{color:#009}
+.del a{color:#fff}
+.msg{margin:4px 40px 24px}
+.q{color:#aac}
+.yt{background:#2f587a;border:1px solid #1b2933}
+.msg hr{display:block}
+.deleted{color:#afafaf;margin-bottom:24px}
+.abbrev{color:#bbb}
+.size{color:#de9d7f}
+.postform,#createbox,.threads .outerbox,#content{border-right:2px solid #5b8bb4;border-bottom:2px solid #5b8bb4;background:#3b6b94}
+.postform{padding:10px}
+.threadpage .threadlinks{margin:0 0 3px}
+form .msg{border:1px dashed #000;background:#1b3345}
+#q-p{background:#1b3345;border:1px solid #3b6b94}
+#q-p .msg,#q-p a.thumb{margin-bottom:8px}
+.lastposts{background:#5b8bb4;padding:8px}
+#content{padding:0 10px 10px}
+#content.list #header div{background:#3b6b94}
+#content.list .row:nth-child(odd){background:#1b3345}
+#content.list .row:nth-child(even){background:#294b68}
+#content.grid{border:0;padding:0}
+#content.grid .row{border-width:0 2px 2px 0;border-style:solid;border-color:#5b8bb4}
+#content.grid .row:hover{background:#154a72}
+@media(max-width:720px){
+ .mainpage .thread{padding:0}
+ .innerbox,.postform,.mainpage .postform{padding:8px;padding-left:8px}
+} \ No newline at end of file
diff --git a/static/css/txt/headline.css b/static/css/txt/headline.css
new file mode 100644
index 0000000..8fb085b
--- /dev/null
+++ b/static/css/txt/headline.css
@@ -0,0 +1,41 @@
+body,#main_nav{background:#FFF}
+body,textarea{color:#000}
+a,#n2,h3 span{color:#D60}
+a:active .name,h2 a:active,h4 a:active,a:active,#n2:active{color:#FA4}
+h2 a,.del a,.name,h4 a,h4{color:#000}
+h1{border-bottom:2px solid #F70;padding:0 10px;margin:0 -10px 10px}
+h2,h3{background:#EEE;border-bottom:2px solid #F70;display:inline-block;padding:2px 3px}
+h3{margin:0.7em 0}
+h4{background:#EEE;border-bottom:1px solid #BBB;padding:0 3px}
+hr{display:none}
+input,input[type="text"],textarea,button{border:1px solid #000}
+input[type="submit"],input[type="button"],button{background:#DDD;padding:2px 10px}
+input[type="submit"]:active,input[type="button"]:active,button:active{background:#CCC}
+.outerbox,#titlebox .innerbox:first-child,.postform,.lastposts,#content{background:#EEE;border-bottom:2px solid #BBB}
+.innerbox{margin:0;padding:10px}
+#threadlist{background:#fff;border:1px inset #bbb}
+.mainpage .thread{padding:5px}
+#thread_nav{border-bottom:2px solid #F70;padding:0 0 6px 6px}
+.mainpage .first div.msg::first-letter{font-size:1.5em;text-transform:uppercase}
+.name em{color:#009;font-style:normal}
+.q,.abbrev{color:#7f7f7f}
+.yt{background:#f2f2f2;border:1px solid #bbb}
+.msg hr{display:block;max-width:500px;margin-left:0}
+.deleted{color:#AFAFAF}
+#q-p{background:#FFF;border:1px solid #BBB;border-bottom:2px solid #BBB}
+.lastposts{padding:8px}
+.size{color:#D60}
+.threadpage .threadlinks{margin:0 0 3px}
+.postform{padding:10px}
+form .msg{border:1px dashed #000;background:#FFF;margin:0;padding:.5em 0.15em}
+#content{padding:0 10px 10px}
+#content.list #header div{background:#EEE}
+#content.list .row:nth-child(odd){background:#FFF}
+#content.list .row:nth-child(even){background:#DDD}
+#content.grid{border:1px solid #BBB;padding:0}
+#content.grid .row{border:1px solid #BBB}
+#content.grid .row:hover{background:#DDD}
+@media(max-width:720px){
+ .mainpage .thread{padding:0}
+ .innerbox,.postform,.mainpage .postform{padding:8px;padding-left:8px}
+} \ No newline at end of file
diff --git a/static/css/txt/postal.css b/static/css/txt/postal.css
new file mode 100644
index 0000000..d91b523
--- /dev/null
+++ b/static/css/txt/postal.css
@@ -0,0 +1,47 @@
+body,textarea{color:#000}
+body{background:#E5B98D}
+a,a .name,#n2{color:#3683C2}
+a:active,a:active .name,#n2:active{color:#E9976B}
+input[type="text"],textarea{border:1px solid #CCC}
+input[type="submit"],input[type="button"],button{background:#CBCBCB;border:0;padding:3px 10px}
+input[type="submit"]:active,input[type="button"]:active,button:active{background:#B1B1B1}
+body>hr{position:absolute;top:0;left:8px;right:8px;border:0;background-image:repeating-linear-gradient(125deg,#EE4C47 0px,#EE4C47 30px,#FFF 30px,#FFF 50px,#5CACEB 50px,#5CACEB 80px,#FFF 80px,#FFF 100px);height:1em}
+hr,.threadpage .thread{background-image:repeating-linear-gradient(125deg,#EE4C47 0px,#EE4C47 30px,#FFF 30px,#FFF 50px,#5CACEB 50px,#5CACEB 80px,#FFF 80px,#FFF 100px)}
+h2 span{color:#686868}
+h2 a,h2 a:active,h3{color:#3E3020}
+h2 a:active{text-decoration:underline}
+h3{margin-top:0}
+h3 span{color:dimgrey}
+h4{background:#F0E7CE;color:#686868;padding-left:3px}
+#main_nav,.outerbox{background:#FFF}
+.outerbox{border:1px solid #FFF}
+#threadlist{background:#EFEFEF;border:1px inset #EFEFEF}
+.thread .innerbox{background:#FFF;box-shadow:1px 1px 0 rgba(0,0,0,0.1),3px 3px 0 rgba(255,255,255,1),4px 4px 0 rgba(0,0,0,0.125),6px 6px 0 rgba(255,255,255,1),7px 7px 0 rgba(0,0,0,0.15),9px 9px 0 rgba(255,255,255,1),10px 10px 0 rgba(0,0,0,0.175),12px 12px 0 rgba(255,255,255,1),13px 13px 0 rgba(0,0,0,0.175);margin:8px 12px 8px 0;padding:8px}
+#thread_nav{background:#FFF;font-style:italic;padding:1.5em 8px .5em}
+.threadpage .thread{background-color:#FFF;background-position:bottom;background-repeat:repeat-x;background-size:100% 1em;overflow:hidden;padding:0 10px 1.5em}
+.innerbox.links {border-top:2px solid #E5B98D;margin:-1px;padding:12px}
+.name,.abbrev{color:#416D91}
+.name em{color:#009}
+.del a{color:#000}
+.q{color:#666;display:inline-block}
+.q:hover{background:#F0F0E0}
+.yt{background:#EEE;border:1px solid #CCC}
+.deleted{background:##F7F3E6;color:#AAA}
+#q-p{background:#FFF;border:1px solid #CCC}
+#createbox{background:#F0E7CE;border-color:#F0E7CE;color:#353535}
+.lastposts,.threadpage .postform{margin-top:.5em;padding:.5em}
+.lastposts,.threadpage .postform,.threads .outerbox,#content.list,#content.grid .row{background:#FFF;-webkit-box-shadow:0 0 10px rgba(0,0,0,0.3);-moz-box-shadow:0 0 10px rgba(0,0,0,0.3);box-shadow:0 0 10px rgba(0,0,0,0.3)}
+.threadpage .threadlinks{margin-top:0}
+.size{margin-bottom:0}
+form .msg{border:1px dotted #CCC;background:#FFF}
+#footer{color:#333}
+#content.list{padding:8px}
+#content.list #header div{background:#6AA9D7}
+#content.list .row:hover,#content.grid .row:hover{background:#B7D2E8}
+#content.list .row a:hover,#content.grid .row:hover a{color:#0801BF}
+#content.grid .row{margin:4px}
+@media(max-width:720px){
+ body.threadpage{margin:0 0 8px}
+ body>hr{top:-8px;left:0;right:0}
+ #createbox .innerbox{padding:0}
+} \ No newline at end of file
diff --git a/static/css/txt/sjis.css b/static/css/txt/sjis.css
new file mode 100644
index 0000000..018c6db
--- /dev/null
+++ b/static/css/txt/sjis.css
@@ -0,0 +1 @@
+body,textarea{font-family:Mona,Monapo,IPAMonaPGothic,'MS PGothic',YOzFontAA97}textarea{font-size:16px}
diff --git a/static/css/txt/ventanas.css b/static/css/txt/ventanas.css
new file mode 100644
index 0000000..cddee34
--- /dev/null
+++ b/static/css/txt/ventanas.css
@@ -0,0 +1,48 @@
+body,textarea{color:#000}
+body.mainpage,body.threads{background:#008081}
+body.threadpage,.outerbox,.mainpage .thread,#q-p{background:#C0C0C0}
+::selection{background:blue;color:white}::-moz-selection{background:blue;color:white}
+a,a .name,#n2{color:#00F}
+a:active,a:active .name,#n2:active{color:#f00}
+input[type=submit],input[type=button],button{border-width:2px;border-color:#FFF #000 #000 #FFF;border-style:ridge;background:#C0C0C0;color:#000;padding:2px 10px}
+h1,h2,#threadlinks:before,h5{background:#010081;color:#FFF;font-size:21px;font-weight:bold;margin:-11px -11px 11px;padding:2px}
+h2 a,h2 a:active{color:#FFF}
+h3 span{color:#555;text-decoration:underline}
+hr{border:0}
+hr,.reply,.deleted{border-bottom:2px groove white}
+#main_nav{background:#C0C0C0;border-bottom:2px ridge white;line-height:1;padding:2px 0}
+.threadnav{line-height:1;margin:-11px}
+#main_nav a,.threadnav a{background:#C0C0C0;border-width:2px;border-color:#FFF #000 #000 #FFF;border-style:ridge;color:#000;display:inline-block;margin:0 -1px;padding:2px;text-decoration:none;outline-offset:-4px}
+.threadnav a{margin:2px;padding:0}
+#main_nav a:first-child{font-weight:bold}
+#main_nav .cur_brd{background:#BBB url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAHUlEQVQImQESAO3/AMG/wv////7/AP///v++vr7/gXcOcY36q6gAAAAASUVORK5CYII=');font-weight:bold}
+#main_nav .cur_brd,#main_nav a:active,.threadnav a:active,input[type=submit]:active,input[type=button]:active,button:active{border-color:#000 #FFF #FFF #000}
+.outerbox,.mainpage .thread,#q-p{border-width:2px;border-color:#FFF #000 #000 #FFF;border-style:groove}
+input[type=text],textarea,.innerbox,#content,#threadlist{border-width:2px;border-color:#000 #FFF #FFF #000;border-style:groove}
+#threadlinks:before{content:"";display:block;height:15px;margin-bottom:5px}
+.innerbox{padding:10px;margin:2px}
+.links{border:1px solid;border-color:#888 #dadada #dadada #888;padding:2px}
+#threadlist{background:#FFF}
+#threadlist a{color:#000}
+#thread_nav a{color:#000;display:inline-block;margin:-3px -2px;padding:3px}#thread_nav a:hover{background:#DDD}
+.reply,.deleted{margin-bottom:.5em}
+.name,.abbrev{color:#444}
+.name em{color:#009}
+.del a{color:#000}
+.q{color:#666}
+.yt{background:#FFF;border:1px inset #aaa;color:#000}
+.deleted{color:gray;padding-bottom:.5em}
+#q-p{box-shadow:5px 5px #000;padding:0}
+#q-p .reply{padding:.5em;margin-bottom:0}
+#q-p a.thumb,#q-p .msg{margin-bottom:.5em}
+.postform,.formpad{padding:0}
+form .msg{background:#FFFFE0;border:1px solid #000}
+#footer{color:#FFF}
+#listmenu h1{background:none;color:#000;margin:0;padding:0}
+#content{background:#FFF}
+#content.list #header div{background:#CCC}
+#content.list .row div,#content.grid .row{border-width:0 1px 1px 0;border-style:solid;border-color:#000}
+#content .row:hover{background:#EEE}
+@media(max-width:720px){
+ #createbox form{margin:-10px}
+} \ No newline at end of file
diff --git a/static/css/vndb.css b/static/css/vndb.css
new file mode 100644
index 0000000..43a9c7c
--- /dev/null
+++ b/static/css/vndb.css
@@ -0,0 +1,30 @@
+html,body{background-attachment:scroll,fixed;background-color:#000;background-image:url('img/vndb1.jpg'),url('img/vndb2.jpg');background-position:left top,right top;background-repeat:no-repeat,no-repeat;color:#DDD;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif}
+.rep{color:#DDD}
+a,a .name,.nav label{color:#77BBDD}
+a:hover,a:hover .name,.nav label:hover{border-bottom:1px dotted #DDD;text-decoration:none}
+#catalog .thread > a:hover{border-bottom:none;text-decoration:underline}
+.logo{color:#135;font-style:italic}
+.replymode,.extramode{color:#FFF}
+.replymode{background:#258}
+.extramode{background:#247}
+.postblock{border:1px solid #258;background:rgba(7,28,47,0.75)}
+input,input[type="text"],input[type="password"],textarea{background:#0d2741;border:1px solid #35A;color:#DDD}
+input[type="submit"]{background:rgba(7,28,47,0.9);padding:3px 10px}
+input[type="submit"]:active{background:#0d2741}
+.fs{text-decoration:none}
+.subj{color:#7bd;font-weight:bold}
+.ell,.name,.omitted{color:#258}
+.q{border-left:1px dotted #258;color:#336da7}
+.reply,#q-p{background:rgba(7,28,47,0.8);border:1px solid #258}
+.abbrev{color:#707070}
+.highlight{background:rgb(10,35,60)}
+.managertable{border:1px solid #258}
+.managertable td{background:rgba(7,28,47,0.5)}
+.managertable th{background:rgba(7,28,47,0.9)}
+hr{border:none;border-top:1px solid #258;height:0}
+#catalog .thread:hover{background:rgba(7,28,47,0.92);box-shadow:0 0 5px 5px rgba(7,28,47,0.9)}
+#catalog .replies{color:#258;font-weight:bold}
+.yt,.yt:hover{background:#0d2741;border:1px solid #258;color:#DDD}
+.pg,.pg td{background:rgba(7,28,47,0.8);border:1px solid #258}
+.footer,.footer a{color:#247}
+.quoted{border-color:#35A;color:#247} \ No newline at end of file
diff --git a/static/ico/1372836.gif b/static/ico/1372836.gif
new file mode 100644
index 0000000..9ebe25b
--- /dev/null
+++ b/static/ico/1372836.gif
Binary files differ
diff --git a/static/ico/1k.gif b/static/ico/1k.gif
new file mode 100644
index 0000000..95847ec
--- /dev/null
+++ b/static/ico/1k.gif
Binary files differ
diff --git a/static/ico/2-1.gif b/static/ico/2-1.gif
new file mode 100644
index 0000000..a7f2b98
--- /dev/null
+++ b/static/ico/2-1.gif
Binary files differ
diff --git a/static/ico/2ppa.gif b/static/ico/2ppa.gif
new file mode 100644
index 0000000..23088ea
--- /dev/null
+++ b/static/ico/2ppa.gif
Binary files differ
diff --git a/static/ico/2syobo_2.gif b/static/ico/2syobo_2.gif
new file mode 100644
index 0000000..d54d613
--- /dev/null
+++ b/static/ico/2syobo_2.gif
Binary files differ
diff --git a/static/ico/3-2.gif b/static/ico/3-2.gif
new file mode 100644
index 0000000..c0aff5a
--- /dev/null
+++ b/static/ico/3-2.gif
Binary files differ
diff --git a/static/ico/3.gif b/static/ico/3.gif
new file mode 100644
index 0000000..fb65b6d
--- /dev/null
+++ b/static/ico/3.gif
Binary files differ
diff --git a/static/ico/3na.gif b/static/ico/3na.gif
new file mode 100644
index 0000000..2c30e0c
--- /dev/null
+++ b/static/ico/3na.gif
Binary files differ
diff --git a/static/ico/4-2.gif b/static/ico/4-2.gif
new file mode 100644
index 0000000..0d43898
--- /dev/null
+++ b/static/ico/4-2.gif
Binary files differ
diff --git a/static/ico/4248688.gif b/static/ico/4248688.gif
new file mode 100644
index 0000000..ef629f0
--- /dev/null
+++ b/static/ico/4248688.gif
Binary files differ
diff --git a/static/ico/5007629.gif b/static/ico/5007629.gif
new file mode 100644
index 0000000..9fa6a22
--- /dev/null
+++ b/static/ico/5007629.gif
Binary files differ
diff --git a/static/ico/5296219.gif b/static/ico/5296219.gif
new file mode 100644
index 0000000..a77351d
--- /dev/null
+++ b/static/ico/5296219.gif
Binary files differ
diff --git a/static/ico/5ta.gif b/static/ico/5ta.gif
new file mode 100644
index 0000000..04800b1
--- /dev/null
+++ b/static/ico/5ta.gif
Binary files differ
diff --git a/static/ico/6396408.gif b/static/ico/6396408.gif
new file mode 100644
index 0000000..ba33fc2
--- /dev/null
+++ b/static/ico/6396408.gif
Binary files differ
diff --git a/static/ico/6za.gif b/static/ico/6za.gif
new file mode 100644
index 0000000..bd4a945
--- /dev/null
+++ b/static/ico/6za.gif
Binary files differ
diff --git a/static/ico/8028885.gif b/static/ico/8028885.gif
new file mode 100644
index 0000000..cca1680
--- /dev/null
+++ b/static/ico/8028885.gif
Binary files differ
diff --git a/static/ico/8toushinnomonar16.gif b/static/ico/8toushinnomonar16.gif
new file mode 100644
index 0000000..e4ac044
--- /dev/null
+++ b/static/ico/8toushinnomonar16.gif
Binary files differ
diff --git a/static/ico/8toushinnomonar32.gif b/static/ico/8toushinnomonar32.gif
new file mode 100644
index 0000000..4c31836
--- /dev/null
+++ b/static/ico/8toushinnomonar32.gif
Binary files differ
diff --git a/static/ico/ace.gif b/static/ico/ace.gif
new file mode 100644
index 0000000..f521c7e
--- /dev/null
+++ b/static/ico/ace.gif
Binary files differ
diff --git a/static/ico/af1.gif b/static/ico/af1.gif
new file mode 100644
index 0000000..e88e02b
--- /dev/null
+++ b/static/ico/af1.gif
Binary files differ
diff --git a/static/ico/af2.gif b/static/ico/af2.gif
new file mode 100644
index 0000000..fe46aa6
--- /dev/null
+++ b/static/ico/af2.gif
Binary files differ
diff --git a/static/ico/ahya_xmas_2.gif b/static/ico/ahya_xmas_2.gif
new file mode 100644
index 0000000..6c0aebc
--- /dev/null
+++ b/static/ico/ahya_xmas_2.gif
Binary files differ
diff --git a/static/ico/aka.gif b/static/ico/aka.gif
new file mode 100644
index 0000000..c22596b
--- /dev/null
+++ b/static/ico/aka.gif
Binary files differ
diff --git a/static/ico/ame.gif b/static/ico/ame.gif
new file mode 100644
index 0000000..08dca67
--- /dev/null
+++ b/static/ico/ame.gif
Binary files differ
diff --git a/static/ico/anime_buun02.gif b/static/ico/anime_buun02.gif
new file mode 100644
index 0000000..c3422f2
--- /dev/null
+++ b/static/ico/anime_buun02.gif
Binary files differ
diff --git a/static/ico/anime_charhan01.gif b/static/ico/anime_charhan01.gif
new file mode 100644
index 0000000..cb04d65
--- /dev/null
+++ b/static/ico/anime_charhan01.gif
Binary files differ
diff --git a/static/ico/anime_charhan02.gif b/static/ico/anime_charhan02.gif
new file mode 100644
index 0000000..92eb054
--- /dev/null
+++ b/static/ico/anime_charhan02.gif
Binary files differ
diff --git a/static/ico/anime_giko01.gif b/static/ico/anime_giko01.gif
new file mode 100644
index 0000000..d4a6f84
--- /dev/null
+++ b/static/ico/anime_giko01.gif
Binary files differ
diff --git a/static/ico/anime_giko04.gif b/static/ico/anime_giko04.gif
new file mode 100644
index 0000000..bab9e77
--- /dev/null
+++ b/static/ico/anime_giko04.gif
Binary files differ
diff --git a/static/ico/anime_giko10.gif b/static/ico/anime_giko10.gif
new file mode 100644
index 0000000..c9db6cc
--- /dev/null
+++ b/static/ico/anime_giko10.gif
Binary files differ
diff --git a/static/ico/anime_giko11.gif b/static/ico/anime_giko11.gif
new file mode 100644
index 0000000..80af838
--- /dev/null
+++ b/static/ico/anime_giko11.gif
Binary files differ
diff --git a/static/ico/anime_giko12.gif b/static/ico/anime_giko12.gif
new file mode 100644
index 0000000..201d60c
--- /dev/null
+++ b/static/ico/anime_giko12.gif
Binary files differ
diff --git a/static/ico/anime_giko13.gif b/static/ico/anime_giko13.gif
new file mode 100644
index 0000000..446bed8
--- /dev/null
+++ b/static/ico/anime_giko13.gif
Binary files differ
diff --git a/static/ico/anime_hossyu01.gif b/static/ico/anime_hossyu01.gif
new file mode 100644
index 0000000..66be979
--- /dev/null
+++ b/static/ico/anime_hossyu01.gif
Binary files differ
diff --git a/static/ico/anime_imanouchi01.gif b/static/ico/anime_imanouchi01.gif
new file mode 100644
index 0000000..d3eacf5
--- /dev/null
+++ b/static/ico/anime_imanouchi01.gif
Binary files differ
diff --git a/static/ico/anime_iyou02.gif b/static/ico/anime_iyou02.gif
new file mode 100644
index 0000000..1f3216c
--- /dev/null
+++ b/static/ico/anime_iyou02.gif
Binary files differ
diff --git a/static/ico/anime_jien01.gif b/static/ico/anime_jien01.gif
new file mode 100644
index 0000000..bd2d8ed
--- /dev/null
+++ b/static/ico/anime_jien01.gif
Binary files differ
diff --git a/static/ico/anime_jien02.gif b/static/ico/anime_jien02.gif
new file mode 100644
index 0000000..51d5393
--- /dev/null
+++ b/static/ico/anime_jien02.gif
Binary files differ
diff --git a/static/ico/anime_jien03.gif b/static/ico/anime_jien03.gif
new file mode 100644
index 0000000..2e59a55
--- /dev/null
+++ b/static/ico/anime_jien03.gif
Binary files differ
diff --git a/static/ico/anime_jyorujyu01.gif b/static/ico/anime_jyorujyu01.gif
new file mode 100644
index 0000000..6e3bca8
--- /dev/null
+++ b/static/ico/anime_jyorujyu01.gif
Binary files differ
diff --git a/static/ico/anime_jyorujyu02.gif b/static/ico/anime_jyorujyu02.gif
new file mode 100644
index 0000000..5d13a89
--- /dev/null
+++ b/static/ico/anime_jyorujyu02.gif
Binary files differ
diff --git a/static/ico/anime_jyorujyu03.gif b/static/ico/anime_jyorujyu03.gif
new file mode 100644
index 0000000..5034286
--- /dev/null
+++ b/static/ico/anime_jyorujyu03.gif
Binary files differ
diff --git a/static/ico/anime_kukkuru01.gif b/static/ico/anime_kukkuru01.gif
new file mode 100644
index 0000000..7a817cd
--- /dev/null
+++ b/static/ico/anime_kukkuru01.gif
Binary files differ
diff --git a/static/ico/anime_kuma01.gif b/static/ico/anime_kuma01.gif
new file mode 100644
index 0000000..5c1cbae
--- /dev/null
+++ b/static/ico/anime_kuma01.gif
Binary files differ
diff --git a/static/ico/anime_kumaface01.gif b/static/ico/anime_kumaface01.gif
new file mode 100644
index 0000000..e6027fc
--- /dev/null
+++ b/static/ico/anime_kumaface01.gif
Binary files differ
diff --git a/static/ico/anime_loop.gif b/static/ico/anime_loop.gif
new file mode 100644
index 0000000..19f2e9b
--- /dev/null
+++ b/static/ico/anime_loop.gif
Binary files differ
diff --git a/static/ico/anime_marara02.gif b/static/ico/anime_marara02.gif
new file mode 100644
index 0000000..7d3fb7f
--- /dev/null
+++ b/static/ico/anime_marara02.gif
Binary files differ
diff --git a/static/ico/anime_matanki01.gif b/static/ico/anime_matanki01.gif
new file mode 100644
index 0000000..7ab5b77
--- /dev/null
+++ b/static/ico/anime_matanki01.gif
Binary files differ
diff --git a/static/ico/anime_matanki02.gif b/static/ico/anime_matanki02.gif
new file mode 100644
index 0000000..342eca3
--- /dev/null
+++ b/static/ico/anime_matanki02.gif
Binary files differ
diff --git a/static/ico/anime_miruna01.gif b/static/ico/anime_miruna01.gif
new file mode 100644
index 0000000..85e1c5d
--- /dev/null
+++ b/static/ico/anime_miruna01.gif
Binary files differ
diff --git a/static/ico/anime_monar02.gif b/static/ico/anime_monar02.gif
new file mode 100644
index 0000000..c8bfdfc
--- /dev/null
+++ b/static/ico/anime_monar02.gif
Binary files differ
diff --git a/static/ico/anime_monar03.gif b/static/ico/anime_monar03.gif
new file mode 100644
index 0000000..b3e061c
--- /dev/null
+++ b/static/ico/anime_monar03.gif
Binary files differ
diff --git a/static/ico/anime_monar05.gif b/static/ico/anime_monar05.gif
new file mode 100644
index 0000000..4d934fb
--- /dev/null
+++ b/static/ico/anime_monar05.gif
Binary files differ
diff --git a/static/ico/anime_morara01.gif b/static/ico/anime_morara01.gif
new file mode 100644
index 0000000..e9d4808
--- /dev/null
+++ b/static/ico/anime_morara01.gif
Binary files differ
diff --git a/static/ico/anime_morara02.gif b/static/ico/anime_morara02.gif
new file mode 100644
index 0000000..0cf4f97
--- /dev/null
+++ b/static/ico/anime_morara02.gif
Binary files differ
diff --git a/static/ico/anime_morara04.gif b/static/ico/anime_morara04.gif
new file mode 100644
index 0000000..846d642
--- /dev/null
+++ b/static/ico/anime_morara04.gif
Binary files differ
diff --git a/static/ico/anime_nokar01.gif b/static/ico/anime_nokar01.gif
new file mode 100644
index 0000000..89ea5bb
--- /dev/null
+++ b/static/ico/anime_nokar01.gif
Binary files differ
diff --git a/static/ico/anime_okashi01.gif b/static/ico/anime_okashi01.gif
new file mode 100644
index 0000000..5e4e518
--- /dev/null
+++ b/static/ico/anime_okashi01.gif
Binary files differ
diff --git a/static/ico/anime_okashi02.gif b/static/ico/anime_okashi02.gif
new file mode 100644
index 0000000..6ba6ec3
--- /dev/null
+++ b/static/ico/anime_okashi02.gif
Binary files differ
diff --git a/static/ico/anime_onigiri04.gif b/static/ico/anime_onigiri04.gif
new file mode 100644
index 0000000..78f3f66
--- /dev/null
+++ b/static/ico/anime_onigiri04.gif
Binary files differ
diff --git a/static/ico/anime_saitama01.gif b/static/ico/anime_saitama01.gif
new file mode 100644
index 0000000..b36dcb5
--- /dev/null
+++ b/static/ico/anime_saitama01.gif
Binary files differ
diff --git a/static/ico/anime_saitama02.gif b/static/ico/anime_saitama02.gif
new file mode 100644
index 0000000..0a81ff2
--- /dev/null
+++ b/static/ico/anime_saitama02.gif
Binary files differ
diff --git a/static/ico/anime_saitama03.gif b/static/ico/anime_saitama03.gif
new file mode 100644
index 0000000..5cf168b
--- /dev/null
+++ b/static/ico/anime_saitama03.gif
Binary files differ
diff --git a/static/ico/anime_sasuga01.gif b/static/ico/anime_sasuga01.gif
new file mode 100644
index 0000000..279d97a
--- /dev/null
+++ b/static/ico/anime_sasuga01.gif
Binary files differ
diff --git a/static/ico/anime_sasuga03.gif b/static/ico/anime_sasuga03.gif
new file mode 100644
index 0000000..047e2b9
--- /dev/null
+++ b/static/ico/anime_sasuga03.gif
Binary files differ
diff --git a/static/ico/anime_sasuga04.gif b/static/ico/anime_sasuga04.gif
new file mode 100644
index 0000000..0e9f839
--- /dev/null
+++ b/static/ico/anime_sasuga04.gif
Binary files differ
diff --git a/static/ico/anime_shii01.gif b/static/ico/anime_shii01.gif
new file mode 100644
index 0000000..99cf151
--- /dev/null
+++ b/static/ico/anime_shii01.gif
Binary files differ
diff --git a/static/ico/anime_shii02.gif b/static/ico/anime_shii02.gif
new file mode 100644
index 0000000..233869b
--- /dev/null
+++ b/static/ico/anime_shii02.gif
Binary files differ
diff --git a/static/ico/anime_shii03.gif b/static/ico/anime_shii03.gif
new file mode 100644
index 0000000..51f3723
--- /dev/null
+++ b/static/ico/anime_shii03.gif
Binary files differ
diff --git a/static/ico/anime_syobon01.gif b/static/ico/anime_syobon01.gif
new file mode 100644
index 0000000..bcbd7eb
--- /dev/null
+++ b/static/ico/anime_syobon01.gif
Binary files differ
diff --git a/static/ico/anime_syobon03.gif b/static/ico/anime_syobon03.gif
new file mode 100644
index 0000000..02bc032
--- /dev/null
+++ b/static/ico/anime_syobon03.gif
Binary files differ
diff --git a/static/ico/anime_tarn01.gif b/static/ico/anime_tarn01.gif
new file mode 100644
index 0000000..0de9031
--- /dev/null
+++ b/static/ico/anime_tarn01.gif
Binary files differ
diff --git a/static/ico/anime_uwan01.gif b/static/ico/anime_uwan01.gif
new file mode 100644
index 0000000..8945d5a
--- /dev/null
+++ b/static/ico/anime_uwan01.gif
Binary files differ
diff --git a/static/ico/anime_uwan02.gif b/static/ico/anime_uwan02.gif
new file mode 100644
index 0000000..c4e5c2d
--- /dev/null
+++ b/static/ico/anime_uwan02.gif
Binary files differ
diff --git a/static/ico/anime_uwan03.gif b/static/ico/anime_uwan03.gif
new file mode 100644
index 0000000..7ec0b3e
--- /dev/null
+++ b/static/ico/anime_uwan03.gif
Binary files differ
diff --git a/static/ico/anime_youkanman01.gif b/static/ico/anime_youkanman01.gif
new file mode 100644
index 0000000..8706427
--- /dev/null
+++ b/static/ico/anime_youkanman01.gif
Binary files differ
diff --git a/static/ico/anime_youkanman02.gif b/static/ico/anime_youkanman02.gif
new file mode 100644
index 0000000..6c3862a
--- /dev/null
+++ b/static/ico/anime_youkanman02.gif
Binary files differ
diff --git a/static/ico/anime_youkanman03.gif b/static/ico/anime_youkanman03.gif
new file mode 100644
index 0000000..a5973f6
--- /dev/null
+++ b/static/ico/anime_youkanman03.gif
Binary files differ
diff --git a/static/ico/anime_zonu01.gif b/static/ico/anime_zonu01.gif
new file mode 100644
index 0000000..964ed8c
--- /dev/null
+++ b/static/ico/anime_zonu01.gif
Binary files differ
diff --git a/static/ico/anime_zonu02.gif b/static/ico/anime_zonu02.gif
new file mode 100644
index 0000000..70d4572
--- /dev/null
+++ b/static/ico/anime_zonu02.gif
Binary files differ
diff --git a/static/ico/aramaki.gif b/static/ico/aramaki.gif
new file mode 100644
index 0000000..b3f6420
--- /dev/null
+++ b/static/ico/aramaki.gif
Binary files differ
diff --git a/static/ico/aroeri-na32.gif b/static/ico/aroeri-na32.gif
new file mode 100644
index 0000000..e6cf7d6
--- /dev/null
+++ b/static/ico/aroeri-na32.gif
Binary files differ
diff --git a/static/ico/asopasomaso.gif b/static/ico/asopasomaso.gif
new file mode 100644
index 0000000..2b153e4
--- /dev/null
+++ b/static/ico/asopasomaso.gif
Binary files differ
diff --git a/static/ico/bikyakusan32.gif b/static/ico/bikyakusan32.gif
new file mode 100644
index 0000000..62f8483
--- /dev/null
+++ b/static/ico/bikyakusan32.gif
Binary files differ
diff --git a/static/ico/bs.gif b/static/ico/bs.gif
new file mode 100644
index 0000000..25c1f0f
--- /dev/null
+++ b/static/ico/bs.gif
Binary files differ
diff --git a/static/ico/button1_03.gif b/static/ico/button1_03.gif
new file mode 100644
index 0000000..1e29394
--- /dev/null
+++ b/static/ico/button1_03.gif
Binary files differ
diff --git a/static/ico/buun.gif b/static/ico/buun.gif
new file mode 100644
index 0000000..81f9b62
--- /dev/null
+++ b/static/ico/buun.gif
Binary files differ
diff --git a/static/ico/chahan.gif b/static/ico/chahan.gif
new file mode 100644
index 0000000..d10116c
--- /dev/null
+++ b/static/ico/chahan.gif
Binary files differ
diff --git a/static/ico/dokuo1.gif b/static/ico/dokuo1.gif
new file mode 100644
index 0000000..70e9a1f
--- /dev/null
+++ b/static/ico/dokuo1.gif
Binary files differ
diff --git a/static/ico/file2_01.gif b/static/ico/file2_01.gif
new file mode 100644
index 0000000..9c88ab0
--- /dev/null
+++ b/static/ico/file2_01.gif
Binary files differ
diff --git a/static/ico/fujisan.gif b/static/ico/fujisan.gif
new file mode 100644
index 0000000..9e33757
--- /dev/null
+++ b/static/ico/fujisan.gif
Binary files differ
diff --git a/static/ico/fuun.gif b/static/ico/fuun.gif
new file mode 100644
index 0000000..7576689
--- /dev/null
+++ b/static/ico/fuun.gif
Binary files differ
diff --git a/static/ico/gaku.gif b/static/ico/gaku.gif
new file mode 100644
index 0000000..667c680
--- /dev/null
+++ b/static/ico/gaku.gif
Binary files differ
diff --git a/static/ico/gaku2.gif b/static/ico/gaku2.gif
new file mode 100644
index 0000000..6f30a26
--- /dev/null
+++ b/static/ico/gaku2.gif
Binary files differ
diff --git a/static/ico/gaku3.gif b/static/ico/gaku3.gif
new file mode 100644
index 0000000..685a0fc
--- /dev/null
+++ b/static/ico/gaku3.gif
Binary files differ
diff --git a/static/ico/gekisya1.gif b/static/ico/gekisya1.gif
new file mode 100644
index 0000000..7b2238f
--- /dev/null
+++ b/static/ico/gekisya1.gif
Binary files differ
diff --git a/static/ico/giko1.gif b/static/ico/giko1.gif
new file mode 100644
index 0000000..330a682
--- /dev/null
+++ b/static/ico/giko1.gif
Binary files differ
diff --git a/static/ico/gikog_gomibako.gif b/static/ico/gikog_gomibako.gif
new file mode 100644
index 0000000..cfdd338
--- /dev/null
+++ b/static/ico/gikog_gomibako.gif
Binary files differ
diff --git a/static/ico/gikog_gyunyupack.gif b/static/ico/gikog_gyunyupack.gif
new file mode 100644
index 0000000..8e2de6b
--- /dev/null
+++ b/static/ico/gikog_gyunyupack.gif
Binary files differ
diff --git a/static/ico/gikog_pimiento.gif b/static/ico/gikog_pimiento.gif
new file mode 100644
index 0000000..21e5eca
--- /dev/null
+++ b/static/ico/gikog_pimiento.gif
Binary files differ
diff --git a/static/ico/gikoinu.gif b/static/ico/gikoinu.gif
new file mode 100644
index 0000000..d923982
--- /dev/null
+++ b/static/ico/gikoinu.gif
Binary files differ
diff --git a/static/ico/gikoneko.gif b/static/ico/gikoneko.gif
new file mode 100644
index 0000000..f9e4999
--- /dev/null
+++ b/static/ico/gikoneko.gif
Binary files differ
diff --git a/static/ico/gikoneko2.gif b/static/ico/gikoneko2.gif
new file mode 100644
index 0000000..54d4647
--- /dev/null
+++ b/static/ico/gikoneko2.gif
Binary files differ
diff --git a/static/ico/gikoneko_1.gif b/static/ico/gikoneko_1.gif
new file mode 100644
index 0000000..a168dbf
--- /dev/null
+++ b/static/ico/gikoneko_1.gif
Binary files differ
diff --git a/static/ico/gocchin_face.gif b/static/ico/gocchin_face.gif
new file mode 100644
index 0000000..cfde101
--- /dev/null
+++ b/static/ico/gocchin_face.gif
Binary files differ
diff --git a/static/ico/gomiopen.gif b/static/ico/gomiopen.gif
new file mode 100644
index 0000000..56d9ada
--- /dev/null
+++ b/static/ico/gomiopen.gif
Binary files differ
diff --git a/static/ico/goo_1.gif b/static/ico/goo_1.gif
new file mode 100644
index 0000000..e3c2d93
--- /dev/null
+++ b/static/ico/goo_1.gif
Binary files differ
diff --git a/static/ico/goo_3.gif b/static/ico/goo_3.gif
new file mode 100644
index 0000000..b47825b
--- /dev/null
+++ b/static/ico/goo_3.gif
Binary files differ
diff --git a/static/ico/gya-.gif b/static/ico/gya-.gif
new file mode 100644
index 0000000..dfb2bd1
--- /dev/null
+++ b/static/ico/gya-.gif
Binary files differ
diff --git a/static/ico/hagenin-shuriken.gif b/static/ico/hagenin-shuriken.gif
new file mode 100644
index 0000000..51e3f8e
--- /dev/null
+++ b/static/ico/hagenin-shuriken.gif
Binary files differ
diff --git a/static/ico/hagurumaou.gif b/static/ico/hagurumaou.gif
new file mode 100644
index 0000000..06a1969
--- /dev/null
+++ b/static/ico/hagurumaou.gif
Binary files differ
diff --git a/static/ico/hikky.gif b/static/ico/hikky.gif
new file mode 100644
index 0000000..87e90e7
--- /dev/null
+++ b/static/ico/hikky.gif
Binary files differ
diff --git a/static/ico/hikky_xmas_2.gif b/static/ico/hikky_xmas_2.gif
new file mode 100644
index 0000000..162b96f
--- /dev/null
+++ b/static/ico/hikky_xmas_2.gif
Binary files differ
diff --git a/static/ico/hyou.gif b/static/ico/hyou.gif
new file mode 100644
index 0000000..0574ff5
--- /dev/null
+++ b/static/ico/hyou.gif
Binary files differ
diff --git a/static/ico/iirasan_face.gif b/static/ico/iirasan_face.gif
new file mode 100644
index 0000000..83b2462
--- /dev/null
+++ b/static/ico/iirasan_face.gif
Binary files differ
diff --git a/static/ico/imanouchi_1.gif b/static/ico/imanouchi_1.gif
new file mode 100644
index 0000000..9e242a0
--- /dev/null
+++ b/static/ico/imanouchi_1.gif
Binary files differ
diff --git a/static/ico/iyahoo.gif b/static/ico/iyahoo.gif
new file mode 100644
index 0000000..3387787
--- /dev/null
+++ b/static/ico/iyahoo.gif
Binary files differ
diff --git a/static/ico/iyou.gif b/static/ico/iyou.gif
new file mode 100644
index 0000000..bc94072
--- /dev/null
+++ b/static/ico/iyou.gif
Binary files differ
diff --git a/static/ico/jisakujien_2.gif b/static/ico/jisakujien_2.gif
new file mode 100644
index 0000000..0cc759a
--- /dev/null
+++ b/static/ico/jisakujien_2.gif
Binary files differ
diff --git a/static/ico/jisakujien_xmas.gif b/static/ico/jisakujien_xmas.gif
new file mode 100644
index 0000000..9c1c8c8
--- /dev/null
+++ b/static/ico/jisakujien_xmas.gif
Binary files differ
diff --git a/static/ico/kantoku1.gif b/static/ico/kantoku1.gif
new file mode 100644
index 0000000..6459dc4
--- /dev/null
+++ b/static/ico/kantoku1.gif
Binary files differ
diff --git a/static/ico/kappappa1.gif b/static/ico/kappappa1.gif
new file mode 100644
index 0000000..e182e84
--- /dev/null
+++ b/static/ico/kappappa1.gif
Binary files differ
diff --git a/static/ico/kasa-ri.gif b/static/ico/kasa-ri.gif
new file mode 100644
index 0000000..26fde75
--- /dev/null
+++ b/static/ico/kasa-ri.gif
Binary files differ
diff --git a/static/ico/kashiwamo-chi32.gif b/static/ico/kashiwamo-chi32.gif
new file mode 100644
index 0000000..5d99a57
--- /dev/null
+++ b/static/ico/kashiwamo-chi32.gif
Binary files differ
diff --git a/static/ico/kinokorusensei32.gif b/static/ico/kinokorusensei32.gif
new file mode 100644
index 0000000..e315517
--- /dev/null
+++ b/static/ico/kinokorusensei32.gif
Binary files differ
diff --git a/static/ico/kita_.gif b/static/ico/kita_.gif
new file mode 100644
index 0000000..b953217
--- /dev/null
+++ b/static/ico/kita_.gif
Binary files differ
diff --git a/static/ico/kodomona.gif b/static/ico/kodomona.gif
new file mode 100644
index 0000000..9998fb8
--- /dev/null
+++ b/static/ico/kodomona.gif
Binary files differ
diff --git a/static/ico/konkon_folder.gif b/static/ico/konkon_folder.gif
new file mode 100644
index 0000000..7a1f3c6
--- /dev/null
+++ b/static/ico/konkon_folder.gif
Binary files differ
diff --git a/static/ico/kossorisan.gif b/static/ico/kossorisan.gif
new file mode 100644
index 0000000..96e177c
--- /dev/null
+++ b/static/ico/kossorisan.gif
Binary files differ
diff --git a/static/ico/kotatu.gif b/static/ico/kotatu.gif
new file mode 100644
index 0000000..2b0fa89
--- /dev/null
+++ b/static/ico/kotatu.gif
Binary files differ
diff --git a/static/ico/kuma.gif b/static/ico/kuma.gif
new file mode 100644
index 0000000..453e2c3
--- /dev/null
+++ b/static/ico/kuma.gif
Binary files differ
diff --git a/static/ico/kuma2.gif b/static/ico/kuma2.gif
new file mode 100644
index 0000000..a3e7109
--- /dev/null
+++ b/static/ico/kuma2.gif
Binary files differ
diff --git a/static/ico/maimai.gif b/static/ico/maimai.gif
new file mode 100644
index 0000000..0a37a4f
--- /dev/null
+++ b/static/ico/maimai.gif
Binary files differ
diff --git a/static/ico/makotan2_folder.gif b/static/ico/makotan2_folder.gif
new file mode 100644
index 0000000..ea6996c
--- /dev/null
+++ b/static/ico/makotan2_folder.gif
Binary files differ
diff --git a/static/ico/mona.gif b/static/ico/mona.gif
new file mode 100644
index 0000000..2163e99
--- /dev/null
+++ b/static/ico/mona.gif
Binary files differ
diff --git a/static/ico/mona_shiri.gif b/static/ico/mona_shiri.gif
new file mode 100644
index 0000000..f1c209a
--- /dev/null
+++ b/static/ico/mona_shiri.gif
Binary files differ
diff --git a/static/ico/mona_tya.gif b/static/ico/mona_tya.gif
new file mode 100644
index 0000000..ae5feb6
--- /dev/null
+++ b/static/ico/mona_tya.gif
Binary files differ
diff --git a/static/ico/monaazarashi_1.gif b/static/ico/monaazarashi_1.gif
new file mode 100644
index 0000000..b6c09ca
--- /dev/null
+++ b/static/ico/monaazarashi_1.gif
Binary files differ
diff --git a/static/ico/namaetukenai.gif b/static/ico/namaetukenai.gif
new file mode 100644
index 0000000..a381eba
--- /dev/null
+++ b/static/ico/namaetukenai.gif
Binary files differ
diff --git a/static/ico/naoruyo.gif b/static/ico/naoruyo.gif
new file mode 100644
index 0000000..0dc9c83
--- /dev/null
+++ b/static/ico/naoruyo.gif
Binary files differ
diff --git a/static/ico/nida.gif b/static/ico/nida.gif
new file mode 100644
index 0000000..8c383b6
--- /dev/null
+++ b/static/ico/nida.gif
Binary files differ
diff --git a/static/ico/nigete.gif b/static/ico/nigete.gif
new file mode 100644
index 0000000..271dfb1
--- /dev/null
+++ b/static/ico/nigete.gif
Binary files differ
diff --git a/static/ico/nono_ie.gif b/static/ico/nono_ie.gif
new file mode 100644
index 0000000..302971b
--- /dev/null
+++ b/static/ico/nono_ie.gif
Binary files differ
diff --git a/static/ico/nurupo_ga_2.gif b/static/ico/nurupo_ga_2.gif
new file mode 100644
index 0000000..4cc8611
--- /dev/null
+++ b/static/ico/nurupo_ga_2.gif
Binary files differ
diff --git a/static/ico/onigiri_seito.gif b/static/ico/onigiri_seito.gif
new file mode 100644
index 0000000..9be7160
--- /dev/null
+++ b/static/ico/onigiri_seito.gif
Binary files differ
diff --git a/static/ico/otiketu48.gif b/static/ico/otiketu48.gif
new file mode 100644
index 0000000..3787378
--- /dev/null
+++ b/static/ico/otiketu48.gif
Binary files differ
diff --git a/static/ico/pc3.gif b/static/ico/pc3.gif
new file mode 100644
index 0000000..a4ddc7d
--- /dev/null
+++ b/static/ico/pc3.gif
Binary files differ
diff --git a/static/ico/pgya.gif b/static/ico/pgya.gif
new file mode 100644
index 0000000..edfad21
--- /dev/null
+++ b/static/ico/pgya.gif
Binary files differ
diff --git a/static/ico/sasuga1.gif b/static/ico/sasuga1.gif
new file mode 100644
index 0000000..1f8bfd9
--- /dev/null
+++ b/static/ico/sasuga1.gif
Binary files differ
diff --git a/static/ico/seito_2.gif b/static/ico/seito_2.gif
new file mode 100644
index 0000000..3ff3e3c
--- /dev/null
+++ b/static/ico/seito_2.gif
Binary files differ
diff --git a/static/ico/soon.gif b/static/ico/soon.gif
new file mode 100644
index 0000000..95e4d74
--- /dev/null
+++ b/static/ico/soon.gif
Binary files differ
diff --git a/static/ico/tasukete.gif b/static/ico/tasukete.gif
new file mode 100644
index 0000000..9e4fe3a
--- /dev/null
+++ b/static/ico/tasukete.gif
Binary files differ
diff --git a/static/ico/torimasu1.gif b/static/ico/torimasu1.gif
new file mode 100644
index 0000000..64fd5fe
--- /dev/null
+++ b/static/ico/torimasu1.gif
Binary files differ
diff --git a/static/ico/torimasu2.gif b/static/ico/torimasu2.gif
new file mode 100644
index 0000000..e3ec154
--- /dev/null
+++ b/static/ico/torimasu2.gif
Binary files differ
diff --git a/static/ico/u_ame.gif b/static/ico/u_ame.gif
new file mode 100644
index 0000000..1369356
--- /dev/null
+++ b/static/ico/u_ame.gif
Binary files differ
diff --git a/static/ico/u_hoshi.gif b/static/ico/u_hoshi.gif
new file mode 100644
index 0000000..6b8adbd
--- /dev/null
+++ b/static/ico/u_hoshi.gif
Binary files differ
diff --git a/static/ico/u_naoruyo_bath.gif b/static/ico/u_naoruyo_bath.gif
new file mode 100644
index 0000000..def8ca6
--- /dev/null
+++ b/static/ico/u_naoruyo_bath.gif
Binary files differ
diff --git a/static/ico/u_okotowari_a.gif b/static/ico/u_okotowari_a.gif
new file mode 100644
index 0000000..ed43164
--- /dev/null
+++ b/static/ico/u_okotowari_a.gif
Binary files differ
diff --git a/static/ico/u_sofa.gif b/static/ico/u_sofa.gif
new file mode 100644
index 0000000..783aa98
--- /dev/null
+++ b/static/ico/u_sofa.gif
Binary files differ
diff --git a/static/ico/wakannai1.gif b/static/ico/wakannai1.gif
new file mode 100644
index 0000000..eeecb33
--- /dev/null
+++ b/static/ico/wakannai1.gif
Binary files differ
diff --git a/static/ico/yakimochi.gif b/static/ico/yakimochi.gif
new file mode 100644
index 0000000..8652360
--- /dev/null
+++ b/static/ico/yakimochi.gif
Binary files differ
diff --git a/static/ico/youkan.gif b/static/ico/youkan.gif
new file mode 100644
index 0000000..d1c386e
--- /dev/null
+++ b/static/ico/youkan.gif
Binary files differ
diff --git a/static/ico/zonu_1.gif b/static/ico/zonu_1.gif
new file mode 100644
index 0000000..816c451
--- /dev/null
+++ b/static/ico/zonu_1.gif
Binary files differ
diff --git a/static/ico/zuzagiko48.gif b/static/ico/zuzagiko48.gif
new file mode 100644
index 0000000..c4dd620
--- /dev/null
+++ b/static/ico/zuzagiko48.gif
Binary files differ
diff --git a/static/img/anarkia.jpg b/static/img/anarkia.jpg
new file mode 100644
index 0000000..43db329
--- /dev/null
+++ b/static/img/anarkia.jpg
Binary files differ
diff --git a/static/img/bai.jpg b/static/img/bai.jpg
new file mode 100644
index 0000000..ac41b4d
--- /dev/null
+++ b/static/img/bai.jpg
Binary files differ
diff --git a/static/img/cero.gif b/static/img/cero.gif
new file mode 100644
index 0000000..9ab0f0f
--- /dev/null
+++ b/static/img/cero.gif
Binary files differ
diff --git a/static/img/default.png b/static/img/default.png
new file mode 100644
index 0000000..9cd9b93
--- /dev/null
+++ b/static/img/default.png
Binary files differ
diff --git a/static/img/juegos1.jpg b/static/img/juegos1.jpg
new file mode 100644
index 0000000..b908128
--- /dev/null
+++ b/static/img/juegos1.jpg
Binary files differ
diff --git a/static/img/juegos2.jpg b/static/img/juegos2.jpg
new file mode 100644
index 0000000..0cc9cc5
--- /dev/null
+++ b/static/img/juegos2.jpg
Binary files differ
diff --git a/static/img/juegos3.png b/static/img/juegos3.png
new file mode 100644
index 0000000..685a3d0
--- /dev/null
+++ b/static/img/juegos3.png
Binary files differ
diff --git a/static/img/juegos4.gif b/static/img/juegos4.gif
new file mode 100644
index 0000000..40aca15
--- /dev/null
+++ b/static/img/juegos4.gif
Binary files differ
diff --git a/static/img/letras1.png b/static/img/letras1.png
new file mode 100644
index 0000000..719de0d
--- /dev/null
+++ b/static/img/letras1.png
Binary files differ
diff --git a/static/img/letras2.png b/static/img/letras2.png
new file mode 100644
index 0000000..61affa4
--- /dev/null
+++ b/static/img/letras2.png
Binary files differ
diff --git a/static/img/letras3.png b/static/img/letras3.png
new file mode 100644
index 0000000..78183be
--- /dev/null
+++ b/static/img/letras3.png
Binary files differ
diff --git a/static/img/letras4.jpg b/static/img/letras4.jpg
new file mode 100644
index 0000000..32c5ff6
--- /dev/null
+++ b/static/img/letras4.jpg
Binary files differ
diff --git a/static/img/letras5.jpg b/static/img/letras5.jpg
new file mode 100644
index 0000000..61128bc
--- /dev/null
+++ b/static/img/letras5.jpg
Binary files differ
diff --git a/static/img/musica1.jpg b/static/img/musica1.jpg
new file mode 100644
index 0000000..3cd141d
--- /dev/null
+++ b/static/img/musica1.jpg
Binary files differ
diff --git a/static/img/noticias.png b/static/img/noticias.png
new file mode 100644
index 0000000..1ee2187
--- /dev/null
+++ b/static/img/noticias.png
Binary files differ
diff --git a/static/img/old/2d_1.jpg b/static/img/old/2d_1.jpg
new file mode 100644
index 0000000..01216b3
--- /dev/null
+++ b/static/img/old/2d_1.jpg
Binary files differ
diff --git a/static/img/old/2d_2.jpg b/static/img/old/2d_2.jpg
new file mode 100644
index 0000000..dd9c234
--- /dev/null
+++ b/static/img/old/2d_2.jpg
Binary files differ
diff --git a/static/img/old/2d_3.png b/static/img/old/2d_3.png
new file mode 100644
index 0000000..034cf1e
--- /dev/null
+++ b/static/img/old/2d_3.png
Binary files differ
diff --git a/static/img/old/2d_4.jpg b/static/img/old/2d_4.jpg
new file mode 100644
index 0000000..7f5c7fe
--- /dev/null
+++ b/static/img/old/2d_4.jpg
Binary files differ
diff --git a/static/img/old/argentina1.png b/static/img/old/argentina1.png
new file mode 100644
index 0000000..4dc22b6
--- /dev/null
+++ b/static/img/old/argentina1.png
Binary files differ
diff --git a/static/img/old/chile1.png b/static/img/old/chile1.png
new file mode 100644
index 0000000..37bda0b
--- /dev/null
+++ b/static/img/old/chile1.png
Binary files differ
diff --git a/static/img/old/chile2.jpg b/static/img/old/chile2.jpg
new file mode 100644
index 0000000..558212a
--- /dev/null
+++ b/static/img/old/chile2.jpg
Binary files differ
diff --git a/static/img/old/g0.jpg b/static/img/old/g0.jpg
new file mode 100644
index 0000000..b70c449
--- /dev/null
+++ b/static/img/old/g0.jpg
Binary files differ
diff --git a/static/img/old/g1.jpg b/static/img/old/g1.jpg
new file mode 100644
index 0000000..30315c9
--- /dev/null
+++ b/static/img/old/g1.jpg
Binary files differ
diff --git a/static/img/old/g2.jpg b/static/img/old/g2.jpg
new file mode 100644
index 0000000..c073028
--- /dev/null
+++ b/static/img/old/g2.jpg
Binary files differ
diff --git a/static/img/old/g3.jpg b/static/img/old/g3.jpg
new file mode 100644
index 0000000..9686553
--- /dev/null
+++ b/static/img/old/g3.jpg
Binary files differ
diff --git a/static/img/old/g4.jpg b/static/img/old/g4.jpg
new file mode 100644
index 0000000..f49404b
--- /dev/null
+++ b/static/img/old/g4.jpg
Binary files differ
diff --git a/static/img/old/g5.jpg b/static/img/old/g5.jpg
new file mode 100644
index 0000000..959aaaf
--- /dev/null
+++ b/static/img/old/g5.jpg
Binary files differ
diff --git a/static/img/old/peli.jpg b/static/img/old/peli.jpg
new file mode 100644
index 0000000..0b953b9
--- /dev/null
+++ b/static/img/old/peli.jpg
Binary files differ
diff --git a/static/img/old/salon2d_3.jpg b/static/img/old/salon2d_3.jpg
new file mode 100644
index 0000000..592b04f
--- /dev/null
+++ b/static/img/old/salon2d_3.jpg
Binary files differ
diff --git a/static/img/old/salon2d_4.png b/static/img/old/salon2d_4.png
new file mode 100644
index 0000000..bbcd904
--- /dev/null
+++ b/static/img/old/salon2d_4.png
Binary files differ
diff --git a/static/img/old/salon2d_5.jpg b/static/img/old/salon2d_5.jpg
new file mode 100644
index 0000000..35151b1
--- /dev/null
+++ b/static/img/old/salon2d_5.jpg
Binary files differ
diff --git a/static/img/old/zine.png b/static/img/old/zine.png
new file mode 100644
index 0000000..2812b34
--- /dev/null
+++ b/static/img/old/zine.png
Binary files differ
diff --git a/static/img/salon2d_1.png b/static/img/salon2d_1.png
new file mode 100644
index 0000000..7295a44
--- /dev/null
+++ b/static/img/salon2d_1.png
Binary files differ
diff --git a/static/img/salon2d_3.jpg b/static/img/salon2d_3.jpg
new file mode 100644
index 0000000..592b04f
--- /dev/null
+++ b/static/img/salon2d_3.jpg
Binary files differ
diff --git a/static/img/salon2d_4.png b/static/img/salon2d_4.png
new file mode 100644
index 0000000..bbcd904
--- /dev/null
+++ b/static/img/salon2d_4.png
Binary files differ
diff --git a/static/img/salon2d_5.jpg b/static/img/salon2d_5.jpg
new file mode 100644
index 0000000..35151b1
--- /dev/null
+++ b/static/img/salon2d_5.jpg
Binary files differ
diff --git a/static/img/tech1.png b/static/img/tech1.png
new file mode 100644
index 0000000..3e851c2
--- /dev/null
+++ b/static/img/tech1.png
Binary files differ
diff --git a/static/img/tech2.jpg b/static/img/tech2.jpg
new file mode 100644
index 0000000..cd982ff
--- /dev/null
+++ b/static/img/tech2.jpg
Binary files differ
diff --git a/static/img/tech3.png b/static/img/tech3.png
new file mode 100644
index 0000000..b7ad99d
--- /dev/null
+++ b/static/img/tech3.png
Binary files differ
diff --git a/static/img/tech4.jpg b/static/img/tech4.jpg
new file mode 100644
index 0000000..d9d959d
--- /dev/null
+++ b/static/img/tech4.jpg
Binary files differ
diff --git a/static/img/tech5.jpg b/static/img/tech5.jpg
new file mode 100644
index 0000000..b19df49
--- /dev/null
+++ b/static/img/tech5.jpg
Binary files differ
diff --git a/static/img/tech6.png b/static/img/tech6.png
new file mode 100644
index 0000000..32faa9b
--- /dev/null
+++ b/static/img/tech6.png
Binary files differ
diff --git a/static/img/tv1.png b/static/img/tv1.png
new file mode 100644
index 0000000..17ab84b
--- /dev/null
+++ b/static/img/tv1.png
Binary files differ
diff --git a/static/img/weird-al.jpg b/static/img/weird-al.jpg
new file mode 100644
index 0000000..10de1c6
--- /dev/null
+++ b/static/img/weird-al.jpg
Binary files differ
diff --git a/static/img/world.gif b/static/img/world.gif
new file mode 100644
index 0000000..f6a8d80
--- /dev/null
+++ b/static/img/world.gif
Binary files differ
diff --git a/static/img/zonavip1.jpg b/static/img/zonavip1.jpg
new file mode 100644
index 0000000..2d8d98f
--- /dev/null
+++ b/static/img/zonavip1.jpg
Binary files differ
diff --git a/static/img/zonavip2.gif b/static/img/zonavip2.gif
new file mode 100644
index 0000000..0e37bae
--- /dev/null
+++ b/static/img/zonavip2.gif
Binary files differ
diff --git a/static/img/zonavip3.png b/static/img/zonavip3.png
new file mode 100644
index 0000000..323e346
--- /dev/null
+++ b/static/img/zonavip3.png
Binary files differ
diff --git a/static/img/zonavip4.jpg b/static/img/zonavip4.jpg
new file mode 100644
index 0000000..98d0ef4
--- /dev/null
+++ b/static/img/zonavip4.jpg
Binary files differ
diff --git a/static/img/zonavip5.gif b/static/img/zonavip5.gif
new file mode 100644
index 0000000..dc69964
--- /dev/null
+++ b/static/img/zonavip5.gif
Binary files differ
diff --git a/static/img/zonavip6.png b/static/img/zonavip6.png
new file mode 100644
index 0000000..aa3443b
--- /dev/null
+++ b/static/img/zonavip6.png
Binary files differ
diff --git a/static/img/zonavip7.gif b/static/img/zonavip7.gif
new file mode 100644
index 0000000..ff96166
--- /dev/null
+++ b/static/img/zonavip7.gif
Binary files differ
diff --git a/static/img/zonavip8.png b/static/img/zonavip8.png
new file mode 100644
index 0000000..847ad9a
--- /dev/null
+++ b/static/img/zonavip8.png
Binary files differ
diff --git a/static/img/zonavip9.gif b/static/img/zonavip9.gif
new file mode 100644
index 0000000..ba636df
--- /dev/null
+++ b/static/img/zonavip9.gif
Binary files differ
diff --git a/static/img/zonavip9.jpg b/static/img/zonavip9.jpg
new file mode 100644
index 0000000..9590b48
--- /dev/null
+++ b/static/img/zonavip9.jpg
Binary files differ
diff --git a/static/img/zonavip_halloween.jpg b/static/img/zonavip_halloween.jpg
new file mode 100644
index 0000000..674792f
--- /dev/null
+++ b/static/img/zonavip_halloween.jpg
Binary files differ
diff --git a/static/img/zonavip_nav.jpg b/static/img/zonavip_nav.jpg
new file mode 100644
index 0000000..506abf9
--- /dev/null
+++ b/static/img/zonavip_nav.jpg
Binary files differ
diff --git a/static/js/aquiencitas.js b/static/js/aquiencitas.js
new file mode 100644
index 0000000..0cf860f
--- /dev/null
+++ b/static/js/aquiencitas.js
@@ -0,0 +1,168 @@
+var cur_url;
+var linklist;
+var linki;
+var is_bbs;
+var plimit = 5;
+function getPostRange(t, n) {
+ var posts, replies, s, ss, ee, rev = false;
+ posts = [];
+ replies = t.getElementsByClassName("reply");
+ s = n.split('-');
+ ss = parseInt(s[0]);
+ ee = ss;
+ if(s.length == 2) ee = parseInt(s[1]);
+ if(ee<ss) { tmp=ss;ss=ee;ee=tmp; rev=true; }
+ for(j = 0; j < replies.length; j++) {
+ num = parseInt(replies[j].dataset.n);
+ if(num > ee) break;
+ if(num >= ss && num <= ee) {
+ if(rev) posts.unshift(replies[j]);
+ else posts.push(replies[j]);
+ }
+ }
+ return posts;
+}
+function findAncestor (el) {
+ while ((el = el.parentElement) && !el.className.startsWith("thread") && !el.className.startsWith("cont"));
+ return el;
+}
+function getPostDivs(e) {
+ if(is_bbs) {
+ divs = [];
+ t = findAncestor(e);
+ s = e.getAttribute('href').split('/');
+ r = s[s.length-1];
+ rs = r.split(',');
+ linki = 0;
+ for(i=0;i<rs.length;i++) { divs.push.apply(divs, getPostRange(t, rs[i])); }
+ return divs;
+ } else {
+ ele = document.getElementById('reply' + e.getAttribute('href').split('#')[1]);
+ return [ele,];
+ }
+}
+function get_pid(e) {
+ return is_bbs ? e.dataset.n : e.id.substr(5);
+}
+function fill_links(e) {
+ var divs = getPostDivs(e);
+ if(!divs[0]) return;
+
+ this_id = get_pid(e.parentNode.parentNode);
+
+ for(i=0;i<divs.length;i++) {
+ tid = get_pid(divs[i]);
+ if (linklist[tid])
+ continue;
+ if (this_id == tid)
+ continue;
+ t = (is_bbs ? divs[i].getElementsByTagName("h4")[0] : divs[i]);
+ bl = document.createElement('a');
+ bl.href = cur_url + (is_bbs ? "/" : "#") + this_id;
+ bl.textContent = '>>' + this_id;
+ bl.addEventListener('mouseover', who_are_you_quoting, false);
+ bl.addEventListener('mouseout', remove_quote_preview, false);
+ if (!(qb = t.getElementsByClassName('quoted')[0])) {
+ qb = document.createElement((is_bbs ? 'span' : 'div'));
+ qb.className = 'quoted';
+ qb.textContent = ' Citado por: ';
+ if(is_bbs) {
+ t.insertBefore(qb, t.getElementsByClassName("del")[0]);
+ t.insertBefore(document.createTextNode(' '), t.getElementsByClassName("del")[0]);
+ } else {
+ p = t.getElementsByTagName("blockquote");
+ p[p.length-1].insertAdjacentHTML('afterend', qb.outerHTML);
+ }
+ t.getElementsByClassName('quoted')[0].appendChild(bl);
+ } else {
+ qb.appendChild(document.createTextNode(' '));
+ qb.appendChild(bl);
+ }
+ linklist[tid] = true;
+ }
+}
+function who_are_you_quoting(e) {
+ var parent, d, clr, src, cnt, left, top, width, maxWidth;
+ e = e.target || window.event.srcElement;
+ var divs = getPostDivs(e);
+ if(!divs[0]) return;
+
+ maxWidth = 500;
+ cnt = document.createElement('div');
+ cnt.id = 'q-p';
+ width = divs[0].offsetWidth;
+ if (width > maxWidth) {
+ width = maxWidth;
+ }
+
+ for(i=0;i<divs.length&&i<plimit;i++) {
+ src = divs[i].cloneNode(true);
+ cnt.appendChild(src);
+ }
+ left = 0;
+ top = e.offsetHeight + 1;
+ parent = e;
+ do {
+ left += parent.offsetLeft;
+ top += parent.offsetTop;
+ } while (parent = parent.offsetParent);
+ if ((d = document.body.offsetWidth - left - width) < 0) left += d;
+ cnt.setAttribute('style', 'left:' + left + 'px;top:' + top + 'px;');
+ document.body.appendChild(cnt);
+}
+function remove_quote_preview(e) {
+ var cnt;
+ if (cnt = document.getElementById('q-p'))
+ document.body.removeChild(cnt);
+}
+/*function goTo(e) {
+ e.preventDefault();
+ var pst = this.textContent.split(/[-,]/)[0];
+ pst = "r"+ pst.slice(2);
+ pst = document.getElementById(pst);
+ if (pst) pst.scrollIntoView();
+}*/
+function quotePreview() {
+ if(localStorage.getItem("shobon_on") == "false") { return; }
+ if(localStorage.getItem("shobon_preview") == "false" && localStorage.getItem("shobon_backlink") == "false") { return; }
+
+ var i, q, replies, quotes;
+
+ if(document.body.className && document.body.className != "res")
+ is_bbs = true;
+ else is_bbs = false;
+
+ if(is_bbs) replies = document.getElementsByClassName('msg');
+ else replies = document.getElementsByTagName('blockquote');
+
+ urls = window.location.pathname.split("/");
+ cur_url = urls[0] + "/" + urls[1] + "/" + urls[2] + "/" + urls[3];
+
+ for (x = 0; x < replies.length; x++) {
+ quotes = replies[x].getElementsByTagName('a');
+ linklist = {};
+
+ for (i = 0; i < quotes.length; i++) {
+ q = quotes[i];
+ if(q.textContent.length < 3 || !q.textContent.startsWith(">>")) continue;
+
+ if(localStorage.getItem("shobon_preview") != "false") {
+ q.addEventListener('mouseover', who_are_you_quoting, false);
+ q.addEventListener('mouseout', remove_quote_preview, false);
+ }
+
+ if(localStorage.getItem("shobon_backlink") != "false") {
+ fill_links(q);
+ }
+ }
+ }
+/* if (document.body.className === "threadpage") {
+ for (x = 0; x < replies.length; x++) {
+ var q = replies[x].getElementsByTagName("a");
+ for(var j=0;j<q.length;j++) {
+ if(q[j].textContent.startsWith(">>")) q[j].addEventListener("click", goTo, false);
+ }
+ }
+ }*/
+}
+document.addEventListener('DOMContentLoaded', quotePreview, false); \ No newline at end of file
diff --git a/static/js/autorefresh.js b/static/js/autorefresh.js
new file mode 100644
index 0000000..0ed3e06
--- /dev/null
+++ b/static/js/autorefresh.js
@@ -0,0 +1,275 @@
+var lastTime = 0;
+var refreshInterval;
+var refreshMaxTime = 30;
+var refreshTime;
+var manual = 0;
+var serviceType = 0; // 2 = BBS, 3 = IB
+var thread_length = 0;
+var thread_lastreply = 0;
+var thread_title = "";
+var thread_first_length = 0;
+var http_request = new XMLHttpRequest();
+
+function checkNew(e) {
+ e.preventDefault();
+ manual = 1;
+ loadJSON();
+ if (chk.checked) refreshMaxTime = 25;
+}
+
+function loadJSON() {
+ if (chk.checked)
+ stopCounter("...");
+ if (manual)
+ document.getElementById("counter").innerText = "...";
+ var data_file;
+ if (serviceType == 2 || serviceType == 3) {
+ board = document.getElementsByName("board")[0].value;
+ parent = document.getElementsByName("parent")[0].value;
+ data_file = "/cgi/api/thread?dir=" + board + "&id=" + parent + "&offset=" + thread_length + "&time=" + lastTime;
+ } else {
+ return false;
+ }
+ http_request.open("GET", data_file, true);
+ http_request.send();
+}
+
+function updateThread(posts, total_replies, serverTime) {
+ thread_div = document.getElementsByClassName("thread")[0];
+ if (serviceType == 2)
+ last_elem = document.getElementsByClassName("size")[0];
+ else
+ last_elem = document.getElementsByClassName("cut")[0];
+
+ for (var i = 0; i < posts.length; i++) {
+ post = posts[i];
+ var div = document.createElement('div');
+ if (serviceType == 2) div.className = "reply";
+ else div.className = "replycont";
+ if (post.email) {
+ if (post.tripcode) s_name = '<a href="mailto:' + post.email + '"><span class="name"><b>' + post.name + '</b> ' + post.tripcode + '</span></a>';
+ else s_name = '<a href="mailto:' + post.email + '"><span class="name"><b>' + post.name + '</b></span></a>';
+ } else {
+ if (post.tripcode) s_name = '<span class="name"><b>' + post.name + '</b> ' + post.tripcode + '</span>';
+ else s_name = '<span class="name"><b>' + post.name + '</b></span>';
+ }
+ if (serviceType == 2) {
+ if (post.file) {
+ s_img = '<a href="/' + board + '/src/' + post.file + '" target="_blank" class="thumb"><img src="/' + board + '/thumb/' + post.thumb + '" width="' + post.thumb_width + '" height="' + post.thumb_height + '" /><br />' + Math.round(post.file_size/1024) + 'KB ' + post.file.substring(post.file.lastIndexOf(".")+1, post.file.length).toUpperCase() + '</a>';
+ } else s_img = '';
+ if (post.IS_DELETED == 1) div.innerHTML = '<h4 class="deleted">' + (thread_length + i + 1) + ' : Mensaje eliminado por el usuario.</h4>';
+ else if (post.IS_DELETED == 2) div.innerHTML = '<h4 class="deleted">' + (thread_length + i + 1) + ' : Mensaje eliminado por miembro del staff.</h4>';
+ else
+ div.innerHTML = '<h4>' + (thread_length + i + 1) + ' : ' + s_name + ' : <span class="date" data-unix="' + post.timestamp + '">' + post.timestamp_formatted + '</span> <span class="del"><a href="/cgi/report/' + board + '/' + post.id + '/' + (thread_length + i + 1) + '" rel="nofollow">rep</a> <a href="#">del</a></span></h4>' + s_img + '<div class="msg">' + post.message + '</div>';
+ } else {
+ if (post.file) {
+ if (post.image_width != 0) {
+ s_img = '<div class="fs"><a href="/' + board + '/src/' + post.file + '" class="expimg" data-id="' + post.id + '" data-thumb="/' + board + '/thumb/' + post.thumb + '" data-w="' + post.image_width + '" data-h="' + post.image_height + '" data-tw="' + post.thumb_width + '" data-th="' + post.thumb_height + '">' + post.file + '</a>-(' + post.file_size+ ' B, ' + post.image_width + 'x' + post.image_height + ')</div>';
+ } else {
+ s_img = '<div class="fs"><a href="/' + board + '/src/' + post.file + '" target="_blank">' + post.file + '</a>-(' + post.file_size+ ' B)</div>';
+ }
+ s_img += '<a target="_blank" href="/' + board + '/src/' + post.file + '" id="thumb' + post.id + '"><img class="thumb" alt="' + post.id + '" src="/' + board + '/thumb/' + post.thumb + '" width="' + post.thumb_width + '" height="' + post.thumb_height + '" /></a>';
+ s_msg = '<blockquote style="margin-left:' + (post.thumb_width+40) + 'px;">' + post.message + '</blockquote>';
+ } else {
+ s_img = '';
+ s_msg = '<blockquote>' + post.message + '</blockquote>';
+ }
+ if (post.IS_DELETED == 0) {
+ div.innerHTML = '<table border="0"><tr><td class="ell">…</td><td class="reply" id="reply' + post.id + '"><div class="info"><input type="checkbox" name="delete" value="' + post.id + '" />' + (post.subject ? (' <span class="subj">' + post.subject + '</span>') : '') + ' ' + s_name + ' ' + '<span class="date" data-unix="' + post.timestamp + '">' + post.timestamp_formatted + '</span> <span class="reflink"><a href="#' + post.id + '">No.</a><a href="#" class="postid">' + post.id + '</a></span> <a class="rep" href="/cgi/report/' + board + '/' + post.id + '" rel="nofollow">rep</a></div>' + s_img + s_msg + '</td></tr></table>';
+ }
+ }
+
+ thread_div.insertBefore(div, last_elem);
+ thread_div.setAttribute("data-length",(thread_length + i + 1));
+ if (serviceType == 2)
+ document.getElementsByTagName("h3")[0].getElementsByTagName("span")[0].innerText = "(" + (thread_length + i + 1) + " respuestas)";
+ }
+
+ if (posts.length > 0) {
+ if (!manual)
+ refreshMaxTime = 10;
+ if (!document.hasFocus())
+ if (posts.length > 1)
+ notif(thread_title, posts.length + ' nuevos mensajes');
+ else
+ notif(thread_title, 'Un nuevo mensaje');
+ } else {
+ if (refreshMaxTime <= 60)
+ refreshMaxTime += 5;
+ }
+
+ thread_length = parseInt(total_replies) + 1;
+ //document.getElementsByClassName("thread")[0].firstChild.children[0].innerHTML = "("+thread_length+")";
+ new_unread = thread_length - thread_first_length;
+
+ if (new_unread)
+ document.title = "(" + new_unread + ") " + thread_title;
+ else
+ document.title = thread_title;
+}
+
+function notif(title, msg) {
+ var n = new Notification(title, {
+ body: msg
+ });
+ setTimeout(n.close.bind(n), 10000);
+}
+
+function counter() {
+ if (refreshTime < 1) {
+ loadJSON();
+ } else {
+ refreshTime--;
+ document.getElementById("counter").innerHTML = (refreshTime + 1);
+ }
+}
+
+function detectService() {
+ if (document.body.className === "threadpage") {
+ if (!document.getElementById("n")) return;
+ thread_title = document.title;
+ thread_length = parseInt(document.getElementsByClassName("thread")[0].dataset.length);
+ thread_first_length = thread_length;
+ replylist = document.getElementsByClassName("reply");
+ lastr = replylist[replylist.length - 1].textContent;
+ thread_lastreply = parseInt(lastr.substr(0, lastr.indexOf(" :")));
+ if (thread_length == thread_lastreply) {
+ serviceType = 2;
+ document.getElementById("n").addEventListener("click", checkNew);
+ var footer = document.getElementsByClassName("lastposts")[0];
+ var in1 = document.createElement("input");
+ in1.id = "autorefresh";
+ in1.setAttribute("type", "checkbox");
+ in1.addEventListener("click", autoRefresh);
+ in1.style.display = "none";
+ var in2 = document.createElement("label");
+ in2.id = "n2";
+ in2.setAttribute("for", "autorefresh");
+ in2.style.marginRight = "4px";
+ in2.style.cursor = "pointer";
+ in2.textContent = "Auto refresh";
+ var in3 = document.createElement("span");
+ in3.id = "counter";
+ in3.style.position = "absolute";
+ in3.textContent = "OFF";
+ footer.appendChild(document.createTextNode(" | "));
+ footer.appendChild(in1);
+ footer.appendChild(in2);
+ footer.appendChild(in3);
+ return true;
+ } else {
+ return false;
+ }
+ } else if (document.body.className === "res") {
+ serviceType = 3;
+ thread_title = document.title;
+ thread_length = parseInt(document.getElementsByClassName("thread")[0].dataset.length);
+ thread_first_length = thread_length;
+ replylist = document.getElementsByClassName("thread");
+ replylist += document.getElementsByClassName("reply");
+ var footer = document.getElementsByClassName("nav")[0];
+ var mnl = document.createElement("a");
+ mnl.id = "shownew";
+ mnl.href = "#";
+ mnl.textContent = "Ver nuevos posts";
+ var in1 = document.createElement("input");
+ in1.id = "autorefresh";
+ in1.setAttribute("type", "checkbox");
+ in1.addEventListener("click", autoRefresh);
+ in1.style.display = "none";
+ var in2 = document.createElement("label");
+ in2.setAttribute("for", "autorefresh");
+ in2.style.cursor = "pointer";
+ in2.title = "Ver nuevos posts automáticamente";
+ in2.textContent = "Auto";
+ var in4 = document.createElement("span");
+ in4.id = "counter";
+ in4.textContent = "OFF";
+ footer.appendChild(document.createTextNode(" ["));
+ footer.appendChild(mnl);
+ document.getElementById("shownew").addEventListener("click", checkNew);
+ footer.appendChild(document.createTextNode("] ["));
+ footer.appendChild(in1);
+ footer.appendChild(in2);
+ footer.appendChild(document.createTextNode("] "));
+ footer.appendChild(in4);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+function startCounter() {
+ refreshTime = refreshMaxTime;
+ counter();
+ refreshInterval = setInterval(counter, 1000);
+}
+
+function stopCounter(str) {
+ clearInterval(refreshInterval);
+ document.getElementById("counter").innerHTML = str;
+}
+
+function autoRefresh(e) {
+ chk_snd = document.getElementById("autosound");
+ if (document.getElementById("autorefresh").checked) {
+ if (chk_snd)
+ chk_snd.disabled = false;
+ Notification.requestPermission();
+ lastTime = Math.floor(Date.now() / 1000);
+ refreshTime = refreshMaxTime;
+ startCounter();
+ } else {
+ if (chk_snd)
+ document.getElementById("autosound").disabled = true;
+ stopCounter("OFF");
+ }
+}
+
+http_request.onreadystatechange = function() {
+ if (http_request.readyState == 4) {
+ var jsonObj = JSON.parse(http_request.responseText);
+ if (jsonObj.state == "success") {
+ if (serviceType == 2 || serviceType == 3)
+ updateThread(jsonObj.posts, jsonObj.total_replies, jsonObj.time);
+ lastTime = jsonObj.time;
+ if (chk.checked)
+ startCounter();
+ }
+ if (!chk.checked) {
+ document.getElementById("counter").innerText = "OFF";
+ }
+ manual = 0;
+ }
+}
+document.addEventListener("DOMContentLoaded", function() {
+ if (!detectService()) return;
+
+ chk = document.getElementById("autorefresh");
+ chk_snd = document.getElementById("autosound");
+
+ if (localStorage.getItem("autorefresh")) {
+ document.getElementById("autorefresh").checked = true;
+ autoRefresh();
+ }
+ if (!chk_snd) return;
+ if (localStorage.getItem("mainpage_nosound"))
+ document.getElementById("autosound").checked = false;
+});
+
+window.addEventListener("unload", function() {
+ if (!serviceType) return;
+
+ chk = document.getElementById("autorefresh");
+ chk_snd = document.getElementById("autosound");
+
+ if (chk.checked)
+ localStorage.setItem("autorefresh", true);
+ else
+ localStorage.removeItem("autorefresh");
+ if (!chk_snd) return;
+ if (!document.getElementById("autosound").checked)
+ localStorage.setItem("mainpage_nosound", true);
+ else
+ localStorage.removeItem("mainpage_nosound");
+}); \ No newline at end of file
diff --git a/static/js/home.js b/static/js/home.js
new file mode 100644
index 0000000..0c921ec
--- /dev/null
+++ b/static/js/home.js
@@ -0,0 +1,173 @@
+console.log("%c¡Es calidad BaI!", "font-size: 50px; font-weight: bold;");
+
+function set_stylesheet(styletitle) {
+ opcs.style = styletitle;
+ parse();
+ var links=document.getElementsByTagName("link");
+ var found=false;
+ for(var i=0;i<links.length;i++) {
+ var rel=links[i].getAttribute("rel");
+ var title=links[i].getAttribute("title");
+ if(rel.indexOf("style")!=-1&&title) {
+ links[i].disabled=true; // IE needs this to work. IE needs to die.
+ if(styletitle==title) { links[i].disabled=false; found=true; }
+ }
+ }
+}
+
+function get_active_stylesheet() {
+ var links=document.getElementsByTagName("link");
+ for(var i=0;i<links.length;i++) {
+ var rel=links[i].getAttribute("rel");
+ var title=links[i].getAttribute("title");
+ if(rel.indexOf("style")!=-1&&title&&!links[i].disabled) return title;
+ }
+ return null;
+}
+
+function check_news() {
+ var last_t = opcs.last;
+ var items = document.getElementsByClassName('ni');
+ var dates = document.getElementsByClassName('ni-d');
+ for(var i=0; i<items.length; i++) if(parseInt(items[i].dataset.t) > last_t) {
+ items[i].className += ' urgent';
+ dates[i].innerHTML = '<img src="/new.gif" style="width:18px;height:7px;"><br />' + dates[i].innerHTML;
+ }
+ opcs.last = Date.now() / 1000 | 0;
+ parse();
+}
+
+var lastTime = 0;
+var refreshInterval;
+var refreshMaxTime = 30;
+var refreshTime;
+var unread = {};
+var last_threads = 0;
+var last_serverTime = 0;
+var http_request = new XMLHttpRequest();
+
+function loadJSON() {
+ stopCounter("...");
+ var data_file = "/cgi/api/lastage?time=" + lastTime + "&limit=" + document.getElementById("limit").value;
+ http_request.open("GET", data_file, true);
+ http_request.send();
+}
+
+function setRead(threadId) {
+ if (threadId in unread) {
+ unread[threadId] = false;
+ updatePostList(last_threads, last_serverTime);
+ }
+}
+
+function updatePostList(threads, serverTime) {
+ if (refreshMaxTime <= 120) refreshMaxTime += 5;
+ var arrayLength = threads.length;
+ if (!arrayLength) return;
+
+ html = "";
+ last_threads = threads;
+ last_serverTime = serverTime;
+
+ var newposts = 0;
+ var newTitle = "Bienvenido a Internet BBS/IB";
+ var new_unread = false;
+ var news = [];
+
+ for (var i = 0; i < arrayLength; i++) {
+ thread = threads[i];
+ if (thread.bumped >= lastTime) {
+ unread[thread.id] = true;
+ news.push('- ' + thread.board_fulln + ': ' + thread.content);
+ new_unread = true;
+ }
+ if (unread[thread.id]) html += '<span class="new">';
+ html += '<a href="' + thread.url + '" class="thread" data-brd="' + thread.board_fulln + '" data-unix="' + thread.timestamp + '" data-last="' + thread.bumped + '" data-img="' + thread.thumb + '"><span class="brd">[' + thread.board_name + ']</span> <span class="cont">' + thread.content + '</span> <span class="rep">(' + thread.length + ')</span></a>';
+ if (unread[thread.id]) {
+ html += '</span>';
+ newposts++;
+ }
+ }
+ if (newposts) newTitle = '(' + newposts + ') ' + newTitle;
+ if (new_unread) {
+ document.getElementById("newposts").style = "color:red";
+ notif('Bienvenido a Internet BBS/IB', 'Hay nuevos mensajes:\n' + news.join('\n'));
+ refreshMaxTime = 10;
+ if (document.getElementById('autosound').checked) {
+ document.getElementById("machina").volume = 0.6;
+ document.getElementById("machina").play();
+ }
+ }
+ window.parent.document.title = newTitle;
+ document.title = newTitle;
+ document.getElementById("postlist").innerHTML = html;
+}
+
+function notif(title, msg) {
+ var n = new Notification(title, { body: msg });
+ setTimeout(n.close.bind(n), 10000);
+}
+
+function counter() {
+ if (refreshTime < 1) loadJSON();
+ else {
+ refreshTime--;
+ document.getElementById("counter").innerHTML = "– " + (refreshTime + 1);
+ }
+}
+
+function startCounter() {
+ refreshTime = refreshMaxTime;
+ counter();
+ refreshInterval = setInterval(counter, 1000);
+}
+
+function stopCounter(str) {
+ clearInterval(refreshInterval);
+ document.getElementById("counter").innerHTML = str;
+}
+
+function autoRefresh(e) {
+ if (chk.checked) {
+ if (chk_snd) chk_snd.disabled = false;
+ Notification.requestPermission();
+ lastTime = Math.floor(Date.now() / 1000);
+ refreshTime = refreshMaxTime;
+ startCounter();
+ } else {
+ if (chk_snd) chk_snd.disabled = true;
+ stopCounter("");
+ }
+}
+
+http_request.onreadystatechange = function() {
+ if (http_request.readyState == 4) {
+ var jsonObj = JSON.parse(http_request.responseText);
+ if (jsonObj.state == "success") {
+ updatePostList(jsonObj.threads, jsonObj.time);
+ lastTime = jsonObj.time;
+ if (chk.checked) startCounter();
+ }
+ }
+}
+
+function parse() { localStorage.setItem("home", JSON.stringify(opcs)); }
+
+document.addEventListener("DOMContentLoaded", function() {
+ if (localStorage.hasOwnProperty("home")) opcs=JSON.parse(localStorage.getItem("home"));
+ else { opcs={"style":"IB","auto":false,"sound":false,"last":0}; parse(); }
+ set_stylesheet(opcs.style);
+
+ var css = document.getElementById("change_style").getElementsByTagName("a");
+ for(var j=0;j<css.length;j++) {
+ css[j].addEventListener("click", function(e) { e.preventDefault(); set_stylesheet(this.textContent); });
+ }
+ document.getElementById("autorefresh").addEventListener("click", function(e) { opcs.auto=!opcs.auto; autoRefresh(); parse(); });
+ document.getElementById("autosound").addEventListener("click", function(e) { opcs.sound=!opcs.sound; parse(); });
+ check_news();
+
+ chk=document.getElementById("autorefresh");
+ chk_snd=document.getElementById("autosound");
+ if (opcs.auto) { chk.checked=true; autoRefresh(); } else chk.checked=false;
+ if (opcs.sound) chk_snd.checked=true; else chk_snd.checked=false;
+}); \ No newline at end of file
diff --git a/static/js/jquery.js b/static/js/jquery.js
new file mode 100644
index 0000000..4d8cc18
--- /dev/null
+++ b/static/js/jquery.js
@@ -0,0 +1,545 @@
+(function(window,undefined){var rootjQuery,readyList,core_strundefined=typeof undefined,location=window.location,document=window.document,docElem=document.documentElement,_jQuery=window.jQuery,_$=window.$,class2type={},core_deletedIds=[],core_version="2.0.2",core_concat=core_deletedIds.concat,core_push=core_deletedIds.push,core_slice=core_deletedIds.slice,core_indexOf=core_deletedIds.indexOf,core_toString=class2type.toString,core_hasOwn=class2type.hasOwnProperty,core_trim=core_version.trim,jQuery=function(selector,context){return new jQuery.fn.init(selector,context,rootjQuery);},core_pnum=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,core_rnotwhite=/\S+/g,rquickExpr=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,rsingleTag=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,rmsPrefix=/^-ms-/,rdashAlpha=/-([\da-z])/gi,fcamelCase=function(all,letter){return letter.toUpperCase();},completed=function(){document.removeEventListener("DOMContentLoaded",completed,false);window.removeEventListener("load",completed,false);jQuery.ready();};jQuery.fn=jQuery.prototype={jquery:core_version,constructor:jQuery,init:function(selector,context,rootjQuery){var match,elem;if(!selector){return this;}
+if(typeof selector==="string"){if(selector.charAt(0)==="<"&&selector.charAt(selector.length-1)===">"&&selector.length>=3){match=[null,selector,null];}else{match=rquickExpr.exec(selector);}
+if(match&&(match[1]||!context)){if(match[1]){context=context instanceof jQuery?context[0]:context;jQuery.merge(this,jQuery.parseHTML(match[1],context&&context.nodeType?context.ownerDocument||context:document,true));if(rsingleTag.test(match[1])&&jQuery.isPlainObject(context)){for(match in context){if(jQuery.isFunction(this[match])){this[match](context[match]);}else{this.attr(match,context[match]);}}}
+return this;}else{elem=document.getElementById(match[2]);if(elem&&elem.parentNode){this.length=1;this[0]=elem;}
+this.context=document;this.selector=selector;return this;}}else{if(!context||context.jquery){return(context||rootjQuery).find(selector);}else{return this.constructor(context).find(selector);}}}else{if(selector.nodeType){this.context=this[0]=selector;this.length=1;return this;}else{if(jQuery.isFunction(selector)){return rootjQuery.ready(selector);}}}
+if(selector.selector!==undefined){this.selector=selector.selector;this.context=selector.context;}
+return jQuery.makeArray(selector,this);},selector:"",length:0,toArray:function(){return core_slice.call(this);},get:function(num){return num==null?this.toArray():num<0?this[this.length+num]:this[num];},pushStack:function(elems){var ret=jQuery.merge(this.constructor(),elems);ret.prevObject=this;ret.context=this.context;return ret;},each:function(callback,args){return jQuery.each(this,callback,args);},ready:function(fn){jQuery.ready.promise().done(fn);return this;},slice:function(){return this.pushStack(core_slice.apply(this,arguments));},first:function(){return this.eq(0);},last:function(){return this.eq(-1);},eq:function(i){var len=this.length,j=+i+(i<0?len:0);return this.pushStack(j>=0&&j<len?[this[j]]:[]);},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},end:function(){return this.prevObject||this.constructor(null);},push:core_push,sort:[].sort,splice:[].splice};jQuery.fn.init.prototype=jQuery.fn;jQuery.extend=jQuery.fn.extend=function(){var options,name,src,copy,copyIsArray,clone,target=arguments[0]||{},i=1,length=arguments.length,deep=false;if(typeof target==="boolean"){deep=target;target=arguments[1]||{};i=2;}
+if(typeof target!=="object"&&!jQuery.isFunction(target)){target={};}
+if(length===i){target=this;--i;}
+for(;i<length;i++){if((options=arguments[i])!=null){for(name in options){src=target[name];copy=options[name];if(target===copy){continue;}
+if(deep&&copy&&(jQuery.isPlainObject(copy)||(copyIsArray=jQuery.isArray(copy)))){if(copyIsArray){copyIsArray=false;clone=src&&jQuery.isArray(src)?src:[];}else{clone=src&&jQuery.isPlainObject(src)?src:{};}
+target[name]=jQuery.extend(deep,clone,copy);}else{if(copy!==undefined){target[name]=copy;}}}}}
+return target;};jQuery.extend({expando:"jQuery"+(core_version+Math.random()).replace(/\D/g,""),noConflict:function(deep){if(window.$===jQuery){window.$=_$;}
+if(deep&&window.jQuery===jQuery){window.jQuery=_jQuery;}
+return jQuery;},isReady:false,readyWait:1,holdReady:function(hold){if(hold){jQuery.readyWait++;}else{jQuery.ready(true);}},ready:function(wait){if(wait===true?--jQuery.readyWait:jQuery.isReady){return;}
+jQuery.isReady=true;if(wait!==true&&--jQuery.readyWait>0){return;}
+readyList.resolveWith(document,[jQuery]);if(jQuery.fn.trigger){jQuery(document).trigger("ready").off("ready");}},isFunction:function(obj){return jQuery.type(obj)==="function";},isArray:Array.isArray,isWindow:function(obj){return obj!=null&&obj===obj.window;},isNumeric:function(obj){return!isNaN(parseFloat(obj))&&isFinite(obj);},type:function(obj){if(obj==null){return String(obj);}
+return typeof obj==="object"||typeof obj==="function"?class2type[core_toString.call(obj)]||"object":typeof obj;},isPlainObject:function(obj){if(jQuery.type(obj)!=="object"||obj.nodeType||jQuery.isWindow(obj)){return false;}
+try{if(obj.constructor&&!core_hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){return false;}}catch(e){return false;}
+return true;},isEmptyObject:function(obj){var name;for(name in obj){return false;}
+return true;},error:function(msg){throw new Error(msg);},parseHTML:function(data,context,keepScripts){if(!data||typeof data!=="string"){return null;}
+if(typeof context==="boolean"){keepScripts=context;context=false;}
+context=context||document;var parsed=rsingleTag.exec(data),scripts=!keepScripts&&[];if(parsed){return[context.createElement(parsed[1])];}
+parsed=jQuery.buildFragment([data],context,scripts);if(scripts){jQuery(scripts).remove();}
+return jQuery.merge([],parsed.childNodes);},parseJSON:JSON.parse,parseXML:function(data){var xml,tmp;if(!data||typeof data!=="string"){return null;}
+try{tmp=new DOMParser;xml=tmp.parseFromString(data,"text/xml");}catch(e){xml=undefined;}
+if(!xml||xml.getElementsByTagName("parsererror").length){jQuery.error("Invalid XML: "+data);}
+return xml;},noop:function(){},globalEval:function(code){var script,indirect=eval;code=jQuery.trim(code);if(code){if(code.indexOf("use strict")===1){script=document.createElement("script");script.text=code;document.head.appendChild(script).parentNode.removeChild(script);}else{indirect(code);}}},camelCase:function(string){return string.replace(rmsPrefix,"ms-").replace(rdashAlpha,fcamelCase);},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toLowerCase()===name.toLowerCase();},each:function(obj,callback,args){var value,i=0,length=obj.length,isArray=isArraylike(obj);if(args){if(isArray){for(;i<length;i++){value=callback.apply(obj[i],args);if(value===false){break;}}}else{for(i in obj){value=callback.apply(obj[i],args);if(value===false){break;}}}}else{if(isArray){for(;i<length;i++){value=callback.call(obj[i],i,obj[i]);if(value===false){break;}}}else{for(i in obj){value=callback.call(obj[i],i,obj[i]);if(value===false){break;}}}}
+return obj;},trim:function(text){return text==null?"":core_trim.call(text);},makeArray:function(arr,results){var ret=results||[];if(arr!=null){if(isArraylike(Object(arr))){jQuery.merge(ret,typeof arr==="string"?[arr]:arr);}else{core_push.call(ret,arr);}}
+return ret;},inArray:function(elem,arr,i){return arr==null?-1:core_indexOf.call(arr,elem,i);},merge:function(first,second){var l=second.length,i=first.length,j=0;if(typeof l==="number"){for(;j<l;j++){first[i++]=second[j];}}else{while(second[j]!==undefined){first[i++]=second[j++];}}
+first.length=i;return first;},grep:function(elems,callback,inv){var retVal,ret=[],i=0,length=elems.length;inv=!!inv;for(;i<length;i++){retVal=!!callback(elems[i],i);if(inv!==retVal){ret.push(elems[i]);}}
+return ret;},map:function(elems,callback,arg){var value,i=0,length=elems.length,isArray=isArraylike(elems),ret=[];if(isArray){for(;i<length;i++){value=callback(elems[i],i,arg);if(value!=null){ret[ret.length]=value;}}}else{for(i in elems){value=callback(elems[i],i,arg);if(value!=null){ret[ret.length]=value;}}}
+return core_concat.apply([],ret);},guid:1,proxy:function(fn,context){var tmp,args,proxy;if(typeof context==="string"){tmp=fn[context];context=fn;fn=tmp;}
+if(!jQuery.isFunction(fn)){return undefined;}
+args=core_slice.call(arguments,2);proxy=function(){return fn.apply(context||this,args.concat(core_slice.call(arguments)));};proxy.guid=fn.guid=fn.guid||jQuery.guid++;return proxy;},access:function(elems,fn,key,value,chainable,emptyGet,raw){var i=0,length=elems.length,bulk=key==null;if(jQuery.type(key)==="object"){chainable=true;for(i in key){jQuery.access(elems,fn,i,key[i],true,emptyGet,raw);}}else{if(value!==undefined){chainable=true;if(!jQuery.isFunction(value)){raw=true;}
+if(bulk){if(raw){fn.call(elems,value);fn=null;}else{bulk=fn;fn=function(elem,key,value){return bulk.call(jQuery(elem),value);};}}
+if(fn){for(;i<length;i++){fn(elems[i],key,raw?value:value.call(elems[i],i,fn(elems[i],key)));}}}}
+return chainable?elems:bulk?fn.call(elems):length?fn(elems[0],key):emptyGet;},now:Date.now,swap:function(elem,options,callback,args){var ret,name,old={};for(name in options){old[name]=elem.style[name];elem.style[name]=options[name];}
+ret=callback.apply(elem,args||[]);for(name in options){elem.style[name]=old[name];}
+return ret;}});jQuery.ready.promise=function(obj){if(!readyList){readyList=jQuery.Deferred();if(document.readyState==="complete"){setTimeout(jQuery.ready);}else{document.addEventListener("DOMContentLoaded",completed,false);window.addEventListener("load",completed,false);}}
+return readyList.promise(obj);};jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(i,name){class2type["[object "+name+"]"]=name.toLowerCase();});function isArraylike(obj){var length=obj.length,type=jQuery.type(obj);if(jQuery.isWindow(obj)){return false;}
+if(obj.nodeType===1&&length){return true;}
+return type==="array"||type!=="function"&&(length===0||typeof length==="number"&&length>0&&length-1 in obj);}
+rootjQuery=jQuery(document);(function(window,undefined){var i,support,cachedruns,Expr,getText,isXML,compile,outermostContext,sortInput,setDocument,document,docElem,documentIsHTML,rbuggyQSA,rbuggyMatches,matches,contains,expando="sizzle"+ -new Date,preferredDoc=window.document,dirruns=0,done=0,classCache=createCache(),tokenCache=createCache(),compilerCache=createCache(),hasDuplicate=false,sortOrder=function(){return 0;},strundefined=typeof undefined,MAX_NEGATIVE=1<<31,hasOwn={}.hasOwnProperty,arr=[],pop=arr.pop,push_native=arr.push,push=arr.push,slice=arr.slice,indexOf=arr.indexOf||function(elem){var i=0,len=this.length;for(;i<len;i++){if(this[i]===elem){return i;}}
+return-1;},booleans="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",whitespace="[\\x20\\t\\r\\n\\f]",characterEncoding="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",identifier=characterEncoding.replace("w","w#"),attributes="\\["+whitespace+"*("+characterEncoding+")"+whitespace+"*(?:([*^$|!~]?=)"+whitespace+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+identifier+")|)|)"+whitespace+"*\\]",pseudos=":("+
+characterEncoding+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+attributes.replace(3,8)+")*)|.*)\\)|)",rtrim=new RegExp("^"+whitespace+"+|((?:^|[^\\\\])(?:\\\\.)*)"+whitespace+"+$","g"),rcomma=new RegExp("^"+whitespace+"*,"+whitespace+"*"),rcombinators=new RegExp("^"+whitespace+"*([>+~]|"+whitespace+")"+whitespace+"*"),rsibling=new RegExp(whitespace+"*[+~]"),rattributeQuotes=new RegExp("="+whitespace+"*([^\\]'\"]*)"+
+whitespace+"*\\]","g"),rpseudo=new RegExp(pseudos),ridentifier=new RegExp("^"+identifier+"$"),matchExpr={"ID":new RegExp("^#("+characterEncoding+")"),"CLASS":new RegExp("^\\.("+characterEncoding+")"),"TAG":new RegExp("^("+characterEncoding.replace("w","w*")+")"),"ATTR":new RegExp("^"+attributes),"PSEUDO":new RegExp("^"+pseudos),"CHILD":new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+whitespace+"*(even|odd|(([+-]|)(\\d*)n|)"+whitespace+"*(?:([+-]|)"+whitespace+"*(\\d+)|))"+whitespace+"*\\)|)","i"),"bool":new RegExp("^(?:"+booleans+")$","i"),"needsContext":new RegExp("^"+whitespace+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+whitespace+"*((?:-\\d)?\\d*)"+whitespace+"*\\)|)(?=[^-]|$)","i")},rnative=/^[^{]+\{\s*\[native \w/,rquickExpr=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,rinputs=/^(?:input|select|textarea|button)$/i,rheader=/^h\d$/i,rescape=/'|\\/g,runescape=new RegExp("\\\\([\\da-f]{1,6}"+
+whitespace+"?|("+whitespace+")|.)","ig"),funescape=function(_,escaped,escapedWhitespace){var high="0x"+escaped-65536;return high!==high||escapedWhitespace?escaped:high<0?String.fromCharCode(high+65536):String.fromCharCode(high>>10|55296,high&1023|56320);};try{push.apply(arr=slice.call(preferredDoc.childNodes),preferredDoc.childNodes);arr[preferredDoc.childNodes.length].nodeType;}catch(e){push={apply:arr.length?function(target,els){push_native.apply(target,slice.call(els));}:function(target,els){var j=target.length,i=0;while(target[j++]=els[i++]){}
+target.length=j-1;}};}
+function Sizzle(selector,context,results,seed){var match,elem,m,nodeType,i,groups,old,nid,newContext,newSelector;if((context?context.ownerDocument||context:preferredDoc)!==document){setDocument(context);}
+context=context||document;results=results||[];if(!selector||typeof selector!=="string"){return results;}
+if((nodeType=context.nodeType)!==1&&nodeType!==9){return[];}
+if(documentIsHTML&&!seed){if(match=rquickExpr.exec(selector)){if(m=match[1]){if(nodeType===9){elem=context.getElementById(m);if(elem&&elem.parentNode){if(elem.id===m){results.push(elem);return results;}}else{return results;}}else{if(context.ownerDocument&&(elem=context.ownerDocument.getElementById(m))&&contains(context,elem)&&elem.id===m){results.push(elem);return results;}}}else{if(match[2]){push.apply(results,context.getElementsByTagName(selector));return results;}else{if((m=match[3])&&support.getElementsByClassName&&context.getElementsByClassName){push.apply(results,context.getElementsByClassName(m));return results;}}}}
+if(support.qsa&&(!rbuggyQSA||!rbuggyQSA.test(selector))){nid=old=expando;newContext=context;newSelector=nodeType===9&&selector;if(nodeType===1&&context.nodeName.toLowerCase()!=="object"){groups=tokenize(selector);if(old=context.getAttribute("id")){nid=old.replace(rescape,"\\$&");}else{context.setAttribute("id",nid);}
+nid="[id='"+nid+"'] ";i=groups.length;while(i--){groups[i]=nid+toSelector(groups[i]);}
+newContext=rsibling.test(selector)&&context.parentNode||context;newSelector=groups.join(",");}
+if(newSelector){try{push.apply(results,newContext.querySelectorAll(newSelector));return results;}catch(qsaError){}finally{if(!old){context.removeAttribute("id");}}}}}
+return select(selector.replace(rtrim,"$1"),context,results,seed);}
+function isNative(fn){return rnative.test(fn+"");}
+function createCache(){var keys=[];function cache(key,value){if(keys.push(key+=" ")>Expr.cacheLength){delete cache[keys.shift()];}
+return cache[key]=value;}
+return cache;}
+function markFunction(fn){fn[expando]=true;return fn;}
+function assert(fn){var div=document.createElement("div");try{return!!fn(div);}catch(e$0){return false;}finally{if(div.parentNode){div.parentNode.removeChild(div);}
+div=null;}}
+function addHandle(attrs,handler,test){attrs=attrs.split("|");var current,i=attrs.length,setHandle=test?null:handler;while(i--){if(!(current=Expr.attrHandle[attrs[i]])||current===handler){Expr.attrHandle[attrs[i]]=setHandle;}}}
+function boolHandler(elem,name){var val=elem.getAttributeNode(name);return val&&val.specified?val.value:elem[name]===true?name.toLowerCase():null;}
+function interpolationHandler(elem,name){return elem.getAttribute(name,name.toLowerCase()==="type"?1:2);}
+function valueHandler(elem){if(elem.nodeName.toLowerCase()==="input"){return elem.defaultValue;}}
+function siblingCheck(a,b){var cur=b&&a,diff=cur&&a.nodeType===1&&b.nodeType===1&&(~b.sourceIndex||MAX_NEGATIVE)-(~a.sourceIndex||MAX_NEGATIVE);if(diff){return diff;}
+if(cur){while(cur=cur.nextSibling){if(cur===b){return-1;}}}
+return a?1:-1;}
+function createInputPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type===type;};}
+function createButtonPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return(name==="input"||name==="button")&&elem.type===type;};}
+function createPositionalPseudo(fn){return markFunction(function(argument){argument=+argument;return markFunction(function(seed,matches){var j,matchIndexes=fn([],seed.length,argument),i=matchIndexes.length;while(i--){if(seed[j=matchIndexes[i]]){seed[j]=!(matches[j]=seed[j]);}}});});}
+isXML=Sizzle.isXML=function(elem){var documentElement=elem&&(elem.ownerDocument||elem).documentElement;return documentElement?documentElement.nodeName!=="HTML":false;};support=Sizzle.support={};setDocument=Sizzle.setDocument=function(node){var doc=node?node.ownerDocument||node:preferredDoc,parent=doc.parentWindow;if(doc===document||doc.nodeType!==9||!doc.documentElement){return document;}
+document=doc;docElem=doc.documentElement;documentIsHTML=!isXML(doc);if(parent&&parent.frameElement){parent.attachEvent("onbeforeunload",function(){setDocument();});}
+support.attributes=assert(function(div){div.innerHTML="<a href='#'></a>";addHandle("type|href|height|width",interpolationHandler,div.firstChild.getAttribute("href")==="#");addHandle(booleans,boolHandler,div.getAttribute("disabled")==null);div.className="i";return!div.getAttribute("className");});support.input=assert(function(div){div.innerHTML="<input>";div.firstChild.setAttribute("value","");return div.firstChild.getAttribute("value")==="";});addHandle("value",valueHandler,support.attributes&&support.input);support.getElementsByTagName=assert(function(div){div.appendChild(doc.createComment(""));return!div.getElementsByTagName("*").length;});support.getElementsByClassName=assert(function(div){div.innerHTML="<div class='a'></div><div class='a i'></div>";div.firstChild.className="i";return div.getElementsByClassName("i").length===2;});support.getById=assert(function(div){docElem.appendChild(div).id=expando;return!doc.getElementsByName||!doc.getElementsByName(expando).length;});if(support.getById){Expr.find["ID"]=function(id,context){if(typeof context.getElementById!==strundefined&&documentIsHTML){var m=context.getElementById(id);return m&&m.parentNode?[m]:[];}};Expr.filter["ID"]=function(id){var attrId=id.replace(runescape,funescape);return function(elem){return elem.getAttribute("id")===attrId;};};}else{delete Expr.find["ID"];Expr.filter["ID"]=function(id){var attrId=id.replace(runescape,funescape);return function(elem){var node=typeof elem.getAttributeNode!==strundefined&&elem.getAttributeNode("id");return node&&node.value===attrId;};};}
+Expr.find["TAG"]=support.getElementsByTagName?function(tag,context){if(typeof context.getElementsByTagName!==strundefined){return context.getElementsByTagName(tag);}}:function(tag,context){var elem,tmp=[],i=0,results=context.getElementsByTagName(tag);if(tag==="*"){while(elem=results[i++]){if(elem.nodeType===1){tmp.push(elem);}}
+return tmp;}
+return results;};Expr.find["CLASS"]=support.getElementsByClassName&&function(className,context){if(typeof context.getElementsByClassName!==strundefined&&documentIsHTML){return context.getElementsByClassName(className);}};rbuggyMatches=[];rbuggyQSA=[];if(support.qsa=isNative(doc.querySelectorAll)){assert(function(div){div.innerHTML="<select><option selected=''></option></select>";if(!div.querySelectorAll("[selected]").length){rbuggyQSA.push("\\["+whitespace+"*(?:value|"+booleans+")");}
+if(!div.querySelectorAll(":checked").length){rbuggyQSA.push(":checked");}});assert(function(div){var input=doc.createElement("input");input.setAttribute("type","hidden");div.appendChild(input).setAttribute("t","");if(div.querySelectorAll("[t^='']").length){rbuggyQSA.push("[*^$]="+whitespace+"*(?:''|\"\")");}
+if(!div.querySelectorAll(":enabled").length){rbuggyQSA.push(":enabled",":disabled");}
+div.querySelectorAll("*,:x");rbuggyQSA.push(",.*:");});}
+if(support.matchesSelector=isNative(matches=docElem.webkitMatchesSelector||docElem.mozMatchesSelector||docElem.oMatchesSelector||docElem.msMatchesSelector)){assert(function(div){support.disconnectedMatch=matches.call(div,"div");matches.call(div,"[s!='']:x");rbuggyMatches.push("!=",pseudos);});}
+rbuggyQSA=rbuggyQSA.length&&new RegExp(rbuggyQSA.join("|"));rbuggyMatches=rbuggyMatches.length&&new RegExp(rbuggyMatches.join("|"));contains=isNative(docElem.contains)||docElem.compareDocumentPosition?function(a,b){var adown=a.nodeType===9?a.documentElement:a,bup=b&&b.parentNode;return a===bup||!!(bup&&bup.nodeType===1&&(adown.contains?adown.contains(bup):a.compareDocumentPosition&&a.compareDocumentPosition(bup)&16));}:function(a,b){if(b){while(b=b.parentNode){if(b===a){return true;}}}
+return false;};support.sortDetached=assert(function(div1){return div1.compareDocumentPosition(doc.createElement("div"))&1;});sortOrder=docElem.compareDocumentPosition?function(a,b){if(a===b){hasDuplicate=true;return 0;}
+var compare=b.compareDocumentPosition&&a.compareDocumentPosition&&a.compareDocumentPosition(b);if(compare){if(compare&1||!support.sortDetached&&b.compareDocumentPosition(a)===compare){if(a===doc||contains(preferredDoc,a)){return-1;}
+if(b===doc||contains(preferredDoc,b)){return 1;}
+return sortInput?indexOf.call(sortInput,a)-indexOf.call(sortInput,b):0;}
+return compare&4?-1:1;}
+return a.compareDocumentPosition?-1:1;}:function(a,b){var cur,i=0,aup=a.parentNode,bup=b.parentNode,ap=[a],bp=[b];if(a===b){hasDuplicate=true;return 0;}else{if(!aup||!bup){return a===doc?-1:b===doc?1:aup?-1:bup?1:sortInput?indexOf.call(sortInput,a)-indexOf.call(sortInput,b):0;}else{if(aup===bup){return siblingCheck(a,b);}}}
+cur=a;while(cur=cur.parentNode){ap.unshift(cur);}
+cur=b;while(cur=cur.parentNode){bp.unshift(cur);}
+while(ap[i]===bp[i]){i++;}
+return i?siblingCheck(ap[i],bp[i]):ap[i]===preferredDoc?-1:bp[i]===preferredDoc?1:0;};return doc;};Sizzle.matches=function(expr,elements){return Sizzle(expr,null,null,elements);};Sizzle.matchesSelector=function(elem,expr){if((elem.ownerDocument||elem)!==document){setDocument(elem);}
+expr=expr.replace(rattributeQuotes,"='$1']");if(support.matchesSelector&&documentIsHTML&&(!rbuggyMatches||!rbuggyMatches.test(expr))&&(!rbuggyQSA||!rbuggyQSA.test(expr))){try{var ret=matches.call(elem,expr);if(ret||support.disconnectedMatch||elem.document&&elem.document.nodeType!==11){return ret;}}catch(e$1){}}
+return Sizzle(expr,document,null,[elem]).length>0;};Sizzle.contains=function(context,elem){if((context.ownerDocument||context)!==document){setDocument(context);}
+return contains(context,elem);};Sizzle.attr=function(elem,name){if((elem.ownerDocument||elem)!==document){setDocument(elem);}
+var fn=Expr.attrHandle[name.toLowerCase()],val=fn&&hasOwn.call(Expr.attrHandle,name.toLowerCase())?fn(elem,name,!documentIsHTML):undefined;return val===undefined?support.attributes||!documentIsHTML?elem.getAttribute(name):(val=elem.getAttributeNode(name))&&val.specified?val.value:null:val;};Sizzle.error=function(msg){throw new Error("Syntax error, unrecognized expression: "+msg);};Sizzle.uniqueSort=function(results){var elem,duplicates=[],j=0,i=0;hasDuplicate=!support.detectDuplicates;sortInput=!support.sortStable&&results.slice(0);results.sort(sortOrder);if(hasDuplicate){while(elem=results[i++]){if(elem===results[i]){j=duplicates.push(i);}}
+while(j--){results.splice(duplicates[j],1);}}
+return results;};getText=Sizzle.getText=function(elem){var node,ret="",i=0,nodeType=elem.nodeType;if(!nodeType){for(;node=elem[i];i++){ret+=getText(node);}}else{if(nodeType===1||nodeType===9||nodeType===11){if(typeof elem.textContent==="string"){return elem.textContent;}else{for(elem=elem.firstChild;elem;elem=elem.nextSibling){ret+=getText(elem);}}}else{if(nodeType===3||nodeType===4){return elem.nodeValue;}}}
+return ret;};Expr=Sizzle.selectors={cacheLength:50,createPseudo:markFunction,match:matchExpr,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:true}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:true},"~":{dir:"previousSibling"}},preFilter:{"ATTR":function(match){match[1]=match[1].replace(runescape,funescape);match[3]=(match[4]||match[5]||"").replace(runescape,funescape);if(match[2]==="~="){match[3]=" "+match[3]+" ";}
+return match.slice(0,4);},"CHILD":function(match){match[1]=match[1].toLowerCase();if(match[1].slice(0,3)==="nth"){if(!match[3]){Sizzle.error(match[0]);}
+match[4]=+(match[4]?match[5]+(match[6]||1):2*(match[3]==="even"||match[3]==="odd"));match[5]=+(match[7]+match[8]||match[3]==="odd");}else{if(match[3]){Sizzle.error(match[0]);}}
+return match;},"PSEUDO":function(match){var excess,unquoted=!match[5]&&match[2];if(matchExpr["CHILD"].test(match[0])){return null;}
+if(match[3]&&match[4]!==undefined){match[2]=match[4];}else{if(unquoted&&rpseudo.test(unquoted)&&(excess=tokenize(unquoted,true))&&(excess=unquoted.indexOf(")",unquoted.length-excess)-unquoted.length)){match[0]=match[0].slice(0,excess);match[2]=unquoted.slice(0,excess);}}
+return match.slice(0,3);}},filter:{"TAG":function(nodeNameSelector){var nodeName=nodeNameSelector.replace(runescape,funescape).toLowerCase();return nodeNameSelector==="*"?function(){return true;}:function(elem){return elem.nodeName&&elem.nodeName.toLowerCase()===nodeName;};},"CLASS":function(className){var pattern=classCache[className+" "];return pattern||(pattern=new RegExp("(^|"+whitespace+")"+className+"("+whitespace+"|$)"))&&classCache(className,function(elem){return pattern.test(typeof elem.className==="string"&&elem.className||typeof elem.getAttribute!==strundefined&&elem.getAttribute("class")||"");});},"ATTR":function(name,operator,check){return function(elem){var result=Sizzle.attr(elem,name);if(result==null){return operator==="!=";}
+if(!operator){return true;}
+result+="";return operator==="="?result===check:operator==="!="?result!==check:operator==="^="?check&&result.indexOf(check)===0:operator==="*="?check&&result.indexOf(check)>-1:operator==="$="?check&&result.slice(-check.length)===check:operator==="~="?(" "+result+" ").indexOf(check)>-1:operator==="|="?result===check||result.slice(0,check.length+1)===check+"-":false;};},"CHILD":function(type,what,argument,first,last){var simple=type.slice(0,3)!=="nth",forward=type.slice(-4)!=="last",ofType=what==="of-type";return first===1&&last===0?function(elem){return!!elem.parentNode;}:function(elem,context,xml){var cache,outerCache,node,diff,nodeIndex,start,dir=simple!==forward?"nextSibling":"previousSibling",parent=elem.parentNode,name=ofType&&elem.nodeName.toLowerCase(),useCache=!xml&&!ofType;if(parent){if(simple){while(dir){node=elem;while(node=node[dir]){if(ofType?node.nodeName.toLowerCase()===name:node.nodeType===1){return false;}}
+start=dir=type==="only"&&!start&&"nextSibling";}
+return true;}
+start=[forward?parent.firstChild:parent.lastChild];if(forward&&useCache){outerCache=parent[expando]||(parent[expando]={});cache=outerCache[type]||[];nodeIndex=cache[0]===dirruns&&cache[1];diff=cache[0]===dirruns&&cache[2];node=nodeIndex&&parent.childNodes[nodeIndex];while(node=++nodeIndex&&node&&node[dir]||(diff=nodeIndex=0)||start.pop()){if(node.nodeType===1&&++diff&&node===elem){outerCache[type]=[dirruns,nodeIndex,diff];break;}}}else{if(useCache&&(cache=(elem[expando]||(elem[expando]={}))[type])&&cache[0]===dirruns){diff=cache[1];}else{while(node=++nodeIndex&&node&&node[dir]||(diff=nodeIndex=0)||start.pop()){if((ofType?node.nodeName.toLowerCase()===name:node.nodeType===1)&&++diff){if(useCache){(node[expando]||(node[expando]={}))[type]=[dirruns,diff];}
+if(node===elem){break;}}}}}
+diff-=last;return diff===first||diff%first===0&&diff / first>=0;}};},"PSEUDO":function(pseudo,argument){var args,fn=Expr.pseudos[pseudo]||Expr.setFilters[pseudo.toLowerCase()]||Sizzle.error("unsupported pseudo: "+pseudo);if(fn[expando]){return fn(argument);}
+if(fn.length>1){args=[pseudo,pseudo,"",argument];return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase())?markFunction(function(seed,matches){var idx,matched=fn(seed,argument),i=matched.length;while(i--){idx=indexOf.call(seed,matched[i]);seed[idx]=!(matches[idx]=matched[i]);}}):function(elem){return fn(elem,0,args);};}
+return fn;}},pseudos:{"not":markFunction(function(selector){var input=[],results=[],matcher=compile(selector.replace(rtrim,"$1"));return matcher[expando]?markFunction(function(seed,matches,context,xml){var elem,unmatched=matcher(seed,null,xml,[]),i=seed.length;while(i--){if(elem=unmatched[i]){seed[i]=!(matches[i]=elem);}}}):function(elem,context,xml){input[0]=elem;matcher(input,null,xml,results);return!results.pop();};}),"has":markFunction(function(selector){return function(elem){return Sizzle(selector,elem).length>0;};}),"contains":markFunction(function(text){return function(elem){return(elem.textContent||elem.innerText||getText(elem)).indexOf(text)>-1;};}),"lang":markFunction(function(lang){if(!ridentifier.test(lang||"")){Sizzle.error("unsupported lang: "+lang);}
+lang=lang.replace(runescape,funescape).toLowerCase();return function(elem){var elemLang;do{if(elemLang=documentIsHTML?elem.lang:elem.getAttribute("xml:lang")||elem.getAttribute("lang")){elemLang=elemLang.toLowerCase();return elemLang===lang||elemLang.indexOf(lang+"-")===0;}}while((elem=elem.parentNode)&&elem.nodeType===1);return false;};}),"target":function(elem){var hash=window.location&&window.location.hash;return hash&&hash.slice(1)===elem.id;},"root":function(elem){return elem===docElem;},"focus":function(elem){return elem===document.activeElement&&(!document.hasFocus||document.hasFocus())&&!!(elem.type||elem.href||~elem.tabIndex);},"enabled":function(elem){return elem.disabled===false;},"disabled":function(elem){return elem.disabled===true;},"checked":function(elem){var nodeName=elem.nodeName.toLowerCase();return nodeName==="input"&&!!elem.checked||nodeName==="option"&&!!elem.selected;},"selected":function(elem){if(elem.parentNode){elem.parentNode.selectedIndex;}
+return elem.selected===true;},"empty":function(elem){for(elem=elem.firstChild;elem;elem=elem.nextSibling){if(elem.nodeName>"@"||elem.nodeType===3||elem.nodeType===4){return false;}}
+return true;},"parent":function(elem){return!Expr.pseudos["empty"](elem);},"header":function(elem){return rheader.test(elem.nodeName);},"input":function(elem){return rinputs.test(elem.nodeName);},"button":function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type==="button"||name==="button";},"text":function(elem){var attr;return elem.nodeName.toLowerCase()==="input"&&elem.type==="text"&&((attr=elem.getAttribute("type"))==null||attr.toLowerCase()===elem.type);},"first":createPositionalPseudo(function(){return[0];}),"last":createPositionalPseudo(function(matchIndexes,length){return[length-1];}),"eq":createPositionalPseudo(function(matchIndexes,length,argument){return[argument<0?argument+length:argument];}),"even":createPositionalPseudo(function(matchIndexes,length){var i=0;for(;i<length;i+=2){matchIndexes.push(i);}
+return matchIndexes;}),"odd":createPositionalPseudo(function(matchIndexes,length){var i=1;for(;i<length;i+=2){matchIndexes.push(i);}
+return matchIndexes;}),"lt":createPositionalPseudo(function(matchIndexes,length,argument){var i=argument<0?argument+length:argument;for(;--i>=0;){matchIndexes.push(i);}
+return matchIndexes;}),"gt":createPositionalPseudo(function(matchIndexes,length,argument){var i=argument<0?argument+length:argument;for(;++i<length;){matchIndexes.push(i);}
+return matchIndexes;})}};for(i in{radio:true,checkbox:true,file:true,password:true,image:true}){Expr.pseudos[i]=createInputPseudo(i);}
+for(i in{submit:true,reset:true}){Expr.pseudos[i]=createButtonPseudo(i);}
+function tokenize(selector,parseOnly){var matched,match,tokens,type,soFar,groups,preFilters,cached=tokenCache[selector+" "];if(cached){return parseOnly?0:cached.slice(0);}
+soFar=selector;groups=[];preFilters=Expr.preFilter;while(soFar){if(!matched||(match=rcomma.exec(soFar))){if(match){soFar=soFar.slice(match[0].length)||soFar;}
+groups.push(tokens=[]);}
+matched=false;if(match=rcombinators.exec(soFar)){matched=match.shift();tokens.push({value:matched,type:match[0].replace(rtrim," ")});soFar=soFar.slice(matched.length);}
+for(type in Expr.filter){if((match=matchExpr[type].exec(soFar))&&(!preFilters[type]||(match=preFilters[type](match)))){matched=match.shift();tokens.push({value:matched,type:type,matches:match});soFar=soFar.slice(matched.length);}}
+if(!matched){break;}}
+return parseOnly?soFar.length:soFar?Sizzle.error(selector):tokenCache(selector,groups).slice(0);}
+function toSelector(tokens){var i=0,len=tokens.length,selector="";for(;i<len;i++){selector+=tokens[i].value;}
+return selector;}
+function addCombinator(matcher,combinator,base){var dir=combinator.dir,checkNonElements=base&&dir==="parentNode",doneName=done++;return combinator.first?function(elem,context,xml){while(elem=elem[dir]){if(elem.nodeType===1||checkNonElements){return matcher(elem,context,xml);}}}:function(elem,context,xml){var data,cache,outerCache,dirkey=dirruns+" "+doneName;if(xml){while(elem=elem[dir]){if(elem.nodeType===1||checkNonElements){if(matcher(elem,context,xml)){return true;}}}}else{while(elem=elem[dir]){if(elem.nodeType===1||checkNonElements){outerCache=elem[expando]||(elem[expando]={});if((cache=outerCache[dir])&&cache[0]===dirkey){if((data=cache[1])===true||data===cachedruns){return data===true;}}else{cache=outerCache[dir]=[dirkey];cache[1]=matcher(elem,context,xml)||cachedruns;if(cache[1]===true){return true;}}}}}};}
+function elementMatcher(matchers){return matchers.length>1?function(elem,context,xml){var i=matchers.length;while(i--){if(!matchers[i](elem,context,xml)){return false;}}
+return true;}:matchers[0];}
+function condense(unmatched,map,filter,context,xml){var elem,newUnmatched=[],i=0,len=unmatched.length,mapped=map!=null;for(;i<len;i++){if(elem=unmatched[i]){if(!filter||filter(elem,context,xml)){newUnmatched.push(elem);if(mapped){map.push(i);}}}}
+return newUnmatched;}
+function setMatcher(preFilter,selector,matcher,postFilter,postFinder,postSelector){if(postFilter&&!postFilter[expando]){postFilter=setMatcher(postFilter);}
+if(postFinder&&!postFinder[expando]){postFinder=setMatcher(postFinder,postSelector);}
+return markFunction(function(seed,results,context,xml){var temp,i,elem,preMap=[],postMap=[],preexisting=results.length,elems=seed||multipleContexts(selector||"*",context.nodeType?[context]:context,[]),matcherIn=preFilter&&(seed||!selector)?condense(elems,preMap,preFilter,context,xml):elems,matcherOut=matcher?postFinder||(seed?preFilter:preexisting||postFilter)?[]:results:matcherIn;if(matcher){matcher(matcherIn,matcherOut,context,xml);}
+if(postFilter){temp=condense(matcherOut,postMap);postFilter(temp,[],context,xml);i=temp.length;while(i--){if(elem=temp[i]){matcherOut[postMap[i]]=!(matcherIn[postMap[i]]=elem);}}}
+if(seed){if(postFinder||preFilter){if(postFinder){temp=[];i=matcherOut.length;while(i--){if(elem=matcherOut[i]){temp.push(matcherIn[i]=elem);}}
+postFinder(null,matcherOut=[],temp,xml);}
+i=matcherOut.length;while(i--){if((elem=matcherOut[i])&&(temp=postFinder?indexOf.call(seed,elem):preMap[i])>-1){seed[temp]=!(results[temp]=elem);}}}}else{matcherOut=condense(matcherOut===results?matcherOut.splice(preexisting,matcherOut.length):matcherOut);if(postFinder){postFinder(null,results,matcherOut,xml);}else{push.apply(results,matcherOut);}}});}
+function matcherFromTokens(tokens){var checkContext,matcher,j,len=tokens.length,leadingRelative=Expr.relative[tokens[0].type],implicitRelative=leadingRelative||Expr.relative[" "],i=leadingRelative?1:0,matchContext=addCombinator(function(elem){return elem===checkContext;},implicitRelative,true),matchAnyContext=addCombinator(function(elem){return indexOf.call(checkContext,elem)>-1;},implicitRelative,true),matchers=[function(elem,context,xml){return!leadingRelative&&(xml||context!==outermostContext)||((checkContext=context).nodeType?matchContext(elem,context,xml):matchAnyContext(elem,context,xml));}];for(;i<len;i++){if(matcher=Expr.relative[tokens[i].type]){matchers=[addCombinator(elementMatcher(matchers),matcher)];}else{matcher=Expr.filter[tokens[i].type].apply(null,tokens[i].matches);if(matcher[expando]){j=++i;for(;j<len;j++){if(Expr.relative[tokens[j].type]){break;}}
+return setMatcher(i>1&&elementMatcher(matchers),i>1&&toSelector(tokens.slice(0,i-1).concat({value:tokens[i-2].type===" "?"*":""})).replace(rtrim,"$1"),matcher,i<j&&matcherFromTokens(tokens.slice(i,j)),j<len&&matcherFromTokens(tokens=tokens.slice(j)),j<len&&toSelector(tokens));}
+matchers.push(matcher);}}
+return elementMatcher(matchers);}
+function matcherFromGroupMatchers(elementMatchers,setMatchers){var matcherCachedRuns=0,bySet=setMatchers.length>0,byElement=elementMatchers.length>0,superMatcher=function(seed,context,xml,results,expandContext){var elem,j,matcher,setMatched=[],matchedCount=0,i="0",unmatched=seed&&[],outermost=expandContext!=null,contextBackup=outermostContext,elems=seed||byElement&&Expr.find["TAG"]("*",expandContext&&context.parentNode||context),dirrunsUnique=dirruns+=contextBackup==null?1:Math.random()||.1;if(outermost){outermostContext=context!==document&&context;cachedruns=matcherCachedRuns;}
+for(;(elem=elems[i])!=null;i++){if(byElement&&elem){j=0;while(matcher=elementMatchers[j++]){if(matcher(elem,context,xml)){results.push(elem);break;}}
+if(outermost){dirruns=dirrunsUnique;cachedruns=++matcherCachedRuns;}}
+if(bySet){if(elem=!matcher&&elem){matchedCount--;}
+if(seed){unmatched.push(elem);}}}
+matchedCount+=i;if(bySet&&i!==matchedCount){j=0;while(matcher=setMatchers[j++]){matcher(unmatched,setMatched,context,xml);}
+if(seed){if(matchedCount>0){while(i--){if(!(unmatched[i]||setMatched[i])){setMatched[i]=pop.call(results);}}}
+setMatched=condense(setMatched);}
+push.apply(results,setMatched);if(outermost&&!seed&&setMatched.length>0&&matchedCount+setMatchers.length>1){Sizzle.uniqueSort(results);}}
+if(outermost){dirruns=dirrunsUnique;outermostContext=contextBackup;}
+return unmatched;};return bySet?markFunction(superMatcher):superMatcher;}
+compile=Sizzle.compile=function(selector,group){var i,setMatchers=[],elementMatchers=[],cached=compilerCache[selector+" "];if(!cached){if(!group){group=tokenize(selector);}
+i=group.length;while(i--){cached=matcherFromTokens(group[i]);if(cached[expando]){setMatchers.push(cached);}else{elementMatchers.push(cached);}}
+cached=compilerCache(selector,matcherFromGroupMatchers(elementMatchers,setMatchers));}
+return cached;};function multipleContexts(selector,contexts,results){var i=0,len=contexts.length;for(;i<len;i++){Sizzle(selector,contexts[i],results);}
+return results;}
+function select(selector,context,results,seed){var i,tokens,token,type,find,match=tokenize(selector);if(!seed){if(match.length===1){tokens=match[0]=match[0].slice(0);if(tokens.length>2&&(token=tokens[0]).type==="ID"&&support.getById&&context.nodeType===9&&documentIsHTML&&Expr.relative[tokens[1].type]){context=(Expr.find["ID"](token.matches[0].replace(runescape,funescape),context)||[])[0];if(!context){return results;}
+selector=selector.slice(tokens.shift().value.length);}
+i=matchExpr["needsContext"].test(selector)?0:tokens.length;while(i--){token=tokens[i];if(Expr.relative[type=token.type]){break;}
+if(find=Expr.find[type]){if(seed=find(token.matches[0].replace(runescape,funescape),rsibling.test(tokens[0].type)&&context.parentNode||context)){tokens.splice(i,1);selector=seed.length&&toSelector(tokens);if(!selector){push.apply(results,seed);return results;}
+break;}}}}}
+compile(selector,match)(seed,context,!documentIsHTML,results,rsibling.test(selector));return results;}
+Expr.pseudos["nth"]=Expr.pseudos["eq"];function setFilters(){}
+setFilters.prototype=Expr.filters=Expr.pseudos;Expr.setFilters=new setFilters;support.sortStable=expando.split("").sort(sortOrder).join("")===expando;setDocument();[0,0].sort(sortOrder);support.detectDuplicates=hasDuplicate;jQuery.find=Sizzle;jQuery.expr=Sizzle.selectors;jQuery.expr[":"]=jQuery.expr.pseudos;jQuery.unique=Sizzle.uniqueSort;jQuery.text=Sizzle.getText;jQuery.isXMLDoc=Sizzle.isXML;jQuery.contains=Sizzle.contains;})(window);var optionsCache={};function createOptions(options){var object=optionsCache[options]={};jQuery.each(options.match(core_rnotwhite)||[],function(_,flag){object[flag]=true;});return object;}
+jQuery.Callbacks=function(options){options=typeof options==="string"?optionsCache[options]||createOptions(options):jQuery.extend({},options);var memory,fired,firing,firingStart,firingLength,firingIndex,list=[],stack=!options.once&&[],fire=function(data){memory=options.memory&&data;fired=true;firingIndex=firingStart||0;firingStart=0;firingLength=list.length;firing=true;for(;list&&firingIndex<firingLength;firingIndex++){if(list[firingIndex].apply(data[0],data[1])===false&&options.stopOnFalse){memory=false;break;}}
+firing=false;if(list){if(stack){if(stack.length){fire(stack.shift());}}else{if(memory){list=[];}else{self.disable();}}}},self={add:function(){if(list){var start=list.length;(function add(args){jQuery.each(args,function(_,arg){var type=jQuery.type(arg);if(type==="function"){if(!options.unique||!self.has(arg)){list.push(arg);}}else{if(arg&&arg.length&&type!=="string"){add(arg);}}});})(arguments);if(firing){firingLength=list.length;}else{if(memory){firingStart=start;fire(memory);}}}
+return this;},remove:function(){if(list){jQuery.each(arguments,function(_,arg){var index;while((index=jQuery.inArray(arg,list,index))>-1){list.splice(index,1);if(firing){if(index<=firingLength){firingLength--;}
+if(index<=firingIndex){firingIndex--;}}}});}
+return this;},has:function(fn){return fn?jQuery.inArray(fn,list)>-1:!!(list&&list.length);},empty:function(){list=[];firingLength=0;return this;},disable:function(){list=stack=memory=undefined;return this;},disabled:function(){return!list;},lock:function(){stack=undefined;if(!memory){self.disable();}
+return this;},locked:function(){return!stack;},fireWith:function(context,args){args=args||[];args=[context,args.slice?args.slice():args];if(list&&(!fired||stack)){if(firing){stack.push(args);}else{fire(args);}}
+return this;},fire:function(){self.fireWith(this,arguments);return this;},fired:function(){return!!fired;}};return self;};jQuery.extend({Deferred:function(func){var tuples=[["resolve","done",jQuery.Callbacks("once memory"),"resolved"],["reject","fail",jQuery.Callbacks("once memory"),"rejected"],["notify","progress",jQuery.Callbacks("memory")]],state="pending",promise={state:function(){return state;},always:function(){deferred.done(arguments).fail(arguments);return this;},then:function(){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var action=tuple[0],fn=jQuery.isFunction(fns[i])&&fns[i];deferred[tuple[1]](function(){var returned=fn&&fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify);}else{newDefer[action+"With"](this===promise?newDefer.promise():this,fn?[returned]:arguments);}});});fns=null;}).promise();},promise:function(obj){return obj!=null?jQuery.extend(obj,promise):promise;}},deferred={};promise.pipe=promise.then;jQuery.each(tuples,function(i,tuple){var list=tuple[2],stateString=tuple[3];promise[tuple[1]]=list.add;if(stateString){list.add(function(){state=stateString;},tuples[i^1][2].disable,tuples[2][2].lock);}
+deferred[tuple[0]]=function(){deferred[tuple[0]+"With"](this===deferred?promise:this,arguments);return this;};deferred[tuple[0]+"With"]=list.fireWith;});promise.promise(deferred);if(func){func.call(deferred,deferred);}
+return deferred;},when:function(subordinate){var i=0,resolveValues=core_slice.call(arguments),length=resolveValues.length,remaining=length!==1||subordinate&&jQuery.isFunction(subordinate.promise)?length:0,deferred=remaining===1?subordinate:jQuery.Deferred(),updateFunc=function(i,contexts,values){return function(value){contexts[i]=this;values[i]=arguments.length>1?core_slice.call(arguments):value;if(values===progressValues){deferred.notifyWith(contexts,values);}else{if(!--remaining){deferred.resolveWith(contexts,values);}}};},progressValues,progressContexts,resolveContexts;if(length>1){progressValues=new Array(length);progressContexts=new Array(length);resolveContexts=new Array(length);for(;i<length;i++){if(resolveValues[i]&&jQuery.isFunction(resolveValues[i].promise)){resolveValues[i].promise().done(updateFunc(i,resolveContexts,resolveValues)).fail(deferred.reject).progress(updateFunc(i,progressContexts,progressValues));}else{--remaining;}}}
+if(!remaining){deferred.resolveWith(resolveContexts,resolveValues);}
+return deferred.promise();}});jQuery.support=function(support){var input=document.createElement("input"),fragment=document.createDocumentFragment(),div=document.createElement("div"),select=document.createElement("select"),opt=select.appendChild(document.createElement("option"));if(!input.type){return support;}
+input.type="checkbox";support.checkOn=input.value!=="";support.optSelected=opt.selected;support.reliableMarginRight=true;support.boxSizingReliable=true;support.pixelPosition=false;input.checked=true;support.noCloneChecked=input.cloneNode(true).checked;select.disabled=true;support.optDisabled=!opt.disabled;input=document.createElement("input");input.value="t";input.type="radio";support.radioValue=input.value==="t";input.setAttribute("checked","t");input.setAttribute("name","t");fragment.appendChild(input);support.checkClone=fragment.cloneNode(true).cloneNode(true).lastChild.checked;support.focusinBubbles="onfocusin"in window;div.style.backgroundClip="content-box";div.cloneNode(true).style.backgroundClip="";support.clearCloneStyle=div.style.backgroundClip==="content-box";jQuery(function(){var container,marginDiv,divReset="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",body=document.getElementsByTagName("body")[0];if(!body){return;}
+container=document.createElement("div");container.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";body.appendChild(container).appendChild(div);div.innerHTML="";div.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%";jQuery.swap(body,body.style.zoom!=null?{zoom:1}:{},function(){support.boxSizing=div.offsetWidth===4;});if(window.getComputedStyle){support.pixelPosition=(window.getComputedStyle(div,null)||{}).top!=="1%";support.boxSizingReliable=(window.getComputedStyle(div,null)||{width:"4px"}).width==="4px";marginDiv=div.appendChild(document.createElement("div"));marginDiv.style.cssText=div.style.cssText=divReset;marginDiv.style.marginRight=marginDiv.style.width="0";div.style.width="1px";support.reliableMarginRight=!parseFloat((window.getComputedStyle(marginDiv,null)||{}).marginRight);}
+body.removeChild(container);});return support;}({});var data_user,data_priv,rbrace=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,rmultiDash=/([A-Z])/g;function Data(){Object.defineProperty(this.cache={},0,{get:function(){return{};}});this.expando=jQuery.expando+Math.random();}
+Data.uid=1;Data.accepts=function(owner){return owner.nodeType?owner.nodeType===1||owner.nodeType===9:true;};Data.prototype={key:function(owner){if(!Data.accepts(owner)){return 0;}
+var descriptor={},unlock=owner[this.expando];if(!unlock){unlock=Data.uid++;try{descriptor[this.expando]={value:unlock};Object.defineProperties(owner,descriptor);}catch(e){descriptor[this.expando]=unlock;jQuery.extend(owner,descriptor);}}
+if(!this.cache[unlock]){this.cache[unlock]={};}
+return unlock;},set:function(owner,data,value){var prop,unlock=this.key(owner),cache=this.cache[unlock];if(typeof data==="string"){cache[data]=value;}else{if(jQuery.isEmptyObject(cache)){jQuery.extend(this.cache[unlock],data);}else{for(prop in data){cache[prop]=data[prop];}}}
+return cache;},get:function(owner,key){var cache=this.cache[this.key(owner)];return key===undefined?cache:cache[key];},access:function(owner,key,value){if(key===undefined||key&&typeof key==="string"&&value===undefined){return this.get(owner,key);}
+this.set(owner,key,value);return value!==undefined?value:key;},remove:function(owner,key){var i,name,camel,unlock=this.key(owner),cache=this.cache[unlock];if(key===undefined){this.cache[unlock]={};}else{if(jQuery.isArray(key)){name=key.concat(key.map(jQuery.camelCase));}else{camel=jQuery.camelCase(key);if(key in cache){name=[key,camel];}else{name=camel;name=name in cache?[name]:name.match(core_rnotwhite)||[];}}
+i=name.length;while(i--){delete cache[name[i]];}}},hasData:function(owner){return!jQuery.isEmptyObject(this.cache[owner[this.expando]]||{});},discard:function(owner){if(owner[this.expando]){delete this.cache[owner[this.expando]];}}};data_user=new Data;data_priv=new Data;jQuery.extend({acceptData:Data.accepts,hasData:function(elem){return data_user.hasData(elem)||data_priv.hasData(elem);},data:function(elem,name,data){return data_user.access(elem,name,data);},removeData:function(elem,name){data_user.remove(elem,name);},_data:function(elem,name,data){return data_priv.access(elem,name,data);},_removeData:function(elem,name){data_priv.remove(elem,name);}});jQuery.fn.extend({data:function(key,value){var attrs,name,elem=this[0],i=0,data=null;if(key===undefined){if(this.length){data=data_user.get(elem);if(elem.nodeType===1&&!data_priv.get(elem,"hasDataAttrs")){attrs=elem.attributes;for(;i<attrs.length;i++){name=attrs[i].name;if(name.indexOf("data-")===0){name=jQuery.camelCase(name.slice(5));dataAttr(elem,name,data[name]);}}
+data_priv.set(elem,"hasDataAttrs",true);}}
+return data;}
+if(typeof key==="object"){return this.each(function(){data_user.set(this,key);});}
+return jQuery.access(this,function(value){var data,camelKey=jQuery.camelCase(key);if(elem&&value===undefined){data=data_user.get(elem,key);if(data!==undefined){return data;}
+data=data_user.get(elem,camelKey);if(data!==undefined){return data;}
+data=dataAttr(elem,camelKey,undefined);if(data!==undefined){return data;}
+return;}
+this.each(function(){var data=data_user.get(this,camelKey);data_user.set(this,camelKey,value);if(key.indexOf("-")!==-1&&data!==undefined){data_user.set(this,key,value);}});},null,value,arguments.length>1,null,true);},removeData:function(key){return this.each(function(){data_user.remove(this,key);});}});function dataAttr(elem,key,data){var name;if(data===undefined&&elem.nodeType===1){name="data-"+key.replace(rmultiDash,"-$1").toLowerCase();data=elem.getAttribute(name);if(typeof data==="string"){try{data=data==="true"?true:data==="false"?false:data==="null"?null:+data+""===data?+data:rbrace.test(data)?JSON.parse(data):data;}catch(e){}
+data_user.set(elem,key,data);}else{data=undefined;}}
+return data;}
+jQuery.extend({queue:function(elem,type,data){var queue;if(elem){type=(type||"fx")+"queue";queue=data_priv.get(elem,type);if(data){if(!queue||jQuery.isArray(data)){queue=data_priv.access(elem,type,jQuery.makeArray(data));}else{queue.push(data);}}
+return queue||[];}},dequeue:function(elem,type){type=type||"fx";var queue=jQuery.queue(elem,type),startLength=queue.length,fn=queue.shift(),hooks=jQuery._queueHooks(elem,type),next=function(){jQuery.dequeue(elem,type);};if(fn==="inprogress"){fn=queue.shift();startLength--;}
+if(fn){if(type==="fx"){queue.unshift("inprogress");}
+delete hooks.stop;fn.call(elem,next,hooks);}
+if(!startLength&&hooks){hooks.empty.fire();}},_queueHooks:function(elem,type){var key=type+"queueHooks";return data_priv.get(elem,key)||data_priv.access(elem,key,{empty:jQuery.Callbacks("once memory").add(function(){data_priv.remove(elem,[type+"queue",key]);})});}});jQuery.fn.extend({queue:function(type,data){var setter=2;if(typeof type!=="string"){data=type;type="fx";setter--;}
+if(arguments.length<setter){return jQuery.queue(this[0],type);}
+return data===undefined?this:this.each(function(){var queue=jQuery.queue(this,type,data);jQuery._queueHooks(this,type);if(type==="fx"&&queue[0]!=="inprogress"){jQuery.dequeue(this,type);}});},dequeue:function(type){return this.each(function(){jQuery.dequeue(this,type);});},delay:function(time,type){time=jQuery.fx?jQuery.fx.speeds[time]||time:time;type=type||"fx";return this.queue(type,function(next,hooks){var timeout=setTimeout(next,time);hooks.stop=function(){clearTimeout(timeout);};});},clearQueue:function(type){return this.queue(type||"fx",[]);},promise:function(type,obj){var tmp,count=1,defer=jQuery.Deferred(),elements=this,i=this.length,resolve=function(){if(!--count){defer.resolveWith(elements,[elements]);}};if(typeof type!=="string"){obj=type;type=undefined;}
+type=type||"fx";while(i--){tmp=data_priv.get(elements[i],type+"queueHooks");if(tmp&&tmp.empty){count++;tmp.empty.add(resolve);}}
+resolve();return defer.promise(obj);}});var nodeHook,boolHook,rclass=/[\t\r\n\f]/g,rreturn=/\r/g,rfocusable=/^(?:input|select|textarea|button)$/i;jQuery.fn.extend({attr:function(name,value){return jQuery.access(this,jQuery.attr,name,value,arguments.length>1);},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name);});},prop:function(name,value){return jQuery.access(this,jQuery.prop,name,value,arguments.length>1);},removeProp:function(name){return this.each(function(){delete this[jQuery.propFix[name]||name];});},addClass:function(value){var classes,elem,cur,clazz,j,i=0,len=this.length,proceed=typeof value==="string"&&value;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,this.className));});}
+if(proceed){classes=(value||"").match(core_rnotwhite)||[];for(;i<len;i++){elem=this[i];cur=elem.nodeType===1&&(elem.className?(" "+elem.className+" ").replace(rclass," "):" ");if(cur){j=0;while(clazz=classes[j++]){if(cur.indexOf(" "+clazz+" ")<0){cur+=clazz+" ";}}
+elem.className=jQuery.trim(cur);}}}
+return this;},removeClass:function(value){var classes,elem,cur,clazz,j,i=0,len=this.length,proceed=arguments.length===0||typeof value==="string"&&value;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).removeClass(value.call(this,j,this.className));});}
+if(proceed){classes=(value||"").match(core_rnotwhite)||[];for(;i<len;i++){elem=this[i];cur=elem.nodeType===1&&(elem.className?(" "+elem.className+" ").replace(rclass," "):"");if(cur){j=0;while(clazz=classes[j++]){while(cur.indexOf(" "+clazz+" ")>=0){cur=cur.replace(" "+clazz+" "," ");}}
+elem.className=value?jQuery.trim(cur):"";}}}
+return this;},toggleClass:function(value,stateVal){var type=typeof value,isBool=typeof stateVal==="boolean";if(jQuery.isFunction(value)){return this.each(function(i){jQuery(this).toggleClass(value.call(this,i,this.className,stateVal),stateVal);});}
+return this.each(function(){if(type==="string"){var className,i=0,self=jQuery(this),state=stateVal,classNames=value.match(core_rnotwhite)||[];while(className=classNames[i++]){state=isBool?state:!self.hasClass(className);self[state?"addClass":"removeClass"](className);}}else{if(type===core_strundefined||type==="boolean"){if(this.className){data_priv.set(this,"__className__",this.className);}
+this.className=this.className||value===false?"":data_priv.get(this,"__className__")||"";}}});},hasClass:function(selector){var className=" "+selector+" ",i=0,l=this.length;for(;i<l;i++){if(this[i].nodeType===1&&(" "+this[i].className+" ").replace(rclass," ").indexOf(className)>=0){return true;}}
+return false;},val:function(value){var hooks,ret,isFunction,elem=this[0];if(!arguments.length){if(elem){hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()];if(hooks&&"get"in hooks&&(ret=hooks.get(elem,"value"))!==undefined){return ret;}
+ret=elem.value;return typeof ret==="string"?ret.replace(rreturn,""):ret==null?"":ret;}
+return;}
+isFunction=jQuery.isFunction(value);return this.each(function(i){var val;if(this.nodeType!==1){return;}
+if(isFunction){val=value.call(this,i,jQuery(this).val());}else{val=value;}
+if(val==null){val="";}else{if(typeof val==="number"){val+="";}else{if(jQuery.isArray(val)){val=jQuery.map(val,function(value){return value==null?"":value+"";});}}}
+hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()];if(!hooks||!("set"in hooks)||hooks.set(this,val,"value")===undefined){this.value=val;}});}});jQuery.extend({valHooks:{option:{get:function(elem){var val=elem.attributes.value;return!val||val.specified?elem.value:elem.text;}},select:{get:function(elem){var value,option,options=elem.options,index=elem.selectedIndex,one=elem.type==="select-one"||index<0,values=one?null:[],max=one?index+1:options.length,i=index<0?max:one?index:0;for(;i<max;i++){option=options[i];if((option.selected||i===index)&&(jQuery.support.optDisabled?!option.disabled:option.getAttribute("disabled")===null)&&(!option.parentNode.disabled||!jQuery.nodeName(option.parentNode,"optgroup"))){value=jQuery(option).val();if(one){return value;}
+values.push(value);}}
+return values;},set:function(elem,value){var optionSet,option,options=elem.options,values=jQuery.makeArray(value),i=options.length;while(i--){option=options[i];if(option.selected=jQuery.inArray(jQuery(option).val(),values)>=0){optionSet=true;}}
+if(!optionSet){elem.selectedIndex=-1;}
+return values;}}},attr:function(elem,name,value){var hooks,ret,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return;}
+if(typeof elem.getAttribute===core_strundefined){return jQuery.prop(elem,name,value);}
+if(nType!==1||!jQuery.isXMLDoc(elem)){name=name.toLowerCase();hooks=jQuery.attrHooks[name]||(jQuery.expr.match.bool.test(name)?boolHook:nodeHook);}
+if(value!==undefined){if(value===null){jQuery.removeAttr(elem,name);}else{if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret;}else{elem.setAttribute(name,value+"");return value;}}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret;}else{ret=jQuery.find.attr(elem,name);return ret==null?undefined:ret;}}},removeAttr:function(elem,value){var name,propName,i=0,attrNames=value&&value.match(core_rnotwhite);if(attrNames&&elem.nodeType===1){while(name=attrNames[i++]){propName=jQuery.propFix[name]||name;if(jQuery.expr.match.bool.test(name)){elem[propName]=false;}
+elem.removeAttribute(name);}}},attrHooks:{type:{set:function(elem,value){if(!jQuery.support.radioValue&&value==="radio"&&jQuery.nodeName(elem,"input")){var val=elem.value;elem.setAttribute("type",value);if(val){elem.value=val;}
+return value;}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(elem,name,value){var ret,hooks,notxml,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return;}
+notxml=nType!==1||!jQuery.isXMLDoc(elem);if(notxml){name=jQuery.propFix[name]||name;hooks=jQuery.propHooks[name];}
+if(value!==undefined){return hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined?ret:elem[name]=value;}else{return hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null?ret:elem[name];}},propHooks:{tabIndex:{get:function(elem){return elem.hasAttribute("tabindex")||rfocusable.test(elem.nodeName)||elem.href?elem.tabIndex:-1;}}}});boolHook={set:function(elem,value,name){if(value===false){jQuery.removeAttr(elem,name);}else{elem.setAttribute(name,name);}
+return name;}};jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g),function(i,name){var getter=jQuery.expr.attrHandle[name]||jQuery.find.attr;jQuery.expr.attrHandle[name]=function(elem,name,isXML){var fn=jQuery.expr.attrHandle[name],ret=isXML?undefined:(jQuery.expr.attrHandle[name]=undefined)!=getter(elem,name,isXML)?name.toLowerCase():null;jQuery.expr.attrHandle[name]=fn;return ret;};});if(!jQuery.support.optSelected){jQuery.propHooks.selected={get:function(elem){var parent=elem.parentNode;if(parent&&parent.parentNode){parent.parentNode.selectedIndex;}
+return null;}};}
+jQuery.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){jQuery.propFix[this.toLowerCase()]=this;});jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={set:function(elem,value){if(jQuery.isArray(value)){return elem.checked=jQuery.inArray(jQuery(elem).val(),value)>=0;}}};if(!jQuery.support.checkOn){jQuery.valHooks[this].get=function(elem){return elem.getAttribute("value")===null?"on":elem.value;};}});var rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|contextmenu)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,rtypenamespace=/^([^.]*)(?:\.(.+)|)$/;function returnTrue(){return true;}
+function returnFalse(){return false;}
+function safeActiveElement(){try{return document.activeElement;}catch(err){}}
+jQuery.event={global:{},add:function(elem,types,handler,data,selector){var handleObjIn,eventHandle,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=data_priv.get(elem);if(!elemData){return;}
+if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector;}
+if(!handler.guid){handler.guid=jQuery.guid++;}
+if(!(events=elemData.events)){events=elemData.events={};}
+if(!(eventHandle=elemData.handle)){eventHandle=elemData.handle=function(e){return typeof jQuery!==core_strundefined&&(!e||jQuery.event.triggered!==e.type)?jQuery.event.dispatch.apply(eventHandle.elem,arguments):undefined;};eventHandle.elem=elem;}
+types=(types||"").match(core_rnotwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){continue;}
+special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;special=jQuery.event.special[type]||{};handleObj=jQuery.extend({type:type,origType:origType,data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn);if(!(handlers=events[type])){handlers=events[type]=[];handlers.delegateCount=0;if(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){if(elem.addEventListener){elem.addEventListener(type,eventHandle,false);}}}
+if(special.add){special.add.call(elem,handleObj);if(!handleObj.handler.guid){handleObj.handler.guid=handler.guid;}}
+if(selector){handlers.splice(handlers.delegateCount++,0,handleObj);}else{handlers.push(handleObj);}
+jQuery.event.global[type]=true;}
+elem=null;},remove:function(elem,types,handler,selector,mappedTypes){var j,origCount,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=data_priv.hasData(elem)&&data_priv.get(elem);if(!elemData||!(events=elemData.events)){return;}
+types=(types||"").match(core_rnotwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){for(type in events){jQuery.event.remove(elem,type+types[t],handler,selector,true);}
+continue;}
+special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;handlers=events[type]||[];tmp=tmp[2]&&new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)");origCount=j=handlers.length;while(j--){handleObj=handlers[j];if((mappedTypes||origType===handleObj.origType)&&(!handler||handler.guid===handleObj.guid)&&(!tmp||tmp.test(handleObj.namespace))&&(!selector||selector===handleObj.selector||selector==="**"&&handleObj.selector)){handlers.splice(j,1);if(handleObj.selector){handlers.delegateCount--;}
+if(special.remove){special.remove.call(elem,handleObj);}}}
+if(origCount&&!handlers.length){if(!special.teardown||special.teardown.call(elem,namespaces,elemData.handle)===false){jQuery.removeEvent(elem,type,elemData.handle);}
+delete events[type];}}
+if(jQuery.isEmptyObject(events)){delete elemData.handle;data_priv.remove(elem,"events");}},trigger:function(event,data,elem,onlyHandlers){var i,cur,tmp,bubbleType,ontype,handle,special,eventPath=[elem||document],type=core_hasOwn.call(event,"type")?event.type:event,namespaces=core_hasOwn.call(event,"namespace")?event.namespace.split("."):[];cur=tmp=elem=elem||document;if(elem.nodeType===3||elem.nodeType===8){return;}
+if(rfocusMorph.test(type+jQuery.event.triggered)){return;}
+if(type.indexOf(".")>=0){namespaces=type.split(".");type=namespaces.shift();namespaces.sort();}
+ontype=type.indexOf(":")<0&&"on"+type;event=event[jQuery.expando]?event:new jQuery.Event(type,typeof event==="object"&&event);event.isTrigger=onlyHandlers?2:3;event.namespace=namespaces.join(".");event.namespace_re=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;event.result=undefined;if(!event.target){event.target=elem;}
+data=data==null?[event]:jQuery.makeArray(data,[event]);special=jQuery.event.special[type]||{};if(!onlyHandlers&&special.trigger&&special.trigger.apply(elem,data)===false){return;}
+if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){bubbleType=special.delegateType||type;if(!rfocusMorph.test(bubbleType+type)){cur=cur.parentNode;}
+for(;cur;cur=cur.parentNode){eventPath.push(cur);tmp=cur;}
+if(tmp===(elem.ownerDocument||document)){eventPath.push(tmp.defaultView||tmp.parentWindow||window);}}
+i=0;while((cur=eventPath[i++])&&!event.isPropagationStopped()){event.type=i>1?bubbleType:special.bindType||type;handle=(data_priv.get(cur,"events")||{})[event.type]&&data_priv.get(cur,"handle");if(handle){handle.apply(cur,data);}
+handle=ontype&&cur[ontype];if(handle&&jQuery.acceptData(cur)&&handle.apply&&handle.apply(cur,data)===false){event.preventDefault();}}
+event.type=type;if(!onlyHandlers&&!event.isDefaultPrevented()){if((!special._default||special._default.apply(eventPath.pop(),data)===false)&&jQuery.acceptData(elem)){if(ontype&&jQuery.isFunction(elem[type])&&!jQuery.isWindow(elem)){tmp=elem[ontype];if(tmp){elem[ontype]=null;}
+jQuery.event.triggered=type;elem[type]();jQuery.event.triggered=undefined;if(tmp){elem[ontype]=tmp;}}}}
+return event.result;},dispatch:function(event){event=jQuery.event.fix(event);var i,j,ret,matched,handleObj,handlerQueue=[],args=core_slice.call(arguments),handlers=(data_priv.get(this,"events")||{})[event.type]||[],special=jQuery.event.special[event.type]||{};args[0]=event;event.delegateTarget=this;if(special.preDispatch&&special.preDispatch.call(this,event)===false){return;}
+handlerQueue=jQuery.event.handlers.call(this,event,handlers);i=0;while((matched=handlerQueue[i++])&&!event.isPropagationStopped()){event.currentTarget=matched.elem;j=0;while((handleObj=matched.handlers[j++])&&!event.isImmediatePropagationStopped()){if(!event.namespace_re||event.namespace_re.test(handleObj.namespace)){event.handleObj=handleObj;event.data=handleObj.data;ret=((jQuery.event.special[handleObj.origType]||{}).handle||handleObj.handler).apply(matched.elem,args);if(ret!==undefined){if((event.result=ret)===false){event.preventDefault();event.stopPropagation();}}}}}
+if(special.postDispatch){special.postDispatch.call(this,event);}
+return event.result;},handlers:function(event,handlers){var i,matches,sel,handleObj,handlerQueue=[],delegateCount=handlers.delegateCount,cur=event.target;if(delegateCount&&cur.nodeType&&(!event.button||event.type!=="click")){for(;cur!==this;cur=cur.parentNode||this){if(cur.disabled!==true||event.type!=="click"){matches=[];for(i=0;i<delegateCount;i++){handleObj=handlers[i];sel=handleObj.selector+" ";if(matches[sel]===undefined){matches[sel]=handleObj.needsContext?jQuery(sel,this).index(cur)>=0:jQuery.find(sel,this,null,[cur]).length;}
+if(matches[sel]){matches.push(handleObj);}}
+if(matches.length){handlerQueue.push({elem:cur,handlers:matches});}}}}
+if(delegateCount<handlers.length){handlerQueue.push({elem:this,handlers:handlers.slice(delegateCount)});}
+return handlerQueue;},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(event,original){if(event.which==null){event.which=original.charCode!=null?original.charCode:original.keyCode;}
+return event;}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(event,original){var eventDoc,doc,body,button=original.button;if(event.pageX==null&&original.clientX!=null){eventDoc=event.target.ownerDocument||document;doc=eventDoc.documentElement;body=eventDoc.body;event.pageX=original.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc&&doc.clientLeft||body&&body.clientLeft||0);event.pageY=original.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc&&doc.clientTop||body&&body.clientTop||0);}
+if(!event.which&&button!==undefined){event.which=button&1?1:button&2?3:button&4?2:0;}
+return event;}},fix:function(event){if(event[jQuery.expando]){return event;}
+var i,prop,copy,type=event.type,originalEvent=event,fixHook=this.fixHooks[type];if(!fixHook){this.fixHooks[type]=fixHook=rmouseEvent.test(type)?this.mouseHooks:rkeyEvent.test(type)?this.keyHooks:{};}
+copy=fixHook.props?this.props.concat(fixHook.props):this.props;event=new jQuery.Event(originalEvent);i=copy.length;while(i--){prop=copy[i];event[prop]=originalEvent[prop];}
+if(!event.target){event.target=document;}
+if(event.target.nodeType===3){event.target=event.target.parentNode;}
+return fixHook.filter?fixHook.filter(event,originalEvent):event;},special:{load:{noBubble:true},focus:{trigger:function(){if(this!==safeActiveElement()&&this.focus){this.focus();return false;}},delegateType:"focusin"},blur:{trigger:function(){if(this===safeActiveElement()&&this.blur){this.blur();return false;}},delegateType:"focusout"},click:{trigger:function(){if(this.type==="checkbox"&&this.click&&jQuery.nodeName(this,"input")){this.click();return false;}},_default:function(event){return jQuery.nodeName(event.target,"a");}},beforeunload:{postDispatch:function(event){if(event.result!==undefined){event.originalEvent.returnValue=event.result;}}}},simulate:function(type,elem,event,bubble){var e=jQuery.extend(new jQuery.Event,event,{type:type,isSimulated:true,originalEvent:{}});if(bubble){jQuery.event.trigger(e,null,elem);}else{jQuery.event.dispatch.call(elem,e);}
+if(e.isDefaultPrevented()){event.preventDefault();}}};jQuery.removeEvent=function(elem,type,handle){if(elem.removeEventListener){elem.removeEventListener(type,handle,false);}};jQuery.Event=function(src,props){if(!(this instanceof jQuery.Event)){return new jQuery.Event(src,props);}
+if(src&&src.type){this.originalEvent=src;this.type=src.type;this.isDefaultPrevented=src.defaultPrevented||src.getPreventDefault&&src.getPreventDefault()?returnTrue:returnFalse;}else{this.type=src;}
+if(props){jQuery.extend(this,props);}
+this.timeStamp=src&&src.timeStamp||jQuery.now();this[jQuery.expando]=true;};jQuery.Event.prototype={isDefaultPrevented:returnFalse,isPropagationStopped:returnFalse,isImmediatePropagationStopped:returnFalse,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=returnTrue;if(e&&e.preventDefault){e.preventDefault();}},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=returnTrue;if(e&&e.stopPropagation){e.stopPropagation();}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=returnTrue;this.stopPropagation();}};jQuery.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(orig,fix){jQuery.event.special[orig]={delegateType:fix,bindType:fix,handle:function(event){var ret,target=this,related=event.relatedTarget,handleObj=event.handleObj;if(!related||related!==target&&!jQuery.contains(target,related)){event.type=handleObj.origType;ret=handleObj.handler.apply(this,arguments);event.type=fix;}
+return ret;}};});if(!jQuery.support.focusinBubbles){jQuery.each({focus:"focusin",blur:"focusout"},function(orig,fix){var attaches=0,handler=function(event){jQuery.event.simulate(fix,event.target,jQuery.event.fix(event),true);};jQuery.event.special[fix]={setup:function(){if(attaches++===0){document.addEventListener(orig,handler,true);}},teardown:function(){if(--attaches===0){document.removeEventListener(orig,handler,true);}}};});}
+jQuery.fn.extend({on:function(types,selector,data,fn,one){var origFn,type;if(typeof types==="object"){if(typeof selector!=="string"){data=data||selector;selector=undefined;}
+for(type in types){this.on(type,selector,data,types[type],one);}
+return this;}
+if(data==null&&fn==null){fn=selector;data=selector=undefined;}else{if(fn==null){if(typeof selector==="string"){fn=data;data=undefined;}else{fn=data;data=selector;selector=undefined;}}}
+if(fn===false){fn=returnFalse;}else{if(!fn){return this;}}
+if(one===1){origFn=fn;fn=function(event){jQuery().off(event);return origFn.apply(this,arguments);};fn.guid=origFn.guid||(origFn.guid=jQuery.guid++);}
+return this.each(function(){jQuery.event.add(this,types,fn,data,selector);});},one:function(types,selector,data,fn){return this.on(types,selector,data,fn,1);},off:function(types,selector,fn){var handleObj,type;if(types&&types.preventDefault&&types.handleObj){handleObj=types.handleObj;jQuery(types.delegateTarget).off(handleObj.namespace?handleObj.origType+"."+handleObj.namespace:handleObj.origType,handleObj.selector,handleObj.handler);return this;}
+if(typeof types==="object"){for(type in types){this.off(type,selector,types[type]);}
+return this;}
+if(selector===false||typeof selector==="function"){fn=selector;selector=undefined;}
+if(fn===false){fn=returnFalse;}
+return this.each(function(){jQuery.event.remove(this,types,fn,selector);});},trigger:function(type,data){return this.each(function(){jQuery.event.trigger(type,data,this);});},triggerHandler:function(type,data){var elem=this[0];if(elem){return jQuery.event.trigger(type,data,elem,true);}}});var isSimple=/^.[^:#\[\.,]*$/,rparentsprev=/^(?:parents|prev(?:Until|All))/,rneedsContext=jQuery.expr.match.needsContext,guaranteedUnique={children:true,contents:true,next:true,prev:true};jQuery.fn.extend({find:function(selector){var i,ret=[],self=this,len=self.length;if(typeof selector!=="string"){return this.pushStack(jQuery(selector).filter(function(){for(i=0;i<len;i++){if(jQuery.contains(self[i],this)){return true;}}}));}
+for(i=0;i<len;i++){jQuery.find(selector,self[i],ret);}
+ret=this.pushStack(len>1?jQuery.unique(ret):ret);ret.selector=this.selector?this.selector+" "+selector:selector;return ret;},has:function(target){var targets=jQuery(target,this),l=targets.length;return this.filter(function(){var i=0;for(;i<l;i++){if(jQuery.contains(this,targets[i])){return true;}}});},not:function(selector){return this.pushStack(winnow(this,selector||[],true));},filter:function(selector){return this.pushStack(winnow(this,selector||[],false));},is:function(selector){return!!winnow(this,typeof selector==="string"&&rneedsContext.test(selector)?jQuery(selector):selector||[],false).length;},closest:function(selectors,context){var cur,i=0,l=this.length,matched=[],pos=rneedsContext.test(selectors)||typeof selectors!=="string"?jQuery(selectors,context||this.context):0;for(;i<l;i++){for(cur=this[i];cur&&cur!==context;cur=cur.parentNode){if(cur.nodeType<11&&(pos?pos.index(cur)>-1:cur.nodeType===1&&jQuery.find.matchesSelector(cur,selectors))){cur=matched.push(cur);break;}}}
+return this.pushStack(matched.length>1?jQuery.unique(matched):matched);},index:function(elem){if(!elem){return this[0]&&this[0].parentNode?this.first().prevAll().length:-1;}
+if(typeof elem==="string"){return core_indexOf.call(jQuery(elem),this[0]);}
+return core_indexOf.call(this,elem.jquery?elem[0]:elem);},add:function(selector,context){var set=typeof selector==="string"?jQuery(selector,context):jQuery.makeArray(selector&&selector.nodeType?[selector]:selector),all=jQuery.merge(this.get(),set);return this.pushStack(jQuery.unique(all));},addBack:function(selector){return this.add(selector==null?this.prevObject:this.prevObject.filter(selector));}});function sibling(cur,dir){while((cur=cur[dir])&&cur.nodeType!==1){}
+return cur;}
+jQuery.each({parent:function(elem){var parent=elem.parentNode;return parent&&parent.nodeType!==11?parent:null;},parents:function(elem){return jQuery.dir(elem,"parentNode");},parentsUntil:function(elem,i,until){return jQuery.dir(elem,"parentNode",until);},next:function(elem){return sibling(elem,"nextSibling");},prev:function(elem){return sibling(elem,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},nextUntil:function(elem,i,until){return jQuery.dir(elem,"nextSibling",until);},prevUntil:function(elem,i,until){return jQuery.dir(elem,"previousSibling",until);},siblings:function(elem){return jQuery.sibling((elem.parentNode||{}).firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return elem.contentDocument||jQuery.merge([],elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(until,selector){var matched=jQuery.map(this,fn,until);if(name.slice(-5)!=="Until"){selector=until;}
+if(selector&&typeof selector==="string"){matched=jQuery.filter(selector,matched);}
+if(this.length>1){if(!guaranteedUnique[name]){jQuery.unique(matched);}
+if(rparentsprev.test(name)){matched.reverse();}}
+return this.pushStack(matched);};});jQuery.extend({filter:function(expr,elems,not){var elem=elems[0];if(not){expr=":not("+expr+")";}
+return elems.length===1&&elem.nodeType===1?jQuery.find.matchesSelector(elem,expr)?[elem]:[]:jQuery.find.matches(expr,jQuery.grep(elems,function(elem){return elem.nodeType===1;}));},dir:function(elem,dir,until){var matched=[],truncate=until!==undefined;while((elem=elem[dir])&&elem.nodeType!==9){if(elem.nodeType===1){if(truncate&&jQuery(elem).is(until)){break;}
+matched.push(elem);}}
+return matched;},sibling:function(n,elem){var matched=[];for(;n;n=n.nextSibling){if(n.nodeType===1&&n!==elem){matched.push(n);}}
+return matched;}});function winnow(elements,qualifier,not){if(jQuery.isFunction(qualifier)){return jQuery.grep(elements,function(elem,i){return!!qualifier.call(elem,i,elem)!==not;});}
+if(qualifier.nodeType){return jQuery.grep(elements,function(elem){return elem===qualifier!==not;});}
+if(typeof qualifier==="string"){if(isSimple.test(qualifier)){return jQuery.filter(qualifier,elements,not);}
+qualifier=jQuery.filter(qualifier,elements);}
+return jQuery.grep(elements,function(elem){return core_indexOf.call(qualifier,elem)>=0!==not;});}
+var rxhtmlTag=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,rtagName=/<([\w:]+)/,rhtml=/<|&#?\w+;/,rnoInnerhtml=/<(?:script|style|link)/i,manipulation_rcheckableType=/^(?:checkbox|radio)$/i,rchecked=/checked\s*(?:[^=]|=\s*.checked.)/i,rscriptType=/^$|\/(?:java|ecma)script/i,rscriptTypeMasked=/^true\/(.*)/,rcleanScript=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,wrapMap={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};wrapMap.optgroup=wrapMap.option;wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;wrapMap.th=wrapMap.td;jQuery.fn.extend({text:function(value){return jQuery.access(this,function(value){return value===undefined?jQuery.text(this):this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(value));},null,value,arguments.length);},append:function(){return this.domManip(arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.appendChild(elem);}});},prepend:function(){return this.domManip(arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.insertBefore(elem,target.firstChild);}});},before:function(){return this.domManip(arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this);}});},after:function(){return this.domManip(arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this.nextSibling);}});},remove:function(selector,keepData){var elem,elems=selector?jQuery.filter(selector,this):this,i=0;for(;(elem=elems[i])!=null;i++){if(!keepData&&elem.nodeType===1){jQuery.cleanData(getAll(elem));}
+if(elem.parentNode){if(keepData&&jQuery.contains(elem.ownerDocument,elem)){setGlobalEval(getAll(elem,"script"));}
+elem.parentNode.removeChild(elem);}}
+return this;},empty:function(){var elem,i=0;for(;(elem=this[i])!=null;i++){if(elem.nodeType===1){jQuery.cleanData(getAll(elem,false));elem.textContent="";}}
+return this;},clone:function(dataAndEvents,deepDataAndEvents){dataAndEvents=dataAndEvents==null?false:dataAndEvents;deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;return this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents);});},html:function(value){return jQuery.access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(value===undefined&&elem.nodeType===1){return elem.innerHTML;}
+if(typeof value==="string"&&!rnoInnerhtml.test(value)&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=value.replace(rxhtmlTag,"<$1></$2>");try{for(;i<l;i++){elem=this[i]||{};if(elem.nodeType===1){jQuery.cleanData(getAll(elem,false));elem.innerHTML=value;}}
+elem=0;}catch(e){}}
+if(elem){this.empty().append(value);}},null,value,arguments.length);},replaceWith:function(){var args=jQuery.map(this,function(elem){return[elem.nextSibling,elem.parentNode];}),i=0;this.domManip(arguments,function(elem){var next=args[i++],parent=args[i++];if(parent){if(next&&next.parentNode!==parent){next=this.nextSibling;}
+jQuery(this).remove();parent.insertBefore(elem,next);}},true);return i?this:this.remove();},detach:function(selector){return this.remove(selector,true);},domManip:function(args,callback,allowIntersection){args=core_concat.apply([],args);var fragment,first,scripts,hasScripts,node,doc,i=0,l=this.length,set=this,iNoClone=l-1,value=args[0],isFunction=jQuery.isFunction(value);if(isFunction||!(l<=1||typeof value!=="string"||jQuery.support.checkClone||!rchecked.test(value))){return this.each(function(index){var self=set.eq(index);if(isFunction){args[0]=value.call(this,index,self.html());}
+self.domManip(args,callback,allowIntersection);});}
+if(l){fragment=jQuery.buildFragment(args,this[0].ownerDocument,false,!allowIntersection&&this);first=fragment.firstChild;if(fragment.childNodes.length===1){fragment=first;}
+if(first){scripts=jQuery.map(getAll(fragment,"script"),disableScript);hasScripts=scripts.length;for(;i<l;i++){node=fragment;if(i!==iNoClone){node=jQuery.clone(node,true,true);if(hasScripts){jQuery.merge(scripts,getAll(node,"script"));}}
+callback.call(this[i],node,i);}
+if(hasScripts){doc=scripts[scripts.length-1].ownerDocument;jQuery.map(scripts,restoreScript);for(i=0;i<hasScripts;i++){node=scripts[i];if(rscriptType.test(node.type||"")&&!data_priv.access(node,"globalEval")&&jQuery.contains(doc,node)){if(node.src){jQuery._evalUrl(node.src);}else{jQuery.globalEval(node.textContent.replace(rcleanScript,""));}}}}}}
+return this;}});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(selector){var elems,ret=[],insert=jQuery(selector),last=insert.length-1,i=0;for(;i<=last;i++){elems=i===last?this:this.clone(true);jQuery(insert[i])[original](elems);core_push.apply(ret,elems.get());}
+return this.pushStack(ret);};});jQuery.extend({clone:function(elem,dataAndEvents,deepDataAndEvents){var i,l,srcElements,destElements,clone=elem.cloneNode(true),inPage=jQuery.contains(elem.ownerDocument,elem);if(!jQuery.support.noCloneChecked&&(elem.nodeType===1||elem.nodeType===11)&&!jQuery.isXMLDoc(elem)){destElements=getAll(clone);srcElements=getAll(elem);for(i=0,l=srcElements.length;i<l;i++){fixInput(srcElements[i],destElements[i]);}}
+if(dataAndEvents){if(deepDataAndEvents){srcElements=srcElements||getAll(elem);destElements=destElements||getAll(clone);for(i=0,l=srcElements.length;i<l;i++){cloneCopyEvent(srcElements[i],destElements[i]);}}else{cloneCopyEvent(elem,clone);}}
+destElements=getAll(clone,"script");if(destElements.length>0){setGlobalEval(destElements,!inPage&&getAll(elem,"script"));}
+return clone;},buildFragment:function(elems,context,scripts,selection){var elem,tmp,tag,wrap,contains,j,i=0,l=elems.length,fragment=context.createDocumentFragment(),nodes=[];for(;i<l;i++){elem=elems[i];if(elem||elem===0){if(jQuery.type(elem)==="object"){jQuery.merge(nodes,elem.nodeType?[elem]:elem);}else{if(!rhtml.test(elem)){nodes.push(context.createTextNode(elem));}else{tmp=tmp||fragment.appendChild(context.createElement("div"));tag=(rtagName.exec(elem)||["",""])[1].toLowerCase();wrap=wrapMap[tag]||wrapMap._default;tmp.innerHTML=wrap[1]+elem.replace(rxhtmlTag,"<$1></$2>")+wrap[2];j=wrap[0];while(j--){tmp=tmp.firstChild;}
+jQuery.merge(nodes,tmp.childNodes);tmp=fragment.firstChild;tmp.textContent="";}}}}
+fragment.textContent="";i=0;while(elem=nodes[i++]){if(selection&&jQuery.inArray(elem,selection)!==-1){continue;}
+contains=jQuery.contains(elem.ownerDocument,elem);tmp=getAll(fragment.appendChild(elem),"script");if(contains){setGlobalEval(tmp);}
+if(scripts){j=0;while(elem=tmp[j++]){if(rscriptType.test(elem.type||"")){scripts.push(elem);}}}}
+return fragment;},cleanData:function(elems){var data,elem,events,type,key,j,special=jQuery.event.special,i=0;for(;(elem=elems[i])!==undefined;i++){if(Data.accepts(elem)){key=elem[data_priv.expando];if(key&&(data=data_priv.cache[key])){events=Object.keys(data.events||{});if(events.length){for(j=0;(type=events[j])!==undefined;j++){if(special[type]){jQuery.event.remove(elem,type);}else{jQuery.removeEvent(elem,type,data.handle);}}}
+if(data_priv.cache[key]){delete data_priv.cache[key];}}}
+delete data_user.cache[elem[data_user.expando]];}},_evalUrl:function(url){return jQuery.ajax({url:url,type:"GET",dataType:"script",async:false,global:false,"throws":true});}});function manipulationTarget(elem,content){return jQuery.nodeName(elem,"table")&&jQuery.nodeName(content.nodeType===1?content:content.firstChild,"tr")?elem.getElementsByTagName("tbody")[0]||elem.appendChild(elem.ownerDocument.createElement("tbody")):elem;}
+function disableScript(elem){elem.type=(elem.getAttribute("type")!==null)+"/"+elem.type;return elem;}
+function restoreScript(elem){var match=rscriptTypeMasked.exec(elem.type);if(match){elem.type=match[1];}else{elem.removeAttribute("type");}
+return elem;}
+function setGlobalEval(elems,refElements){var l=elems.length,i=0;for(;i<l;i++){data_priv.set(elems[i],"globalEval",!refElements||data_priv.get(refElements[i],"globalEval"));}}
+function cloneCopyEvent(src,dest){var i,l,type,pdataOld,pdataCur,udataOld,udataCur,events;if(dest.nodeType!==1){return;}
+if(data_priv.hasData(src)){pdataOld=data_priv.access(src);pdataCur=data_priv.set(dest,pdataOld);events=pdataOld.events;if(events){delete pdataCur.handle;pdataCur.events={};for(type in events){for(i=0,l=events[type].length;i<l;i++){jQuery.event.add(dest,type,events[type][i]);}}}}
+if(data_user.hasData(src)){udataOld=data_user.access(src);udataCur=jQuery.extend({},udataOld);data_user.set(dest,udataCur);}}
+function getAll(context,tag){var ret=context.getElementsByTagName?context.getElementsByTagName(tag||"*"):context.querySelectorAll?context.querySelectorAll(tag||"*"):[];return tag===undefined||tag&&jQuery.nodeName(context,tag)?jQuery.merge([context],ret):ret;}
+function fixInput(src,dest){var nodeName=dest.nodeName.toLowerCase();if(nodeName==="input"&&manipulation_rcheckableType.test(src.type)){dest.checked=src.checked;}else{if(nodeName==="input"||nodeName==="textarea"){dest.defaultValue=src.defaultValue;}}}
+jQuery.fn.extend({wrapAll:function(html){var wrap;if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapAll(html.call(this,i));});}
+if(this[0]){wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){wrap.insertBefore(this[0]);}
+wrap.map(function(){var elem=this;while(elem.firstElementChild){elem=elem.firstElementChild;}
+return elem;}).append(this);}
+return this;},wrapInner:function(html){if(jQuery.isFunction(html)){return this.each(function(i){jQuery(this).wrapInner(html.call(this,i));});}
+return this.each(function(){var self=jQuery(this),contents=self.contents();if(contents.length){contents.wrapAll(html);}else{self.append(html);}});},wrap:function(html){var isFunction=jQuery.isFunction(html);return this.each(function(i){jQuery(this).wrapAll(isFunction?html.call(this,i):html);});},unwrap:function(){return this.parent().each(function(){if(!jQuery.nodeName(this,"body")){jQuery(this).replaceWith(this.childNodes);}}).end();}});var curCSS,iframe,rdisplayswap=/^(none|table(?!-c[ea]).+)/,rmargin=/^margin/,rnumsplit=new RegExp("^("+core_pnum+")(.*)$","i"),rnumnonpx=new RegExp("^("+core_pnum+")(?!px)[a-z%]+$","i"),rrelNum=new RegExp("^([+-])=("+core_pnum+")","i"),elemdisplay={BODY:"block"},cssShow={position:"absolute",visibility:"hidden",display:"block"},cssNormalTransform={letterSpacing:0,fontWeight:400},cssExpand=["Top","Right","Bottom","Left"],cssPrefixes=["Webkit","O","Moz","ms"];function vendorPropName(style,name){if(name in style){return name;}
+var capName=name.charAt(0).toUpperCase()+name.slice(1),origName=name,i=cssPrefixes.length;while(i--){name=cssPrefixes[i]+capName;if(name in style){return name;}}
+return origName;}
+function isHidden(elem,el){elem=el||elem;return jQuery.css(elem,"display")==="none"||!jQuery.contains(elem.ownerDocument,elem);}
+function getStyles(elem){return window.getComputedStyle(elem,null);}
+function showHide(elements,show){var display,elem,hidden,values=[],index=0,length=elements.length;for(;index<length;index++){elem=elements[index];if(!elem.style){continue;}
+values[index]=data_priv.get(elem,"olddisplay");display=elem.style.display;if(show){if(!values[index]&&display==="none"){elem.style.display="";}
+if(elem.style.display===""&&isHidden(elem)){values[index]=data_priv.access(elem,"olddisplay",css_defaultDisplay(elem.nodeName));}}else{if(!values[index]){hidden=isHidden(elem);if(display&&display!=="none"||!hidden){data_priv.set(elem,"olddisplay",hidden?display:jQuery.css(elem,"display"));}}}}
+for(index=0;index<length;index++){elem=elements[index];if(!elem.style){continue;}
+if(!show||elem.style.display==="none"||elem.style.display===""){elem.style.display=show?values[index]||"":"none";}}
+return elements;}
+jQuery.fn.extend({css:function(name,value){return jQuery.access(this,function(elem,name,value){var styles,len,map={},i=0;if(jQuery.isArray(name)){styles=getStyles(elem);len=name.length;for(;i<len;i++){map[name[i]]=jQuery.css(elem,name[i],false,styles);}
+return map;}
+return value!==undefined?jQuery.style(elem,name,value):jQuery.css(elem,name);},name,value,arguments.length>1);},show:function(){return showHide(this,true);},hide:function(){return showHide(this);},toggle:function(state){var bool=typeof state==="boolean";return this.each(function(){if(bool?state:isHidden(this)){jQuery(this).show();}else{jQuery(this).hide();}});}});jQuery.extend({cssHooks:{opacity:{get:function(elem,computed){if(computed){var ret=curCSS(elem,"opacity");return ret===""?"1":ret;}}}},cssNumber:{"columnCount":true,"fillOpacity":true,"fontWeight":true,"lineHeight":true,"opacity":true,"orphans":true,"widows":true,"zIndex":true,"zoom":true},cssProps:{"float":"cssFloat"},style:function(elem,name,value,extra){if(!elem||elem.nodeType===3||elem.nodeType===8||!elem.style){return;}
+var ret,type,hooks,origName=jQuery.camelCase(name),style=elem.style;name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(style,origName));hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(value!==undefined){type=typeof value;if(type==="string"&&(ret=rrelNum.exec(value))){value=(ret[1]+1)*ret[2]+parseFloat(jQuery.css(elem,name));type="number";}
+if(value==null||type==="number"&&isNaN(value)){return;}
+if(type==="number"&&!jQuery.cssNumber[origName]){value+="px";}
+if(!jQuery.support.clearCloneStyle&&value===""&&name.indexOf("background")===0){style[name]="inherit";}
+if(!hooks||!("set"in hooks)||(value=hooks.set(elem,value,extra))!==undefined){style[name]=value;}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,false,extra))!==undefined){return ret;}
+return style[name];}},css:function(elem,name,extra,styles){var val,num,hooks,origName=jQuery.camelCase(name);name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(elem.style,origName));hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(hooks&&"get"in hooks){val=hooks.get(elem,true,extra);}
+if(val===undefined){val=curCSS(elem,name,styles);}
+if(val==="normal"&&name in cssNormalTransform){val=cssNormalTransform[name];}
+if(extra===""||extra){num=parseFloat(val);return extra===true||jQuery.isNumeric(num)?num||0:val;}
+return val;}});curCSS=function(elem,name,_computed){var width,minWidth,maxWidth,computed=_computed||getStyles(elem),ret=computed?computed.getPropertyValue(name)||computed[name]:undefined,style=elem.style;if(computed){if(ret===""&&!jQuery.contains(elem.ownerDocument,elem)){ret=jQuery.style(elem,name);}
+if(rnumnonpx.test(ret)&&rmargin.test(name)){width=style.width;minWidth=style.minWidth;maxWidth=style.maxWidth;style.minWidth=style.maxWidth=style.width=ret;ret=computed.width;style.width=width;style.minWidth=minWidth;style.maxWidth=maxWidth;}}
+return ret;};function setPositiveNumber(elem,value,subtract){var matches=rnumsplit.exec(value);return matches?Math.max(0,matches[1]-(subtract||0))+(matches[2]||"px"):value;}
+function augmentWidthOrHeight(elem,name,extra,isBorderBox,styles){var i=extra===(isBorderBox?"border":"content")?4:name==="width"?1:0,val=0;for(;i<4;i+=2){if(extra==="margin"){val+=jQuery.css(elem,extra+cssExpand[i],true,styles);}
+if(isBorderBox){if(extra==="content"){val-=jQuery.css(elem,"padding"+cssExpand[i],true,styles);}
+if(extra!=="margin"){val-=jQuery.css(elem,"border"+cssExpand[i]+"Width",true,styles);}}else{val+=jQuery.css(elem,"padding"+cssExpand[i],true,styles);if(extra!=="padding"){val+=jQuery.css(elem,"border"+cssExpand[i]+"Width",true,styles);}}}
+return val;}
+function getWidthOrHeight(elem,name,extra){var valueIsBorderBox=true,val=name==="width"?elem.offsetWidth:elem.offsetHeight,styles=getStyles(elem),isBorderBox=jQuery.support.boxSizing&&jQuery.css(elem,"boxSizing",false,styles)==="border-box";if(val<=0||val==null){val=curCSS(elem,name,styles);if(val<0||val==null){val=elem.style[name];}
+if(rnumnonpx.test(val)){return val;}
+valueIsBorderBox=isBorderBox&&(jQuery.support.boxSizingReliable||val===elem.style[name]);val=parseFloat(val)||0;}
+return val+augmentWidthOrHeight(elem,name,extra||(isBorderBox?"border":"content"),valueIsBorderBox,styles)+"px";}
+function css_defaultDisplay(nodeName){var doc=document,display=elemdisplay[nodeName];if(!display){display=actualDisplay(nodeName,doc);if(display==="none"||!display){iframe=(iframe||jQuery("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(doc.documentElement);doc=(iframe[0].contentWindow||iframe[0].contentDocument).document;doc.write("<!doctype html><html><body>");doc.close();display=actualDisplay(nodeName,doc);iframe.detach();}
+elemdisplay[nodeName]=display;}
+return display;}
+function actualDisplay(name,doc){var elem=jQuery(doc.createElement(name)).appendTo(doc.body),display=jQuery.css(elem[0],"display");elem.remove();return display;}
+jQuery.each(["height","width"],function(i,name){jQuery.cssHooks[name]={get:function(elem,computed,extra){if(computed){return elem.offsetWidth===0&&rdisplayswap.test(jQuery.css(elem,"display"))?jQuery.swap(elem,cssShow,function(){return getWidthOrHeight(elem,name,extra);}):getWidthOrHeight(elem,name,extra);}},set:function(elem,value,extra){var styles=extra&&getStyles(elem);return setPositiveNumber(elem,value,extra?augmentWidthOrHeight(elem,name,extra,jQuery.support.boxSizing&&jQuery.css(elem,"boxSizing",false,styles)==="border-box",styles):0);}};});jQuery(function(){if(!jQuery.support.reliableMarginRight){jQuery.cssHooks.marginRight={get:function(elem,computed){if(computed){return jQuery.swap(elem,{"display":"inline-block"},curCSS,[elem,"marginRight"]);}}};}
+if(!jQuery.support.pixelPosition&&jQuery.fn.position){jQuery.each(["top","left"],function(i,prop){jQuery.cssHooks[prop]={get:function(elem,computed){if(computed){computed=curCSS(elem,prop);return rnumnonpx.test(computed)?jQuery(elem).position()[prop]+"px":computed;}}};});}});if(jQuery.expr&&jQuery.expr.filters){jQuery.expr.filters.hidden=function(elem){return elem.offsetWidth<=0&&elem.offsetHeight<=0;};jQuery.expr.filters.visible=function(elem){return!jQuery.expr.filters.hidden(elem);};}
+jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){var i=0,expanded={},parts=typeof value==="string"?value.split(" "):[value];for(;i<4;i++){expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0];}
+return expanded;}};if(!rmargin.test(prefix)){jQuery.cssHooks[prefix+suffix].set=setPositiveNumber;}});var r20=/%20/g,rbracket=/\[\]$/,rCRLF=/\r?\n/g,rsubmitterTypes=/^(?:submit|button|image|reset|file)$/i,rsubmittable=/^(?:input|select|textarea|keygen)/i;jQuery.fn.extend({serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){var elements=jQuery.prop(this,"elements");return elements?jQuery.makeArray(elements):this;}).filter(function(){var type=this.type;return this.name&&!jQuery(this).is(":disabled")&&rsubmittable.test(this.nodeName)&&!rsubmitterTypes.test(type)&&(this.checked||!manipulation_rcheckableType.test(type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:jQuery.isArray(val)?jQuery.map(val,function(val){return{name:elem.name,value:val.replace(rCRLF,"\r\n")};}):{name:elem.name,value:val.replace(rCRLF,"\r\n")};}).get();}});jQuery.param=function(a,traditional){var prefix,s=[],add=function(key,value){value=jQuery.isFunction(value)?value():value==null?"":value;s[s.length]=encodeURIComponent(key)+"="+encodeURIComponent(value);};if(traditional===undefined){traditional=jQuery.ajaxSettings&&jQuery.ajaxSettings.traditional;}
+if(jQuery.isArray(a)||a.jquery&&!jQuery.isPlainObject(a)){jQuery.each(a,function(){add(this.name,this.value);});}else{for(prefix in a){buildParams(prefix,a[prefix],traditional,add);}}
+return s.join("&").replace(r20,"+");};function buildParams(prefix,obj,traditional,add){var name;if(jQuery.isArray(obj)){jQuery.each(obj,function(i,v){if(traditional||rbracket.test(prefix)){add(prefix,v);}else{buildParams(prefix+"["+(typeof v==="object"?i:"")+"]",v,traditional,add);}});}else{if(!traditional&&jQuery.type(obj)==="object"){for(name in obj){buildParams(prefix+"["+name+"]",obj[name],traditional,add);}}else{add(prefix,obj);}}}
+jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick "+"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave "+"change select submit keydown keypress keyup error contextmenu").split(" "),function(i,name){jQuery.fn[name]=function(data,fn){return arguments.length>0?this.on(name,null,data,fn):this.trigger(name);};});jQuery.fn.extend({hover:function(fnOver,fnOut){return this.mouseenter(fnOver).mouseleave(fnOut||fnOver);},bind:function(types,data,fn){return this.on(types,null,data,fn);},unbind:function(types,fn){return this.off(types,null,fn);},delegate:function(selector,types,data,fn){return this.on(types,selector,data,fn);},undelegate:function(selector,types,fn){return arguments.length===1?this.off(selector,"**"):this.off(types,selector||"**",fn);}});var ajaxLocParts,ajaxLocation,ajax_nonce=jQuery.now(),ajax_rquery=/\?/,rhash=/#.*$/,rts=/([?&])_=[^&]*/,rheaders=/^(.*?):[ \t]*([^\r\n]*)$/mg,rlocalProtocol=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,rurl=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,_load=jQuery.fn.load,prefilters={},transports={},allTypes="*/".concat("*");try{ajaxLocation=location.href;}catch(e){ajaxLocation=document.createElement("a");ajaxLocation.href="";ajaxLocation=ajaxLocation.href;}
+ajaxLocParts=rurl.exec(ajaxLocation.toLowerCase())||[];function addToPrefiltersOrTransports(structure){return function(dataTypeExpression,func){if(typeof dataTypeExpression!=="string"){func=dataTypeExpression;dataTypeExpression="*";}
+var dataType,i=0,dataTypes=dataTypeExpression.toLowerCase().match(core_rnotwhite)||[];if(jQuery.isFunction(func)){while(dataType=dataTypes[i++]){if(dataType[0]==="+"){dataType=dataType.slice(1)||"*";(structure[dataType]=structure[dataType]||[]).unshift(func);}else{(structure[dataType]=structure[dataType]||[]).push(func);}}}};}
+function inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR){var inspected={},seekingTransport=structure===transports;function inspect(dataType){var selected;inspected[dataType]=true;jQuery.each(structure[dataType]||[],function(_,prefilterOrFactory){var dataTypeOrTransport=prefilterOrFactory(options,originalOptions,jqXHR);if(typeof dataTypeOrTransport==="string"&&!seekingTransport&&!inspected[dataTypeOrTransport]){options.dataTypes.unshift(dataTypeOrTransport);inspect(dataTypeOrTransport);return false;}else{if(seekingTransport){return!(selected=dataTypeOrTransport);}}});return selected;}
+return inspect(options.dataTypes[0])||!inspected["*"]&&inspect("*");}
+function ajaxExtend(target,src){var key,deep,flatOptions=jQuery.ajaxSettings.flatOptions||{};for(key in src){if(src[key]!==undefined){(flatOptions[key]?target:deep||(deep={}))[key]=src[key];}}
+if(deep){jQuery.extend(true,target,deep);}
+return target;}
+jQuery.fn.load=function(url,params,callback){if(typeof url!=="string"&&_load){return _load.apply(this,arguments);}
+var selector,type,response,self=this,off=url.indexOf(" ");if(off>=0){selector=url.slice(off);url=url.slice(0,off);}
+if(jQuery.isFunction(params)){callback=params;params=undefined;}else{if(params&&typeof params==="object"){type="POST";}}
+if(self.length>0){jQuery.ajax({url:url,type:type,dataType:"html",data:params}).done(function(responseText){response=arguments;self.html(selector?jQuery("<div>").append(jQuery.parseHTML(responseText)).find(selector):responseText);}).complete(callback&&function(jqXHR,status){self.each(callback,response||[jqXHR.responseText,status,jqXHR]);});}
+return this;};jQuery.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(i,type){jQuery.fn[type]=function(fn){return this.on(type,fn);};});jQuery.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ajaxLocation,type:"GET",isLocal:rlocalProtocol.test(ajaxLocParts[1]),global:true,processData:true,async:true,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":allTypes,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":true,"text json":jQuery.parseJSON,"text xml":jQuery.parseXML},flatOptions:{url:true,context:true}},ajaxSetup:function(target,settings){return settings?ajaxExtend(ajaxExtend(target,jQuery.ajaxSettings),settings):ajaxExtend(jQuery.ajaxSettings,target);},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){if(typeof url==="object"){options=url;url=undefined;}
+options=options||{};var transport,cacheURL,responseHeadersString,responseHeaders,timeoutTimer,parts,fireGlobals,i,s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=s.context&&(callbackContext.nodeType||callbackContext.jquery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},requestHeaders={},requestHeadersNames={},state=0,strAbort="canceled",jqXHR={readyState:0,getResponseHeader:function(key){var match;if(state===2){if(!responseHeaders){responseHeaders={};while(match=rheaders.exec(responseHeadersString)){responseHeaders[match[1].toLowerCase()]=match[2];}}
+match=responseHeaders[key.toLowerCase()];}
+return match==null?null:match;},getAllResponseHeaders:function(){return state===2?responseHeadersString:null;},setRequestHeader:function(name,value){var lname=name.toLowerCase();if(!state){name=requestHeadersNames[lname]=requestHeadersNames[lname]||name;requestHeaders[name]=value;}
+return this;},overrideMimeType:function(type){if(!state){s.mimeType=type;}
+return this;},statusCode:function(map){var code;if(map){if(state<2){for(code in map){statusCode[code]=[statusCode[code],map[code]];}}else{jqXHR.always(map[jqXHR.status]);}}
+return this;},abort:function(statusText){var finalText=statusText||strAbort;if(transport){transport.abort(finalText);}
+done(0,finalText);return this;}};deferred.promise(jqXHR).complete=completeDeferred.add;jqXHR.success=jqXHR.done;jqXHR.error=jqXHR.fail;s.url=((url||s.url||ajaxLocation)+"").replace(rhash,"").replace(rprotocol,ajaxLocParts[1]+"//");s.type=options.method||options.type||s.method||s.type;s.dataTypes=jQuery.trim(s.dataType||"*").toLowerCase().match(core_rnotwhite)||[""];if(s.crossDomain==null){parts=rurl.exec(s.url.toLowerCase());s.crossDomain=!!(parts&&(parts[1]!==ajaxLocParts[1]||parts[2]!==ajaxLocParts[2]||(parts[3]||(parts[1]==="http:"?"80":"443"))!==(ajaxLocParts[3]||(ajaxLocParts[1]==="http:"?"80":"443"))));}
+if(s.data&&s.processData&&typeof s.data!=="string"){s.data=jQuery.param(s.data,s.traditional);}
+inspectPrefiltersOrTransports(prefilters,s,options,jqXHR);if(state===2){return jqXHR;}
+fireGlobals=s.global;if(fireGlobals&&jQuery.active++===0){jQuery.event.trigger("ajaxStart");}
+s.type=s.type.toUpperCase();s.hasContent=!rnoContent.test(s.type);cacheURL=s.url;if(!s.hasContent){if(s.data){cacheURL=s.url+=(ajax_rquery.test(cacheURL)?"&":"?")+s.data;delete s.data;}
+if(s.cache===false){s.url=rts.test(cacheURL)?cacheURL.replace(rts,"$1_="+ajax_nonce++):cacheURL+(ajax_rquery.test(cacheURL)?"&":"?")+"_="+ajax_nonce++;}}
+if(s.ifModified){if(jQuery.lastModified[cacheURL]){jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[cacheURL]);}
+if(jQuery.etag[cacheURL]){jqXHR.setRequestHeader("If-None-Match",jQuery.etag[cacheURL]);}}
+if(s.data&&s.hasContent&&s.contentType!==false||options.contentType){jqXHR.setRequestHeader("Content-Type",s.contentType);}
+jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+(s.dataTypes[0]!=="*"?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers){jqXHR.setRequestHeader(i,s.headers[i]);}
+if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===false||state===2)){return jqXHR.abort();}
+strAbort="abort";for(i in{success:1,error:1,complete:1}){jqXHR[i](s[i]);}
+transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR);if(!transport){done(-1,"No Transport");}else{jqXHR.readyState=1;if(fireGlobals){globalEventContext.trigger("ajaxSend",[jqXHR,s]);}
+if(s.async&&s.timeout>0){timeoutTimer=setTimeout(function(){jqXHR.abort("timeout");},s.timeout);}
+try{state=1;transport.send(requestHeaders,done);}catch(e$2){if(state<2){done(-1,e$2);}else{throw e$2;}}}
+function done(status,nativeStatusText,responses,headers){var isSuccess,success,error,response,modified,statusText=nativeStatusText;if(state===2){return;}
+state=2;if(timeoutTimer){clearTimeout(timeoutTimer);}
+transport=undefined;responseHeadersString=headers||"";jqXHR.readyState=status>0?4:0;isSuccess=status>=200&&status<300||status===304;if(responses){response=ajaxHandleResponses(s,jqXHR,responses);}
+response=ajaxConvert(s,response,jqXHR,isSuccess);if(isSuccess){if(s.ifModified){modified=jqXHR.getResponseHeader("Last-Modified");if(modified){jQuery.lastModified[cacheURL]=modified;}
+modified=jqXHR.getResponseHeader("etag");if(modified){jQuery.etag[cacheURL]=modified;}}
+if(status===204||s.type==="HEAD"){statusText="nocontent";}else{if(status===304){statusText="notmodified";}else{statusText=response.state;success=response.data;error=response.error;isSuccess=!error;}}}else{error=statusText;if(status||!statusText){statusText="error";if(status<0){status=0;}}}
+jqXHR.status=status;jqXHR.statusText=(nativeStatusText||statusText)+"";if(isSuccess){deferred.resolveWith(callbackContext,[success,statusText,jqXHR]);}else{deferred.rejectWith(callbackContext,[jqXHR,statusText,error]);}
+jqXHR.statusCode(statusCode);statusCode=undefined;if(fireGlobals){globalEventContext.trigger(isSuccess?"ajaxSuccess":"ajaxError",[jqXHR,s,isSuccess?success:error]);}
+completeDeferred.fireWith(callbackContext,[jqXHR,statusText]);if(fireGlobals){globalEventContext.trigger("ajaxComplete",[jqXHR,s]);if(!--jQuery.active){jQuery.event.trigger("ajaxStop");}}}
+return jqXHR;},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},getScript:function(url,callback){return jQuery.get(url,undefined,callback,"script");}});jQuery.each(["get","post"],function(i,method){jQuery[method]=function(url,data,callback,type){if(jQuery.isFunction(data)){type=type||callback;callback=data;data=undefined;}
+return jQuery.ajax({url:url,type:method,dataType:type,data:data,success:callback});};});function ajaxHandleResponses(s,jqXHR,responses){var ct,type,finalDataType,firstDataType,contents=s.contents,dataTypes=s.dataTypes;while(dataTypes[0]==="*"){dataTypes.shift();if(ct===undefined){ct=s.mimeType||jqXHR.getResponseHeader("Content-Type");}}
+if(ct){for(type in contents){if(contents[type]&&contents[type].test(ct)){dataTypes.unshift(type);break;}}}
+if(dataTypes[0]in responses){finalDataType=dataTypes[0];}else{for(type in responses){if(!dataTypes[0]||s.converters[type+" "+dataTypes[0]]){finalDataType=type;break;}
+if(!firstDataType){firstDataType=type;}}
+finalDataType=finalDataType||firstDataType;}
+if(finalDataType){if(finalDataType!==dataTypes[0]){dataTypes.unshift(finalDataType);}
+return responses[finalDataType];}}
+function ajaxConvert(s,response,jqXHR,isSuccess){var conv2,current,conv,tmp,prev,converters={},dataTypes=s.dataTypes.slice();if(dataTypes[1]){for(conv in s.converters){converters[conv.toLowerCase()]=s.converters[conv];}}
+current=dataTypes.shift();while(current){if(s.responseFields[current]){jqXHR[s.responseFields[current]]=response;}
+if(!prev&&isSuccess&&s.dataFilter){response=s.dataFilter(response,s.dataType);}
+prev=current;current=dataTypes.shift();if(current){if(current==="*"){current=prev;}else{if(prev!=="*"&&prev!==current){conv=converters[prev+" "+current]||converters["* "+current];if(!conv){for(conv2 in converters){tmp=conv2.split(" ");if(tmp[1]===current){conv=converters[prev+" "+tmp[0]]||converters["* "+tmp[0]];if(conv){if(conv===true){conv=converters[conv2];}else{if(converters[conv2]!==true){current=tmp[0];dataTypes.unshift(tmp[1]);}}
+break;}}}}
+if(conv!==true){if(conv&&s["throws"]){response=conv(response);}else{try{response=conv(response);}catch(e$3){return{state:"parsererror",error:conv?e$3:"No conversion from "+prev+" to "+current};}}}}}}}
+return{state:"success",data:response};}
+jQuery.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(text){jQuery.globalEval(text);return text;}}});jQuery.ajaxPrefilter("script",function(s){if(s.cache===undefined){s.cache=false;}
+if(s.crossDomain){s.type="GET";}});jQuery.ajaxTransport("script",function(s){if(s.crossDomain){var script,callback;return{send:function(_,complete){script=jQuery("<script>").prop({async:true,charset:s.scriptCharset,src:s.url}).on("load error",callback=function(evt){script.remove();callback=null;if(evt){complete(evt.type==="error"?404:200,evt.type);}});document.head.appendChild(script[0]);},abort:function(){if(callback){callback();}}};}});var oldCallbacks=[],rjsonp=/(=)\?(?=&|$)|\?\?/;jQuery.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var callback=oldCallbacks.pop()||jQuery.expando+"_"+ajax_nonce++;this[callback]=true;return callback;}});jQuery.ajaxPrefilter("json jsonp",function(s,originalSettings,jqXHR){var callbackName,overwritten,responseContainer,jsonProp=s.jsonp!==false&&(rjsonp.test(s.url)?"url":typeof s.data==="string"&&!(s.contentType||"").indexOf("application/x-www-form-urlencoded")&&rjsonp.test(s.data)&&"data");if(jsonProp||s.dataTypes[0]==="jsonp"){callbackName=s.jsonpCallback=jQuery.isFunction(s.jsonpCallback)?s.jsonpCallback():s.jsonpCallback;if(jsonProp){s[jsonProp]=s[jsonProp].replace(rjsonp,"$1"+callbackName);}else{if(s.jsonp!==false){s.url+=(ajax_rquery.test(s.url)?"&":"?")+s.jsonp+"="+callbackName;}}
+s.converters["script json"]=function(){if(!responseContainer){jQuery.error(callbackName+" was not called");}
+return responseContainer[0];};s.dataTypes[0]="json";overwritten=window[callbackName];window[callbackName]=function(){responseContainer=arguments;};jqXHR.always(function(){window[callbackName]=overwritten;if(s[callbackName]){s.jsonpCallback=originalSettings.jsonpCallback;oldCallbacks.push(callbackName);}
+if(responseContainer&&jQuery.isFunction(overwritten)){overwritten(responseContainer[0]);}
+responseContainer=overwritten=undefined;});return"script";}});jQuery.ajaxSettings.xhr=function(){try{return new XMLHttpRequest;}catch(e$4){}};var xhrSupported=jQuery.ajaxSettings.xhr(),xhrSuccessStatus={0:200,1223:204},xhrId=0,xhrCallbacks={};if(window.ActiveXObject){jQuery(window).on("unload",function(){for(var key in xhrCallbacks){xhrCallbacks[key]();}
+xhrCallbacks=undefined;});}
+jQuery.support.cors=!!xhrSupported&&"withCredentials"in xhrSupported;jQuery.support.ajax=xhrSupported=!!xhrSupported;jQuery.ajaxTransport(function(options){var callback;if(jQuery.support.cors||xhrSupported&&!options.crossDomain){return{send:function(headers,complete){var i,id,xhr=options.xhr();xhr.open(options.type,options.url,options.async,options.username,options.password);if(options.xhrFields){for(i in options.xhrFields){xhr[i]=options.xhrFields[i];}}
+if(options.mimeType&&xhr.overrideMimeType){xhr.overrideMimeType(options.mimeType);}
+if(!options.crossDomain&&!headers["X-Requested-With"]){headers["X-Requested-With"]="XMLHttpRequest";}
+for(i in headers){xhr.setRequestHeader(i,headers[i]);}
+callback=function(type){return function(){if(callback){delete xhrCallbacks[id];callback=xhr.onload=xhr.onerror=null;if(type==="abort"){xhr.abort();}else{if(type==="error"){complete(xhr.status||404,xhr.statusText);}else{complete(xhrSuccessStatus[xhr.status]||xhr.status,xhr.statusText,typeof xhr.responseText==="string"?{text:xhr.responseText}:undefined,xhr.getAllResponseHeaders());}}}};};xhr.onload=callback();xhr.onerror=callback("error");callback=xhrCallbacks[id=xhrId++]=callback("abort");xhr.send(options.hasContent&&options.data||null);},abort:function(){if(callback){callback();}}};}});var fxNow,timerId,rfxtypes=/^(?:toggle|show|hide)$/,rfxnum=new RegExp("^(?:([+-])=|)("+core_pnum+")([a-z%]*)$","i"),rrun=/queueHooks$/,animationPrefilters=[defaultPrefilter],tweeners={"*":[function(prop,value){var tween=this.createTween(prop,value),target=tween.cur(),parts=rfxnum.exec(value),unit=parts&&parts[3]||(jQuery.cssNumber[prop]?"":"px"),start=(jQuery.cssNumber[prop]||unit!=="px"&&+target)&&rfxnum.exec(jQuery.css(tween.elem,prop)),scale=1,maxIterations=20;if(start&&start[3]!==unit){unit=unit||start[3];parts=parts||[];start=+target||1;do{scale=scale||".5";start=start / scale;jQuery.style(tween.elem,prop,start+unit);}while(scale!==(scale=tween.cur()/ target)&&scale!==1&&--maxIterations);}
+if(parts){start=tween.start=+start||+target||0;tween.unit=unit;tween.end=parts[1]?start+(parts[1]+1)*parts[2]:+parts[2];}
+return tween;}]};function createFxNow(){setTimeout(function(){fxNow=undefined;});return fxNow=jQuery.now();}
+function createTween(value,prop,animation){var tween,collection=(tweeners[prop]||[]).concat(tweeners["*"]),index=0,length=collection.length;for(;index<length;index++){if(tween=collection[index].call(animation,prop,value)){return tween;}}}
+function Animation(elem,properties,options){var result,stopped,index=0,length=animationPrefilters.length,deferred=jQuery.Deferred().always(function(){delete tick.elem;}),tick=function(){if(stopped){return false;}
+var currentTime=fxNow||createFxNow(),remaining=Math.max(0,animation.startTime+animation.duration-currentTime),temp=remaining / animation.duration||0,percent=1-temp,index=0,length=animation.tweens.length;for(;index<length;index++){animation.tweens[index].run(percent);}
+deferred.notifyWith(elem,[animation,percent,remaining]);if(percent<1&&length){return remaining;}else{deferred.resolveWith(elem,[animation]);return false;}},animation=deferred.promise({elem:elem,props:jQuery.extend({},properties),opts:jQuery.extend(true,{specialEasing:{}},options),originalProperties:properties,originalOptions:options,startTime:fxNow||createFxNow(),duration:options.duration,tweens:[],createTween:function(prop,end){var tween=jQuery.Tween(elem,animation.opts,prop,end,animation.opts.specialEasing[prop]||animation.opts.easing);animation.tweens.push(tween);return tween;},stop:function(gotoEnd){var index=0,length=gotoEnd?animation.tweens.length:0;if(stopped){return this;}
+stopped=true;for(;index<length;index++){animation.tweens[index].run(1);}
+if(gotoEnd){deferred.resolveWith(elem,[animation,gotoEnd]);}else{deferred.rejectWith(elem,[animation,gotoEnd]);}
+return this;}}),props=animation.props;propFilter(props,animation.opts.specialEasing);for(;index<length;index++){result=animationPrefilters[index].call(animation,elem,props,animation.opts);if(result){return result;}}
+jQuery.map(props,createTween,animation);if(jQuery.isFunction(animation.opts.start)){animation.opts.start.call(elem,animation);}
+jQuery.fx.timer(jQuery.extend(tick,{elem:elem,anim:animation,queue:animation.opts.queue}));return animation.progress(animation.opts.progress).done(animation.opts.done,animation.opts.complete).fail(animation.opts.fail).always(animation.opts.always);}
+function propFilter(props,specialEasing){var index,name,easing,value,hooks;for(index in props){name=jQuery.camelCase(index);easing=specialEasing[name];value=props[index];if(jQuery.isArray(value)){easing=value[1];value=props[index]=value[0];}
+if(index!==name){props[name]=value;delete props[index];}
+hooks=jQuery.cssHooks[name];if(hooks&&"expand"in hooks){value=hooks.expand(value);delete props[name];for(index in value){if(!(index in props)){props[index]=value[index];specialEasing[index]=easing;}}}else{specialEasing[name]=easing;}}}
+jQuery.Animation=jQuery.extend(Animation,{tweener:function(props,callback){if(jQuery.isFunction(props)){callback=props;props=["*"];}else{props=props.split(" ");}
+var prop,index=0,length=props.length;for(;index<length;index++){prop=props[index];tweeners[prop]=tweeners[prop]||[];tweeners[prop].unshift(callback);}},prefilter:function(callback,prepend){if(prepend){animationPrefilters.unshift(callback);}else{animationPrefilters.push(callback);}}});function defaultPrefilter(elem,props,opts){var prop,value,toggle,tween,hooks,oldfire,anim=this,orig={},style=elem.style,hidden=elem.nodeType&&isHidden(elem),dataShow=data_priv.get(elem,"fxshow");if(!opts.queue){hooks=jQuery._queueHooks(elem,"fx");if(hooks.unqueued==null){hooks.unqueued=0;oldfire=hooks.empty.fire;hooks.empty.fire=function(){if(!hooks.unqueued){oldfire();}};}
+hooks.unqueued++;anim.always(function(){anim.always(function(){hooks.unqueued--;if(!jQuery.queue(elem,"fx").length){hooks.empty.fire();}});});}
+if(elem.nodeType===1&&("height"in props||"width"in props)){opts.overflow=[style.overflow,style.overflowX,style.overflowY];if(jQuery.css(elem,"display")==="inline"&&jQuery.css(elem,"float")==="none"){style.display="inline-block";}}
+if(opts.overflow){style.overflow="hidden";anim.always(function(){style.overflow=opts.overflow[0];style.overflowX=opts.overflow[1];style.overflowY=opts.overflow[2];});}
+for(prop in props){value=props[prop];if(rfxtypes.exec(value)){delete props[prop];toggle=toggle||value==="toggle";if(value===(hidden?"hide":"show")){if(value==="show"&&dataShow&&dataShow[prop]!==undefined){hidden=true;}else{continue;}}
+orig[prop]=dataShow&&dataShow[prop]||jQuery.style(elem,prop);}}
+if(!jQuery.isEmptyObject(orig)){if(dataShow){if("hidden"in dataShow){hidden=dataShow.hidden;}}else{dataShow=data_priv.access(elem,"fxshow",{});}
+if(toggle){dataShow.hidden=!hidden;}
+if(hidden){jQuery(elem).show();}else{anim.done(function(){jQuery(elem).hide();});}
+anim.done(function(){var prop;data_priv.remove(elem,"fxshow");for(prop in orig){jQuery.style(elem,prop,orig[prop]);}});for(prop in orig){tween=createTween(hidden?dataShow[prop]:0,prop,anim);if(!(prop in dataShow)){dataShow[prop]=tween.start;if(hidden){tween.end=tween.start;tween.start=prop==="width"||prop==="height"?1:0;}}}}}
+function Tween(elem,options,prop,end,easing){return new Tween.prototype.init(elem,options,prop,end,easing);}
+jQuery.Tween=Tween;Tween.prototype={constructor:Tween,init:function(elem,options,prop,end,easing,unit){this.elem=elem;this.prop=prop;this.easing=easing||"swing";this.options=options;this.start=this.now=this.cur();this.end=end;this.unit=unit||(jQuery.cssNumber[prop]?"":"px");},cur:function(){var hooks=Tween.propHooks[this.prop];return hooks&&hooks.get?hooks.get(this):Tween.propHooks._default.get(this);},run:function(percent){var eased,hooks=Tween.propHooks[this.prop];if(this.options.duration){this.pos=eased=jQuery.easing[this.easing](percent,this.options.duration*percent,0,1,this.options.duration);}else{this.pos=eased=percent;}
+this.now=(this.end-this.start)*eased+this.start;if(this.options.step){this.options.step.call(this.elem,this.now,this);}
+if(hooks&&hooks.set){hooks.set(this);}else{Tween.propHooks._default.set(this);}
+return this;}};Tween.prototype.init.prototype=Tween.prototype;Tween.propHooks={_default:{get:function(tween){var result;if(tween.elem[tween.prop]!=null&&(!tween.elem.style||tween.elem.style[tween.prop]==null)){return tween.elem[tween.prop];}
+result=jQuery.css(tween.elem,tween.prop,"");return!result||result==="auto"?0:result;},set:function(tween){if(jQuery.fx.step[tween.prop]){jQuery.fx.step[tween.prop](tween);}else{if(tween.elem.style&&(tween.elem.style[jQuery.cssProps[tween.prop]]!=null||jQuery.cssHooks[tween.prop])){jQuery.style(tween.elem,tween.prop,tween.now+tween.unit);}else{tween.elem[tween.prop]=tween.now;}}}}};Tween.propHooks.scrollTop=Tween.propHooks.scrollLeft={set:function(tween){if(tween.elem.nodeType&&tween.elem.parentNode){tween.elem[tween.prop]=tween.now;}}};jQuery.each(["toggle","show","hide"],function(i,name){var cssFn=jQuery.fn[name];jQuery.fn[name]=function(speed,easing,callback){return speed==null||typeof speed==="boolean"?cssFn.apply(this,arguments):this.animate(genFx(name,true),speed,easing,callback);};});jQuery.fn.extend({fadeTo:function(speed,to,easing,callback){return this.filter(isHidden).css("opacity",0).show().end().animate({opacity:to},speed,easing,callback);},animate:function(prop,speed,easing,callback){var empty=jQuery.isEmptyObject(prop),optall=jQuery.speed(speed,easing,callback),doAnimation=function(){var anim=Animation(this,jQuery.extend({},prop),optall);if(empty||data_priv.get(this,"finish")){anim.stop(true);}};doAnimation.finish=doAnimation;return empty||optall.queue===false?this.each(doAnimation):this.queue(optall.queue,doAnimation);},stop:function(type,clearQueue,gotoEnd){var stopQueue=function(hooks){var stop=hooks.stop;delete hooks.stop;stop(gotoEnd);};if(typeof type!=="string"){gotoEnd=clearQueue;clearQueue=type;type=undefined;}
+if(clearQueue&&type!==false){this.queue(type||"fx",[]);}
+return this.each(function(){var dequeue=true,index=type!=null&&type+"queueHooks",timers=jQuery.timers,data=data_priv.get(this);if(index){if(data[index]&&data[index].stop){stopQueue(data[index]);}}else{for(index in data){if(data[index]&&data[index].stop&&rrun.test(index)){stopQueue(data[index]);}}}
+for(index=timers.length;index--;){if(timers[index].elem===this&&(type==null||timers[index].queue===type)){timers[index].anim.stop(gotoEnd);dequeue=false;timers.splice(index,1);}}
+if(dequeue||!gotoEnd){jQuery.dequeue(this,type);}});},finish:function(type){if(type!==false){type=type||"fx";}
+return this.each(function(){var index,data=data_priv.get(this),queue=data[type+"queue"],hooks=data[type+"queueHooks"],timers=jQuery.timers,length=queue?queue.length:0;data.finish=true;jQuery.queue(this,type,[]);if(hooks&&hooks.stop){hooks.stop.call(this,true);}
+for(index=timers.length;index--;){if(timers[index].elem===this&&timers[index].queue===type){timers[index].anim.stop(true);timers.splice(index,1);}}
+for(index=0;index<length;index++){if(queue[index]&&queue[index].finish){queue[index].finish.call(this);}}
+delete data.finish;});}});function genFx(type,includeWidth){var which,attrs={height:type},i=0;includeWidth=includeWidth?1:0;for(;i<4;i+=2-includeWidth){which=cssExpand[i];attrs["margin"+which]=attrs["padding"+which]=type;}
+if(includeWidth){attrs.opacity=attrs.width=type;}
+return attrs;}
+jQuery.each({slideDown:genFx("show"),slideUp:genFx("hide"),slideToggle:genFx("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(name,props){jQuery.fn[name]=function(speed,easing,callback){return this.animate(props,speed,easing,callback);};});jQuery.speed=function(speed,easing,fn){var opt=speed&&typeof speed==="object"?jQuery.extend({},speed):{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&!jQuery.isFunction(easing)&&easing};opt.duration=jQuery.fx.off?0:typeof opt.duration==="number"?opt.duration:opt.duration in jQuery.fx.speeds?jQuery.fx.speeds[opt.duration]:jQuery.fx.speeds._default;if(opt.queue==null||opt.queue===true){opt.queue="fx";}
+opt.old=opt.complete;opt.complete=function(){if(jQuery.isFunction(opt.old)){opt.old.call(this);}
+if(opt.queue){jQuery.dequeue(this,opt.queue);}};return opt;};jQuery.easing={linear:function(p){return p;},swing:function(p){return.5-Math.cos(p*Math.PI)/ 2;}};jQuery.timers=[];jQuery.fx=Tween.prototype.init;jQuery.fx.tick=function(){var timer,timers=jQuery.timers,i=0;fxNow=jQuery.now();for(;i<timers.length;i++){timer=timers[i];if(!timer()&&timers[i]===timer){timers.splice(i--,1);}}
+if(!timers.length){jQuery.fx.stop();}
+fxNow=undefined;};jQuery.fx.timer=function(timer){if(timer()&&jQuery.timers.push(timer)){jQuery.fx.start();}};jQuery.fx.interval=13;jQuery.fx.start=function(){if(!timerId){timerId=setInterval(jQuery.fx.tick,jQuery.fx.interval);}};jQuery.fx.stop=function(){clearInterval(timerId);timerId=null;};jQuery.fx.speeds={slow:600,fast:200,_default:400};jQuery.fx.step={};if(jQuery.expr&&jQuery.expr.filters){jQuery.expr.filters.animated=function(elem){return jQuery.grep(jQuery.timers,function(fn){return elem===fn.elem;}).length;};}
+jQuery.fn.offset=function(options){if(arguments.length){return options===undefined?this:this.each(function(i){jQuery.offset.setOffset(this,options,i);});}
+var docElem,win,elem=this[0],box={top:0,left:0},doc=elem&&elem.ownerDocument;if(!doc){return;}
+docElem=doc.documentElement;if(!jQuery.contains(docElem,elem)){return box;}
+if(typeof elem.getBoundingClientRect!==core_strundefined){box=elem.getBoundingClientRect();}
+win=getWindow(doc);return{top:box.top+win.pageYOffset-docElem.clientTop,left:box.left+win.pageXOffset-docElem.clientLeft};};jQuery.offset={setOffset:function(elem,options,i){var curPosition,curLeft,curCSSTop,curTop,curOffset,curCSSLeft,calculatePosition,position=jQuery.css(elem,"position"),curElem=jQuery(elem),props={};if(position==="static"){elem.style.position="relative";}
+curOffset=curElem.offset();curCSSTop=jQuery.css(elem,"top");curCSSLeft=jQuery.css(elem,"left");calculatePosition=(position==="absolute"||position==="fixed")&&(curCSSTop+curCSSLeft).indexOf("auto")>-1;if(calculatePosition){curPosition=curElem.position();curTop=curPosition.top;curLeft=curPosition.left;}else{curTop=parseFloat(curCSSTop)||0;curLeft=parseFloat(curCSSLeft)||0;}
+if(jQuery.isFunction(options)){options=options.call(elem,i,curOffset);}
+if(options.top!=null){props.top=options.top-curOffset.top+curTop;}
+if(options.left!=null){props.left=options.left-curOffset.left+curLeft;}
+if("using"in options){options.using.call(elem,props);}else{curElem.css(props);}}};jQuery.fn.extend({position:function(){if(!this[0]){return;}
+var offsetParent,offset,elem=this[0],parentOffset={top:0,left:0};if(jQuery.css(elem,"position")==="fixed"){offset=elem.getBoundingClientRect();}else{offsetParent=this.offsetParent();offset=this.offset();if(!jQuery.nodeName(offsetParent[0],"html")){parentOffset=offsetParent.offset();}
+parentOffset.top+=jQuery.css(offsetParent[0],"borderTopWidth",true);parentOffset.left+=jQuery.css(offsetParent[0],"borderLeftWidth",true);}
+return{top:offset.top-parentOffset.top-jQuery.css(elem,"marginTop",true),left:offset.left-parentOffset.left-jQuery.css(elem,"marginLeft",true)};},offsetParent:function(){return this.map(function(){var offsetParent=this.offsetParent||docElem;while(offsetParent&&(!jQuery.nodeName(offsetParent,"html")&&jQuery.css(offsetParent,"position")==="static")){offsetParent=offsetParent.offsetParent;}
+return offsetParent||docElem;});}});jQuery.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(method,prop){var top="pageYOffset"===prop;jQuery.fn[method]=function(val){return jQuery.access(this,function(elem,method,val){var win=getWindow(elem);if(val===undefined){return win?win[prop]:elem[method];}
+if(win){win.scrollTo(!top?val:window.pageXOffset,top?val:window.pageYOffset);}else{elem[method]=val;}},method,val,arguments.length,null);};});function getWindow(elem){return jQuery.isWindow(elem)?elem:elem.nodeType===9&&elem.defaultView;}
+jQuery.each({Height:"height",Width:"width"},function(name,type){jQuery.each({padding:"inner"+name,content:type,"":"outer"+name},function(defaultExtra,funcName){jQuery.fn[funcName]=function(margin,value){var chainable=arguments.length&&(defaultExtra||typeof margin!=="boolean"),extra=defaultExtra||(margin===true||value===true?"margin":"border");return jQuery.access(this,function(elem,type,value){var doc;if(jQuery.isWindow(elem)){return elem.document.documentElement["client"+name];}
+if(elem.nodeType===9){doc=elem.documentElement;return Math.max(elem.body["scroll"+name],doc["scroll"+name],elem.body["offset"+name],doc["offset"+name],doc["client"+name]);}
+return value===undefined?jQuery.css(elem,type,extra):jQuery.style(elem,type,value,extra);},type,chainable?margin:undefined,chainable,null);};});});jQuery.fn.size=function(){return this.length;};jQuery.fn.andSelf=jQuery.fn.addBack;if(typeof module==="object"&&module&&typeof module.exports==="object"){module.exports=jQuery;}else{if(typeof define==="function"&&define.amd){define("jquery",[],function(){return jQuery;});}}
+if(typeof window==="object"&&typeof window.document==="object"){window.jQuery=window.$=jQuery;}})(window);
diff --git a/static/js/manage.js b/static/js/manage.js
new file mode 100644
index 0000000..10898d0
--- /dev/null
+++ b/static/js/manage.js
@@ -0,0 +1,22 @@
+function addtime(e) {
+ e.preventDefault();
+ document.getElementById("seconds").value = this.dataset.secs;
+}
+
+function pvw(e) {
+ prev = document.getElementById("prev_desc");
+ prev.innerHTML = desc.value;
+ prev.style.display = "block";
+ prev.addEventListener("input", function() { desc.value = prev.innerHTML; });
+}
+
+document.addEventListener("DOMContentLoaded", function(e) {
+ var list = document.getElementById("timelist");
+ if (list) {
+ var secs = document.getElementById("timelist").getElementsByTagName("a");
+ for(var i=0;i<secs.length;i++) secs[i].addEventListener("click", addtime);
+ }
+
+ desc = document.getElementById("brd_desc");
+ if (desc) desc.addEventListener("input", pvw);
+}); \ No newline at end of file
diff --git a/static/js/mobile.js b/static/js/mobile.js
new file mode 100644
index 0000000..b4dd8cf
--- /dev/null
+++ b/static/js/mobile.js
@@ -0,0 +1,447 @@
+function sendPost(e) {
+ e.preventDefault();
+ var button = document.getElementById("post");
+ button.disabled = true;
+ var sendpost = new XMLHttpRequest();
+ var postform = document.getElementById("postform");
+ sendpost.open("POST", "/cgi/api/post", true);
+ sendpost.send(new FormData(postform));
+ sendpost.onreadystatechange = function() {
+ if (sendpost.readyState == 4) {
+ button.disabled = false;
+ var response = JSON.parse(sendpost.responseText);
+ if (response.state == "success") { postform.message.value = ""; checkNew(e); }
+ else alert(response.message);
+ }
+ }
+}
+
+function postClick(e) {
+ e.preventDefault();
+ var sel = window.getSelection().toString();
+ if (sel) { sel=sel.replace(/^/gm, ">")+"\n"; sel="\n"+sel; }
+ insert(">>" + parseInt(this.innerHTML, 10) + sel);
+}
+
+function insert(text) {
+ var textarea=document.forms.postform.message;
+ if(textarea) {
+ if(textarea.createTextRange && textarea.caretPos) { // IE
+ var caretPos=textarea.caretPos;
+ caretPos.text=caretPos.text.charAt(caretPos.text.length-1)==" "?text+" ":text;
+ } else if(textarea.setSelectionRange) { // Firefox
+ var start=textarea.selectionStart;
+ var end=textarea.selectionEnd;
+ textarea.value=textarea.value.substr(0,start)+text+textarea.value.substr(end);
+ textarea.setSelectionRange(start+text.length,start+text.length);
+ } else {
+ textarea.value+=text+" ";
+ }
+ textarea.focus();
+ }
+ return false;
+}
+
+function getPassword() {
+ if (weabot.password) return weabot.password;
+ var char="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ var pass="";
+ for (var i=0;i<8;i++) {
+ var rnd = Math.floor(Math.random()*char.length);
+ pass += char.substring(rnd, rnd+1);
+ }
+ console.log(weabot.password);
+ weabot.password = pass;
+ localStorage.setItem("weabot", JSON.stringify(weabot));
+ return(pass);
+}
+
+function saveInputs(e) {
+ var e = e || window.event;
+ var form = e.target || e.srcElement;
+ if(typeof(form.fielda) !== "undefined") weabot.name = form.fielda.value;
+ if(typeof(form.fielda) !== "undefined") weabot.email = form.fieldb.value;
+ localStorage.setItem("weabot", JSON.stringify(weabot));
+}
+
+function setInputs() {
+ with(document.getElementById("postform")) {
+ if(typeof(fielda) !== 'undefined' && !fielda.value && weabot.name) fielda.value = weabot.name;
+ if(typeof(fielda) !== 'undefined' && !fieldb.value && weabot.email) fieldb.value = weabot.email;
+ if(!password.value) password.value = getPassword();
+ addEventListener("submit", saveInputs);
+ }
+}
+
+function showMenu(e) {
+ e.preventDefault();
+ if (document.getElementById("mnu-opened")) closeMenu(e);
+ this.id = "mnu-opened";
+ var brd = postform.board.value;
+ var post = this.parentNode.parentNode;
+ if (document.body.className === "txt") {
+ var id = post.id.substr(1);
+ var num = parseInt(post.getElementsByClassName("num")[0].innerText, 10);
+ } else {
+ var id = post.getElementsByClassName("num")[0].innerText;
+ var num = ((post.className === "first") ? 1 : 0);
+ }
+ var menu = document.createElement("div");
+ menu.id = "mnu-list";
+ menu.style.top = (e.pageY + 5) + "px";
+ menu.style.left = (e.pageX + 5) + "px";
+ document.body.appendChild(menu);
+ menu = document.getElementById("mnu-list");
+ var rep = document.createElement("a");
+ rep.href = "#";
+ rep.innerText = "Denunciar post";
+ rep.addEventListener("click", function(e) {
+ var reason = prompt("Razón de denuncia:");
+ if (reason === "") while(reason === "") reason = prompt("Error: Ingresa una razón.");
+ if (reason) {
+ var rep_req = new XMLHttpRequest();
+ var report = "/cgi/report/" + brd + "/" + id + ((num) ? "/" + num : "") + "?reason=" + reason;
+ rep_req.open("GET", report, true);
+ rep_req.send();
+ rep_req.onreadystatechange = function() {
+ if (rep_req.readyState == 4 && rep_req.status == 200) alert("Denuncia enviada.");
+ }
+ }
+ });
+ menu.appendChild(rep);
+ var del = document.createElement("a");
+ del.href = "#";
+ del.innerText = "Eliminar post";
+ del.addEventListener("click", function(e) {
+ if(confirm("¿Seguro que deseas borrar el mensaje "+((num) ? num : id)+"?")) {
+ var del_req = new XMLHttpRequest();
+ var del_form = "/cgi/api/delete?dir=" + brd + "&id=" + id + "&password=" + postform.password.value;
+ del_req.open("GET", del_form, true);
+ del_req.send();
+ del_req.onreadystatechange = function() {
+ if (del_req.readyState == 4) {
+ var response = JSON.parse(del_req.responseText);
+ if (response.state == "success") {
+ if (num == 1) {
+ alert("Hilo eliminado.");
+ document.location = "/cgi/mobile/" + brd;
+ } else {
+ alert("Mensaje eliminado.");
+ location.reload();
+ }
+ } else if (response.state == "failed") alert(response.message);
+ }
+ }
+ }
+ });
+ menu.appendChild(del);
+ var file = post.getElementsByClassName("thm")[0];
+ if (file) {
+ var dfile = document.createElement("a");
+ dfile.href = "#";
+ dfile.innerText = "Eliminar archivo";
+ dfile.addEventListener("click", function(e) {
+ if(confirm("¿Seguro que deseas borrar el archivo del mensaje "+((num) ? num : id)+"?")) {
+ var fdel_req = new XMLHttpRequest();
+ var fdel_form = "/cgi/api/delete?dir=" + brd + "&id=" + id + "&password=" + postform.password.value + "&imageonly=true";
+ fdel_req.open("GET", fdel_form, true);
+ fdel_req.send();
+ fdel_req.onreadystatechange = function() {
+ if (fdel_req.readyState == 4) {
+ var response = JSON.parse(fdel_req.responseText);
+ if (response.state == "success") {
+ alert("Archivo eliminado.");
+ post.removeChild(file);
+ } else if (response.state == "failed") alert(response.message);
+ }
+ }
+ }
+ });
+ menu.appendChild(dfile);
+ }
+ e.stopPropagation();
+ this.removeEventListener("click", showMenu);
+ document.addEventListener("click", closeMenu);
+}
+
+function closeMenu(e) {
+ var menu = document.getElementById("mnu-list");
+ menu.parentElement.removeChild(menu);
+ document.removeEventListener("click", closeMenu);
+ var btn = document.getElementById("mnu-opened");
+ btn.addEventListener("click", showMenu);
+ btn.removeAttribute("id");
+ e.preventDefault();
+}
+
+function searchSubjects() {
+ var filter = document.getElementById("search").value.toLowerCase();
+ var nodes = document.getElementsByClassName("list")[0].getElementsByTagName("a");
+ for (i = 0; i < nodes.length; i++) {
+ if (nodes[i].innerHTML.toLowerCase().split(/<\/?br[^>]*>\s*/im)[0].includes(filter))
+ nodes[i].removeAttribute("style");
+ else nodes[i].style.display = "none";
+ }
+}
+
+function searchCatalog() {
+ var filter = document.getElementById("catsearch").value.toLowerCase();
+ var nodes = document.getElementsByClassName("cat");
+ for (i = 0; i < nodes.length; i++) {
+ if (nodes[i].innerText.toLowerCase().substring(nodes[i].innerText.indexOf("R)")+2).includes(filter))
+ nodes[i].removeAttribute("style");
+ else nodes[i].style.display = "none";
+ }
+}
+
+var lastTime = 0;
+var refreshInterval;
+var refreshMaxTime = 30;
+var refreshTime;
+var manual = 0;
+var serviceType = 0;
+var thread_length = 0;
+var thread_lastreply = 0;
+var thread_title = "";
+var thread_first_length = 0;
+var http_request = new XMLHttpRequest();
+
+function checkNew(e) {
+ e.preventDefault();
+ manual = 1;
+ loadJSON();
+ if (chk.checked) refreshMaxTime = 25;
+}
+
+function loadJSON() {
+ if (chk.checked) stopCounter("...");
+ if (manual) {
+ document.getElementById("n").style.color = "gray";
+ document.getElementById("n").innerText = "Revisando...";
+ }
+ var data_file;
+ if (serviceType)
+ data_file = "/cgi/api/thread?dir=" + postform.board.value + "&id=" + postform.parent.value + "&offset=" + thread_length + "&time=" + lastTime;
+ else return false;
+ http_request.open("GET", data_file, true);
+ http_request.send();
+}
+
+function updateThread(posts, total_replies, serverTime) {
+ thread_div = document.getElementById("thread");
+ last_elem = document.getElementById("n");
+
+ for (var i = 0; i < posts.length; i++) {
+ post = posts[i];
+ brd = postform.board.value;
+ var div = document.createElement('div');
+ div.className = "pst";
+ div.id = "p" + post.id;
+ if (post.IS_DELETED == 0) {
+ s_name = post.name;
+ if (post.tripcode) s_name += ' ' + post.tripcode;
+ s_time = post.timestamp_formatted.replace(/\(.{1,3}\)/g, " ");
+ if (post.file)
+ s_img = '<a href="/' + brd + '/src/' + post.file + '" target="_blank" class="thm"><img src="/' + brd + '/mobile/' + post.thumb + '" /><br />' + Math.round(post.file_size/1024) + 'KB ' + post.file.substring(post.file.lastIndexOf(".")+1, post.file.length).toUpperCase() + '</a>';
+ else s_img = '';
+ }
+ if (serviceType == 1) {
+ var pad = "0000" + (thread_length + i + 1);
+ pad = pad.substr(pad.length-4);
+ if (post.IS_DELETED == 0)
+ div.innerHTML = '<h3><a href="#" class="num">' + pad + '</a> ' + s_name + '</h3>' + s_img + '<div class="msg">' + post.message + '</div><h4>' + s_time + '<a href="#" class="mnu">|||</a></h4>';
+ else if (post.IS_DELETED == 1)
+ div.innerHTML = '<h3 class="del"><a href="#" class="num">' + pad + '</a> : Eliminado por el usuario.</h3>';
+ else
+ div.innerHTML = '<h3 class="del"><a href="#" class="num">' + pad + '</a> : Eliminado por miembro del staff.</h3>';
+ } else {
+ if (post.IS_DELETED == 0) {
+ div.innerHTML = '<h3>' + s_name + ' ' + s_time + ' <a href="#" class="num" name="' + post.id + '">' + post.id + '</a><a href="#" class="mnu">|||</a></h3>' + s_img + '<div class="msg">' + post.message + '</div>';
+ } else if (post.IS_DELETED == 1) { div.innerHTML = '<h3 class="del"><a name="' + post.id + '"></a>No.' + post.id + ' eliminado por el usuario.</h3>'; }
+ else { div.innerHTML = '<h3 class="del"><a name="' + post.id + '"></a>No.' + post.id + ' eliminado por miembro del staff.</h3>'; }
+ }
+
+ div.getElementsByClassName("mnu")[0].addEventListener("click", showMenu);
+ div.getElementsByClassName("num")[0].addEventListener("click", postClick);
+ thread_div.insertBefore(div, last_elem);
+ document.getElementsByTagName("h1")[0].getElementsByTagName("span")[0].innerText = "(" + (thread_length + i + 1) + ")"
+ }
+
+ if (posts.length > 0) {
+ if (!manual) refreshMaxTime = 10;
+ if (!document.hasFocus())
+ if (posts.length > 1) notif(thread_title, posts.length + ' nuevos mensajes');
+ else notif(thread_title, 'Un nuevo mensaje');
+ } else { if (refreshMaxTime <= 60) refreshMaxTime += 5; }
+
+ thread_length = parseInt(total_replies) + 1;
+ new_unread = thread_length - thread_first_length;
+
+ if (new_unread) document.title = '(' + new_unread + ') ' + thread_title;
+ else document.title = thread_title;
+}
+
+function notif(title, msg) {
+ var n = new Notification(title, { body: msg });
+ setTimeout(n.close.bind(n), 10000);
+}
+
+function counter() {
+ if (refreshTime < 1) loadJSON();
+ else {
+ refreshTime--;
+ document.getElementById("counter").innerHTML = (refreshTime + 1);
+ }
+}
+
+function detectService() {
+ if (document.getElementById("thread")) {
+ thread_title = document.getElementsByTagName("h1")[0].innerHTML.split(" \<span\>")[0] + " - " + document.title;
+ thread_length = parseInt(document.getElementsByTagName("h1")[0].getElementsByTagName("span")[0].innerText.slice(1, -1), 10);
+ thread_first_length = thread_length;
+ if (document.body.className === "txt") {
+ serviceType = 1;
+ replylist = document.getElementsByClassName("pst");
+ thread_lastreply = parseInt(replylist[replylist.length - 1].getElementsByClassName("num")[0].innerText);
+ if (thread_length == thread_lastreply) {
+ serviceType = 1;
+ document.getElementById("n2").setAttribute("style", "border-top:1px solid #c6c7c8;border-left:1px solid #c6c7c8;display:inline-block;text-align:center;width:50%;");
+ return true;
+ } else return false;
+ } else if (document.body.className === "img") {
+ serviceType = 2;
+ document.getElementById("n").innerText = "Ver nuevos posts";
+ document.getElementById("n2").setAttribute("style", "border-top:1px solid #333;border-left:1px solid #333;display:inline-block;text-align:center;width:50%;");
+ replylist = document.getElementsByClassName("first");
+ replylist += document.getElementsByClassName("pst");
+ return true;
+ }
+ } else return false;
+}
+
+function startCounter() {
+ refreshTime = refreshMaxTime;
+ counter();
+ refreshInterval = setInterval(counter, 1000);
+}
+
+function stopCounter(str) {
+ clearInterval(refreshInterval);
+ document.getElementById("counter").innerHTML = str;
+}
+
+function autoRefresh(e) {
+ chk_snd = document.getElementById("autosound");
+ if (document.getElementById("autorefresh").checked) {
+ if (chk_snd) chk_snd.disabled = false;
+ Notification.requestPermission();
+ lastTime = Math.floor(Date.now() / 1000);
+ refreshTime = refreshMaxTime;
+ startCounter();
+ } else {
+ if (chk_snd) document.getElementById("autosound").disabled = true;
+ stopCounter("OFF");
+ }
+}
+
+http_request.onreadystatechange = function() {
+ if (http_request.readyState == 4) {
+ var jsonObj = JSON.parse(http_request.responseText);
+ if (jsonObj.state == "success") {
+ updateThread(jsonObj.posts, jsonObj.total_replies, jsonObj.time);
+ lastTime = jsonObj.time;
+ if (chk.checked) startCounter();
+ }
+ if (manual) {
+ document.getElementById("n").style.color = "inherit";
+ document.getElementById("n").innerText = "Ver nuevos posts";
+ }
+ manual = 0;
+ }
+}
+
+function sortList(type) {
+ for(var i=0;i<srts.length;i++) srts[i].removeAttribute("class");
+ srts[type].className = "sel";
+ var cont = document.getElementById("to_sort");
+ var elem = cont.getElementsByTagName("a");
+ var arr = Array.prototype.slice.call(elem);
+ if (type==0) arr.sort(function (a,b) { return (a.dataset.num-b.dataset.num) });
+ else if (type==1) arr.sort(function (a,b) { return (b.dataset.id-a.dataset.id) });
+ else if (type==2) arr.sort(function (a,b) { return (a.dataset.id-b.dataset.id) });
+ else if (type==3) arr.sort(function (a,b) { return (b.dataset.res-a.dataset.res) });
+ else if (type==4) arr.sort(function (a,b) { return (a.dataset.res-b.dataset.res) });
+ for (var j=0;j<arr.length;j++) cont.appendChild(arr[j]);
+}
+
+document.addEventListener("DOMContentLoaded", function(e) {
+ if (localStorage.hasOwnProperty("weabot")) weabot = JSON.parse(localStorage.getItem("weabot"));
+ else weabot = {"name":null,"email":null,"password":null};
+
+ var ids = document.getElementsByClassName("num");
+ for(var i=0;i<ids.length;i++) ids[i].addEventListener("click", postClick);
+
+ var form = document.getElementById("postform");
+ if (form) {
+ setInputs();
+ if (document.getElementById("post").value == "Responder")
+ form.addEventListener("submit", sendPost);
+ }
+
+ if (document.getElementById("search")) document.getElementById("search").addEventListener("keyup", searchSubjects);
+ if (document.getElementById("catsearch")) document.getElementById("catsearch").addEventListener("keyup", searchCatalog);
+ if (document.getElementById("to_sort")) {
+ srts = document.getElementsByClassName("ord")[0].getElementsByTagName("a");
+ for(var i=0;i<srts.length;i++) srts[i].addEventListener("click", function(e) { e.preventDefault(); sortList(this.dataset.sort); });
+ }
+
+ if (document.getElementById("thread")) {
+ var mnu = document.createElement('a');
+ mnu.href = "#";
+ mnu.className = "mnu";
+ mnu.innerHTML = "|||";
+ if (document.body.className === "txt") var ft = document.getElementsByTagName("h4");
+ else if (document.body.className === "img") var ft = document.getElementsByTagName("h3");
+ for(var i=0;i<ft.length;i++) {
+ if (!ft[i].classList.contains("del")) {
+ var cln = mnu.cloneNode(true);
+ cln.addEventListener("click", showMenu);
+ ft[i].appendChild(cln);
+ }
+ }
+ }
+
+ if (!detectService()) return;
+ document.title = thread_title;
+ document.getElementById("n").style.display = "inline-block";
+ document.getElementById("n").style.width = "50%";
+ document.getElementById("n").addEventListener("click", checkNew);
+ var lbl = document.createElement("label");
+ lbl.id = "auto";
+ lbl.style.display = "block";
+ lbl.style.padding = "6px 0";
+ var btn = document.createElement("input");
+ btn.id = "autorefresh";
+ btn.setAttribute("type", "checkbox");
+ btn.addEventListener("click", autoRefresh);
+ var cnt = document.createElement("span");
+ cnt.id = "counter";
+ cnt.textContent = "OFF";
+ document.getElementById("n2").appendChild(lbl);
+ document.getElementById("auto").appendChild(btn);
+ document.getElementById("auto").appendChild(document.createTextNode(" Auto "));
+ document.getElementById("auto").appendChild(cnt);
+
+ chk = document.getElementById("autorefresh");
+ if (localStorage.getItem("autorefreshmobile")) {
+ chk.checked = true;
+ autoRefresh();
+ }
+});
+
+window.addEventListener("unload", function() {
+ chk = document.getElementById("autorefresh");
+ if (!serviceType) return;
+ if (chk.checked) localStorage.setItem("autorefreshmobile", true);
+ else localStorage.removeItem("autorefreshmobile");
+}); \ No newline at end of file
diff --git a/static/js/paintbbs/PaintBBS-1.1.11.css b/static/js/paintbbs/PaintBBS-1.1.11.css
new file mode 100644
index 0000000..776f63d
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.1.11.css
@@ -0,0 +1,535 @@
+.NEO {
+ margin:0;
+ line-height:18px;
+
+ user-select: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+
+ touch-callout: none;
+ -webkit-touch-callout: none;
+}
+
+.NEO *:active,
+.NEO *:hover {
+ cursor: default;
+}
+
+.NEO #container{
+ width: 100%;
+ height: 100%;
+ position: relative;
+ border: 1px dotted transparent;
+}
+
+.NEO #center{
+ display: table;
+ position: relative;
+ height: 100%;
+ margin: auto;
+}
+
+.NEO #toolsWrapper{
+ width: 52px;
+ display: table;
+ position:absolute;
+ top: 0;
+ right: -3px;
+}
+
+.NEO #tools{
+ width: 52px;
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+}
+
+.NEO #painterContainer{
+ display:table-cell;
+ vertical-align: middle;
+ position: relative;
+}
+
+.NEO #painterWrapper{
+ padding: 0 55px 0 0;
+ position: relative;
+
+ float:right; /* ãªãœã‹Chrome55ã§ãšã‚Œã‚‹ã®ã§å¯¾ç­– */
+}
+
+.NEO #upper {
+ height:30px;
+ padding-right: 20px;
+ text-align:right;
+}
+
+.NEO #lower {
+ height:30px;
+}
+
+.NEO #painter {
+ position: relative;
+ padding: 20px 20px 20px 20px;
+}
+
+.NEO #canvas {
+ position: relative;
+ width: 300px;
+ height: 300px;
+ background-color: white;
+}
+
+.NEO #headerButtons {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+}
+
+.NEO #footerButtons {
+ position: absolute;
+ bottom: 5px;
+ left: 5px;
+}
+
+
+/*
+-----------------------
+ Modal Window
+-----------------------
+*/
+
+.NEO #pageView{
+ background-color: white;
+}
+
+.NEO #windowView{
+ z-index: 9999;
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ background-color: white;
+}
+
+/*
+-----------------------
+ Controls
+-----------------------
+*/
+
+.NEO #zoomMinus {
+ padding: 0;
+ margin: 0;
+ width:16px;
+ height:16px;
+ margin-left:1px;
+}
+
+.NEO #zoomPlus {
+ padding: 0;
+ margin: 0;
+ width:16px;
+ height:16px;
+}
+
+.NEO #zoomMinusWrapper {
+ position: absolute;
+ right: -20px;
+ bottom: -21px;
+ width: 19px;
+ height: 19px;
+ text-align:center;
+}
+
+.NEO #zoomPlusWrapper {
+ position: absolute;
+ left: -21px;
+ bottom: -21px;
+ width: 19px;
+ height: 19px;
+ text-overflow: hidden;
+ text-align:center;
+}
+
+.NEO #scrollH {
+ position: absolute;
+ left: 1px;
+ bottom: -20px;
+ width: calc(100% - 2px);
+ height: 18px;
+}
+
+.NEO #scrollV {
+ position: absolute;
+ right: -20px;
+ top: 1px;
+ width: 18px;
+ height: calc(100% - 2px);
+}
+
+.NEO #scrollH div {
+ position: absolute;
+ width: 50px;
+ height: 16px;
+}
+
+.NEO #scrollV div {
+ position: absolute;
+ width: 16px;
+ height: 50px;
+}
+
+.NEO #scrollH div:hover {}
+.NEO #scrollV div:hover {}
+
+.NEO #neoWarning {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ color: red;
+ pointer-events: none;
+ text-align: left;
+ transition: all 2s;
+}
+
+/*
+-----------------------
+ Widgets
+-----------------------
+*/
+
+.NEO .buttonOff {
+ display: inline-block;
+ border: 1px solid white;
+ height: 19px;
+ padding: 3px;
+ height: 16px;
+ font-size: 15px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ margin-right: 4px;
+
+ border-left: 1px solid rgba(0, 0, 0, 0);
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-right: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin: 1px;
+
+}
+
+.NEO .buttonOff:hover {}
+
+.NEO .buttonOff:active,
+.NEO .buttonOn {
+ display: inline-block;
+ height: 19px;
+ padding: 3px;
+ height: 16px;
+ font-size: 15px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ margin-right: 4px;
+
+ border-right: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin: 1px;
+}
+
+.NEO .toolTipOff,
+.NEO .toolTipFixed {
+ position:relative;
+ padding: 0;
+ margin: 0;
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ width: 46px;
+ height: 18px;
+ border-top: 1px solid #ffffff;
+ border-left: 1px solid #ffffff;
+ border-right: 1px solid #9397b2;
+ border-bottom: 1px solid #9397b2;
+}
+
+.NEO .toolTipOn {
+ position:relative;
+ padding: 0;
+ margin: 0;
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ width: 46px;
+ height: 18px;
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-left: 1px solid rgba(0, 0, 0, 0);
+ border-right: 1px solid #ffffff;
+ border-bottom: 1px solid #ffffff;
+}
+
+.NEO .toolTipOff canvas,
+.NEO .toolTipOn canvas,
+.NEO .toolTipFixed canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+.NEO .toolTipOff .label,
+.NEO .toolTipOn .label,
+.NEO .toolTipFixed .label {
+ position: absolute;
+ bottom: -4px;
+ left: 1px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: -1px;
+}
+
+.NEO .colorTips {
+ position:relative;
+ width: 48px;
+ height: 144px;
+ padding: 0;
+ margin: 0;
+ margin-top: 4px;
+ margin-left: 0px;
+}
+
+.NEO .colorTipOff {
+ position: absolute;
+ overflow: hidden;
+ width: 22px;
+ height: 18px;
+ margin: -1px 4px 0px 0px;
+ padding: 0;
+}
+
+.NEO .colorTipOff img {
+ left: 0;
+ opacity: 0.5;
+ position: absolute;
+ pointer-events:none;
+}
+
+.NEO .colorTipOn {
+ position: absolute;
+ overflow: hidden;
+ width: 22px;
+ height: 18px;
+ margin: -1px 4px 0px 0px;
+ padding: 0;
+}
+
+.NEO .colorTipOn img {
+ left: -22px;
+ opacity: 0.5;
+ position: absolute;
+ pointer-events:none;
+}
+
+.NEO .colorSlider {
+ width: 48px;
+ height:13px;
+ position: relative;
+ margin-top: 3px;
+}
+
+.NEO .colorSlider .label {
+ pointer-events: none;
+ position: absolute;
+ left: 2px;
+ bottom: -3px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: middle;
+}
+
+.NEO .colorSlider .slider {
+ position: absolute;
+ height: 100%;
+ left: 0px;
+ width: 50%;
+ background-color: #fa9696;
+ box-shadow: -1px 0 0 0px rgba(0, 0, 0, 0.3) inset;
+}
+
+.NEO .colorSlider .hit {
+ position:absolute;
+ width: 60px;
+ height: 13px;
+ left: -6px;
+ background-color: white;
+ opacity: 0.01;
+}
+
+.NEO .sizeSlider {
+ width: 48px;
+ height:33px;
+ position: relative;
+ margin-top: 4px;
+}
+
+.NEO .sizeSlider .label {
+ pointer-events: none;
+ position: absolute;
+ left: 2px;
+ bottom: -3px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: middle;
+}
+
+.NEO .sizeSlider .slider {
+ position: absolute;
+ width: 100%;
+ top: 0px;
+ height: 33%;
+ background-color: #82f238;
+ box-shadow: 0 -1px 0 0px rgba(0, 0, 0, 0.3) inset;
+}
+
+.NEO .sizeSlider .hit {
+ position:absolute;
+ width: 48px;
+ height: 41px;
+ top: -4px;
+ background-color: white;
+ opacity: 0.01;
+}
+
+.NEO .reserveControl {
+ width: 48px;
+ height: 13px;
+ position: relative;
+}
+
+.NEO .reserveControl .reserve {
+ position: absolute;
+ width: 11px;
+ height: 8px;
+ background-color: white;
+}
+
+.NEO .layerControl {
+ width: 48px;
+ height: 20px;
+ position: relative;
+ margin-top: 6px;
+}
+
+.NEO .layerControl .bg {
+ position: absolute;
+ width: 44px;
+ height: 9px;
+ margin: 0;
+
+ top: 0px;
+ left: 2px;
+}
+
+.NEO .layerControl .line1 {
+ position: absolute;
+ width: 50px;
+ height:10px;
+ margin: 0;
+ padding: 0;
+
+ top: 0px;
+ left: -1px;
+ background-image: linear-gradient(to top right, transparent, transparent 47%, red 47%, red 53%, transparent 53%, transparent);
+}
+
+.NEO .layerControl .line0 {
+ position: absolute;
+ width: 50px;
+ height: 10px;
+ margin: 0;
+ padding: 0;
+
+ top: 10px;
+ left: -1px;
+ background-image: linear-gradient(to top right, transparent, transparent 47%, red 47%, red 53%, transparent 53%, transparent);
+}
+
+.NEO .layerControl .label1 {
+ position: absolute;
+ left: 2px;
+ Top: -4px;
+ font-size:11px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: baseline;
+}
+
+.NEO .layerControl .label0 {
+ position: absolute;
+ left: 2px;
+ Top: 6px;
+ font-size:11px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: baseline;
+}
+
+/*
+-----------------------
+ InputText
+-----------------------
+*/
+
+.NEO .inputText {
+ z-index: 100000;
+ position: absolute;
+
+ text-align: left;
+ white-space: nowrap;
+ color: #0000ff;
+
+ font-family: 'Arial';
+ padding: 1px 5px 1px 5px;
+ font-size: 32px;
+
+ line-height: 40px;
+ height: 40px;
+ min-width: 10em;
+
+ bottom: 0px;
+ left: 250px;
+
+ border: 1px solid #aaa;
+ background-color: white;
+}
+
+*[contenteditable] {
+ user-select: auto !important;
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto !important;
+}
+
+#testtext {
+ user-select: auto !important;
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto;
+}
+
+[contenteditable="true"]:focus {
+ outline: 1px solid #b1d6fd;
+ border: 1px solid #b1d6fd;
+}
diff --git a/static/js/paintbbs/PaintBBS-1.1.11.js b/static/js/paintbbs/PaintBBS-1.1.11.js
new file mode 100644
index 0000000..8ca50e7
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.1.11.js
@@ -0,0 +1,5686 @@
+'use strict';
+
+document.addEventListener("DOMContentLoaded", function() {
+ Neo.init();
+
+ if (!navigator.userAgent.match("Electron")) {
+ Neo.start();
+ }
+});
+
+
+var Neo = function() {};
+
+Neo.version = "1.1.11";
+Neo.painter;
+Neo.fullScreen = false;
+Neo.uploaded = false;
+
+Neo.config = {
+ width: 300,
+ height: 300,
+
+ color_bk: "#ccccff",
+ color_bk2: "#bbbbff",
+ color_tool_icon: "#e8dfae",
+ color_icon: "#ccccff",
+ color_iconselect: "#ffaaaa",
+ color_text: "#666699",
+ color_bar: "#6f6fae",
+
+ tool_color_button: "#e8dfae",
+ tool_color_button2: "#f8daaa",
+ tool_color_text: "#773333",
+ tool_color_bar: "#ddddff",
+ tool_color_frame: "#000000",
+
+ colors: [
+ "#000000", "#FFFFFF",
+ "#B47575", "#888888",
+ "#FA9696", "#C096C0",
+ "#FFB6FF", "#8080FF",
+ "#25C7C9", "#E7E58D",
+ "#E7962D", "#99CB7B",
+ "#FCECE2", "#F9DDCF"
+ ]
+};
+
+Neo.reservePen = {};
+Neo.reserveEraser = {};
+
+Neo.SLIDERTYPE_RED = 0;
+Neo.SLIDERTYPE_GREEN = 1;
+Neo.SLIDERTYPE_BLUE = 2;
+Neo.SLIDERTYPE_ALPHA = 3;
+Neo.SLIDERTYPE_SIZE = 4;
+
+document.neo = Neo;
+
+Neo.init = function() {
+ var applets = document.getElementsByTagName('applet');
+ if (applets.length == 0) {
+ applets = document.getElementsByTagName('applet-dummy');
+ }
+
+ for (var i = 0; i < applets.length; i++) {
+ var applet = applets[i];
+ var name = applet.attributes.name.value;
+ if (name == "paintbbs") {
+ Neo.applet = applet;
+ Neo.createContainer(applet);
+ Neo.initConfig(applet);
+ Neo.init2();
+ }
+ }
+};
+
+Neo.init2 = function() {
+ var pageview = document.getElementById("pageView");
+ pageview.style.width = Neo.config.applet_width + "px";
+ pageview.style.height = Neo.config.applet_height + "px";
+
+ Neo.canvas = document.getElementById("canvas");
+ Neo.container = document.getElementById("container");
+ Neo.toolsWrapper = document.getElementById("toolsWrapper");
+
+ Neo.painter = new Neo.Painter();
+ Neo.painter.build(Neo.canvas, Neo.config.width, Neo.config.height);
+
+ Neo.container.oncontextmenu = function() {return false;};
+
+ // 続ãã‹ã‚‰æã
+ if (Neo.config.image_canvas) {
+ Neo.painter.loadImage(Neo.config.image_canvas);
+ }
+
+ // æãã‹ã‘ã®ç”»åƒãŒè¦‹ã¤ã‹ã£ãŸã¨ã
+ if (sessionStorage.getItem('timestamp')) {
+ setTimeout(function () {
+ if (confirm("¿Cargar datos guardados?")) {
+ Neo.painter.loadSession();
+ }
+ }, 1);
+ }
+
+ window.addEventListener("beforeunload", function(e) {
+ if (!Neo.uploaded) {
+ Neo.painter.saveSession();
+ } else {
+ Neo.painter.clearSession();
+ }
+ }, false);
+}
+
+Neo.initConfig = function(applet) {
+ if (applet) {
+ var name = applet.attributes.name.value || "neo";
+ var appletWidth = applet.attributes.width;
+ var appletHeight = applet.attributes.height;
+ if (appletWidth) Neo.config.applet_width = parseInt(appletWidth.value);
+ if (appletHeight) Neo.config.applet_height = parseInt(appletHeight.value);
+
+ var params = applet.getElementsByTagName('param');
+ for (var i = 0; i < params.length; i++) {
+ var p = params[i];
+ Neo.config[p.name] = Neo.fixConfig(p.value);
+
+ if (p.name == "image_width") Neo.config.width = parseInt(p.value);
+ if (p.name == "image_height") Neo.config.height = parseInt(p.value);
+ }
+
+ var e = document.getElementById("container");
+ Neo.config.inherit_color = Neo.getInheritColor(e);
+ if (!Neo.config.color_frame) Neo.config.color_frame = Neo.config.color_text;
+ }
+
+ Neo.config.reserves = [
+ { size:1,
+ color:"#000000", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_PEN,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ { size:5,
+ color:"#FFFFFF", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_ERASER,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ { size:10,
+ color:"#FFFFFF", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_ERASER,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ ];
+
+ Neo.reservePen = Neo.clone(Neo.config.reserves[0]);
+ Neo.reserveEraser = Neo.clone(Neo.config.reserves[1]);
+};
+
+Neo.fixConfig = function(value) {
+ // javaã§ã¯"#12345"を色ã¨ã—ã¦è§£é‡ˆã™ã‚‹ãŒjavascriptã§ã¯"#012345"ã«å¤‰æ›ã—ãªã„ã¨ã ã‚
+ if (value.match(/^#[0-9a-fA-F]{5}$/)) {
+ value = "#0" + value.slice(1);
+ }
+ return value;
+};
+
+Neo.initSkin = function() {
+ var sheet = document.styleSheets[0];
+ if (!sheet) {
+ var style = document.createElement("style");
+ document.head.appendChild(style); // must append before you can access sheet property
+ sheet = style.sheet;
+ }
+
+ Neo.styleSheet = sheet;
+
+ var lightBorder = Neo.multColor(Neo.config.color_icon, 1.3);
+ var darkBorder = Neo.multColor(Neo.config.color_icon, 0.7);
+ var lightBar = Neo.multColor(Neo.config.color_bar, 1.3);
+ var darkBar = Neo.multColor(Neo.config.color_bar, 0.7);
+ var bgImage = Neo.backgroundImage();
+
+ Neo.addRule(".NEO #container", "background-image", "url(" + bgImage + ")");
+ Neo.addRule(".NEO .colorSlider .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .sizeSlider .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .label1", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .label0", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .toolTipOn .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .toolTipOff .label", "color", Neo.config.tool_color_text);
+
+ Neo.addRule(".NEO #toolSet", "background-color", Neo.config.color_bk);
+ Neo.addRule(".NEO #tools", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .bg", "border-bottom", "1px solid " + Neo.config.tool_color_text);
+
+ Neo.addRule(".NEO .buttonOn", "color", Neo.config.color_text);
+ Neo.addRule(".NEO .buttonOff", "color", Neo.config.color_text);
+
+ Neo.addRule(".NEO .buttonOff", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "border-top", "1px solid ", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "border-left", "1px solid ", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "box-shadow", "0 0 0 1px " + Neo.config.color_icon + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO .buttonOff:hover", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff:hover", "border-top", "1px solid " + lightBorder);
+ Neo.addRule(".NEO .buttonOff:hover", "border-left", "1px solid " + lightBorder);
+ Neo.addRule(".NEO .buttonOff:hover", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "background-color", darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "border-top", "1px solid " + darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "border-left", "1px solid " + darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO #canvas", "border", "1px solid " + Neo.config.color_frame);
+ Neo.addRule(".NEO #scrollH, .NEO #scrollV", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO #scrollH, .NEO #scrollV", "box-shadow", "0 0 0 1px white" + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "background-color", Neo.config.color_bar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "box-shadow", "0 0 0 1px " + Neo.config.color_icon);
+ Neo.addRule(".NEO #scrollH div:hover, .NEO #scrollV div:hover", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect);
+
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-top", "1px solid " + lightBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-left", "1px solid " + lightBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-right", "1px solid " + darkBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-bottom", "1px solid " + darkBar);
+
+ Neo.addRule(".NEO .toolTipOn", "background-color", Neo.multColor(Neo.config.tool_color_button, 0.7));
+ Neo.addRule(".NEO .toolTipOff", "background-color", Neo.config.tool_color_button);
+ Neo.addRule(".NEO .toolTipFixed", "background-color", Neo.config.tool_color_button2);
+
+ Neo.addRule(".NEO .colorSlider, .NEO .sizeSlider", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .reserveControl", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .reserveControl", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .layerControl", "background-color", Neo.config.tool_color_bar);
+
+ Neo.addRule(".NEO .colorTipOn, .NEO .colorTipOff", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .toolTipOn, .NEO .toolTipOff", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .toolTipFixed", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .colorSlider, .NEO .sizeSlider", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .reserveControl", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .layerControl", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .reserveControl .reserve", "border", "1px solid " + Neo.config.tool_color_frame);
+};
+
+Neo.addRule = function(selector, styleName, value, sheet) {
+ if (!sheet) sheet = Neo.styleSheet;
+ if (sheet.addRule) {
+ sheet.addRule(selector, styleName + ":" + value, sheet.rules.length);
+
+ } else if (sheet.insertRule) {
+ var rule = selector + "{" + styleName + ":" + value + "}";
+ var index = sheet.cssRules.length;
+ sheet.insertRule(rule, index);
+ }
+};
+
+Neo.getInheritColor = function(e) {
+ var result = "#000000";
+ while (e && e.style) {
+ if (e.style.color != "") {
+ result = e.style.color;
+ break;
+ }
+ if (e.attributes["text"]) {
+ result = e.attributes["text"].value;
+ break;
+ }
+ e = e.parentNode;
+ }
+ return result;
+};
+
+Neo.backgroundImage = function() {
+ var c1 = Neo.painter.getColor(Neo.config.color_bk) | 0xff000000;
+ var c2 = Neo.painter.getColor(Neo.config.color_bk2) | 0xff000000;
+ var bgCanvas = document.createElement("canvas");
+ bgCanvas.width = 16;
+ bgCanvas.height = 16;
+ var ctx = bgCanvas.getContext("2d");
+ var imageData = ctx.getImageData(0, 0, 16, 16);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var index = 0;
+ for (var y = 0; y < 16; y++) {
+ for (var x = 0; x < 16; x++) {
+ buf32[index++] = (x == 14 || y == 14) ? c2 : c1;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+ return bgCanvas.toDataURL('image/png');
+};
+
+Neo.multColor = function(c, scale) {
+ var r = Math.round(parseInt(c.substr(1, 2), 16) * scale);
+ var g = Math.round(parseInt(c.substr(3, 2), 16) * scale);
+ var b = Math.round(parseInt(c.substr(5, 2), 16) * scale);
+ r = ("0" + Math.min(Math.max(r, 0), 255).toString(16)).substr(-2);
+ g = ("0" + Math.min(Math.max(g, 0), 255).toString(16)).substr(-2);
+ b = ("0" + Math.min(Math.max(b, 0), 255).toString(16)).substr(-2);
+ return '#' + r + g + b;
+};
+
+Neo.initComponents = function() {
+ document.getElementById("copyright").innerHTML += "v" + Neo.version;
+
+ //アプレットã®borderã®å‹•ä½œã‚’エミュレート
+ if (navigator.userAgent.search("FireFox") > -1) {
+ var container = document.getElementById("container");
+ container.addEventListener("mousedown", function(e) {
+ container.style.borderColor = Neo.config.inherit_color;
+ e.stopPropagation();
+ }, false);
+ document.addEventListener("mousedown", function(e) {
+ container.style.borderColor = 'transparent';
+ }, false);
+ }
+
+ // 投稿ã«å¤±æ•—ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ã¨ãã¯è­¦å‘Šã‚’表示ã™ã‚‹
+ Neo.showWarning();
+
+ if (Neo.styleSheet) {
+ Neo.addRule("*", "user-select", "none");
+ Neo.addRule("*", "-webkit-user-select", "none");
+ Neo.addRule("*", "-ms-user-select", "none");
+ }
+}
+
+Neo.initButtons = function() {
+ new Neo.Button().init("undo").onmouseup = function() {
+ new Neo.UndoCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("redo").onmouseup = function () {
+ new Neo.RedoCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("window").onmouseup = function() {
+ new Neo.WindowCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("submit").onmouseup = function() {
+ new Neo.SubmitCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("copyright").onmouseup = function() {
+ new Neo.CopyrightCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("zoomPlus").onmouseup = function() {
+ new Neo.ZoomPlusCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("zoomMinus").onmouseup = function() {
+ new Neo.ZoomMinusCommand(Neo.painter).execute();
+ };
+
+ Neo.fillButton = new Neo.Button().init("fill", {type:'fill'});
+
+ // toolTip
+ Neo.penTip = new Neo.PenTip().init("pen");
+ Neo.pen2Tip = new Neo.Pen2Tip().init("pen2");
+ Neo.effectTip = new Neo.EffectTip().init("effect");
+ Neo.effect2Tip = new Neo.Effect2Tip().init("effect2");
+ Neo.eraserTip = new Neo.EraserTip().init("eraser");
+ Neo.drawTip = new Neo.DrawTip().init("draw");
+ Neo.maskTip = new Neo.MaskTip().init("mask");
+
+ Neo.toolButtons = [Neo.fillButton,
+ Neo.penTip,
+ Neo.pen2Tip,
+ Neo.effectTip,
+ Neo.effect2Tip,
+ Neo.drawTip,
+ Neo.eraserTip];
+
+ // colorTip
+ for (var i = 1; i <= 14; i++) {
+ new Neo.ColorTip().init("color" + i, {index:i});
+ };
+
+ // colorSlider
+ Neo.sliders[Neo.SLIDERTYPE_RED] = new Neo.ColorSlider().init(
+ "sliderRed", {type:Neo.SLIDERTYPE_RED});
+ Neo.sliders[Neo.SLIDERTYPE_GREEN] = new Neo.ColorSlider().init(
+ "sliderGreen", {type:Neo.SLIDERTYPE_GREEN});
+ Neo.sliders[Neo.SLIDERTYPE_BLUE] = new Neo.ColorSlider().init(
+ "sliderBlue", {type:Neo.SLIDERTYPE_BLUE});
+ Neo.sliders[Neo.SLIDERTYPE_ALPHA] = new Neo.ColorSlider().init(
+ "sliderAlpha", {type:Neo.SLIDERTYPE_ALPHA});
+
+ // sizeSlider
+ Neo.sliders[Neo.SLIDERTYPE_SIZE] = new Neo.SizeSlider().init(
+ "sliderSize", {type:Neo.SLIDERTYPE_SIZE});
+
+ // reserveControl
+ for (var i = 1; i <= 3; i++) {
+ new Neo.ReserveControl().init("reserve" + i, {index:i});
+ };
+
+ new Neo.LayerControl().init("layerControl");
+ new Neo.ScrollBarButton().init("scrollH");
+ new Neo.ScrollBarButton().init("scrollV");
+};
+
+Neo.start = function(isApp) {
+ if (!Neo.painter) return;
+
+ Neo.initSkin();
+ Neo.initComponents();
+ Neo.initButtons();
+
+ Neo.isApp = isApp;
+ if (Neo.applet) {
+ var name = Neo.applet.attributes.name.value || "paintbbs";
+ Neo.applet.outerHTML = "";
+ document[name] = Neo;
+
+ Neo.resizeCanvas();
+ Neo.container.style.visibility = "visible";
+
+ if (Neo.isApp) {
+ var ipc = require('electron').ipcRenderer;
+ ipc.sendToHost('neo-status', 'ok');
+ }
+ }
+};
+
+Neo.showWarning = function() {
+ var futaba = location.hostname.match(/2chan.net/i);
+ var samplebbs = location.hostname.match(/neo.websozai.jp/i);
+
+ var chrome = navigator.userAgent.match(/Chrome\/(\d+)/i);
+ if (chrome && chrome.length > 1) chrome = chrome[1];
+
+ var edge = navigator.userAgent.match(/Edge\/(\d+)/i);
+ if (edge && edge.length > 1) edge = edge[1];
+
+ var ms = false;
+ if (/MSIE 10/i.test(navigator.userAgent)) {
+ ms = true; // This is internet explorer 10
+ }
+ if (/MSIE 9/i.test(navigator.userAgent) ||
+ /rv:11.0/i.test(navigator.userAgent)) {
+ ms = true; // This is internet explorer 9 or 11
+ }
+
+ var str = "";
+ if (futaba || samplebbs) {
+ if (ms || (edge && edge < 15)) {
+ str = "ã“ã®ãƒ–ラウザã§ã¯<br>投稿ã«å¤±æ•—ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™<br>";
+ }
+ }
+
+ // ã‚‚ã—<PARAM NAME="neo_warning" VALUE="...">ãŒã‚ã‚Œã°è¡¨ç¤ºã™ã‚‹
+ if (Neo.config.neo_warning) {
+ str += Neo.config.neo_warning;
+ }
+
+ var warning = document.getElementById("neoWarning")
+ warning.innerHTML = str;
+ setTimeout(function() { warning.style.opacity = "0"; }, 15000);
+};
+
+/*
+-----------------------------------------------------------------------
+UIã®æ›´æ–°
+-----------------------------------------------------------------------
+*/
+
+Neo.updateUI = function() {
+ var current = Neo.painter.tool.getToolButton();
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ if (current) {
+ if (current == toolTip) {
+ toolTip.setSelected(true);
+ toolTip.update();
+ } else {
+ toolTip.setSelected(false);
+ }
+ }
+ }
+ if (Neo.drawTip) {
+ Neo.drawTip.update();
+ }
+
+ Neo.updateUIColor(true, false);
+}
+
+Neo.updateUIColor = function(updateSlider, updateColorTip) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.update();
+ }
+
+ if (updateSlider) {
+ for (var i = 0; i < Neo.sliders.length; i++) {
+ var slider = Neo.sliders[i];
+ slider.update();
+ }
+ }
+
+ // パレットを変更ã™ã‚‹ã¨ã
+ if (updateColorTip) {
+ var colorTip = Neo.ColorTip.getCurrent();
+ if (colorTip) {
+ colorTip.setColor(Neo.painter.foregroundColor);
+ }
+ }
+};
+
+/*
+-----------------------------------------------------------------------
+リサイズ対応
+-----------------------------------------------------------------------
+*/
+
+Neo.updateWindow = function() {
+ if (Neo.fullScreen) {
+ document.getElementById("windowView").style.display = "block";
+ document.getElementById("windowView").appendChild(Neo.container);
+
+ } else {
+ document.getElementById("windowView").style.display = "none";
+ document.getElementById("pageView").appendChild(Neo.container);
+ }
+ Neo.resizeCanvas();
+};
+
+Neo.resizeCanvas = function() {
+ var appletWidth = Neo.container.clientWidth;
+ var appletHeight = Neo.container.clientHeight;
+
+ var canvasWidth = Neo.painter.canvasWidth;
+ var canvasHeight = Neo.painter.canvasHeight;
+
+ var width0 = canvasWidth * Neo.painter.zoom;
+ var height0 = canvasHeight * Neo.painter.zoom;
+
+ var width = (width0 < appletWidth - 100) ? width0 : appletWidth - 100;
+ var height = (height0 < appletHeight - 120) ? height0 : appletHeight - 120;
+
+ //width, heightã¯å¶æ•°ã§ãªã„ã¨èª¤å·®ãŒå‡ºã‚‹ãŸã‚
+ width = Math.floor(width / 2) * 2;
+ height = Math.floor(height / 2) * 2;
+
+ Neo.painter.destWidth = width;
+ Neo.painter.destHeight = height;
+
+ Neo.painter.destCanvas.width = width;
+ Neo.painter.destCanvas.height = height;
+ Neo.painter.destCanvasCtx = Neo.painter.destCanvas.getContext("2d");
+ Neo.painter.destCanvasCtx.imageSmoothingEnabled = false;
+ Neo.painter.destCanvasCtx.mozImageSmoothingEnabled = false;
+
+ Neo.canvas.style.width = width + "px";
+ Neo.canvas.style.height = height + "px";
+
+ var top = (Neo.container.clientHeight - toolsWrapper.clientHeight) / 2;
+ Neo.toolsWrapper.style.top = ((top > 0) ? top : 0) + "px";
+
+ if (top < 0) {
+ var s = Neo.container.clientHeight / toolsWrapper.clientHeight;
+ Neo.toolsWrapper.style.transform =
+ "translate(0, " + top + "px) scale(1," + s + ")";
+ } else {
+ Neo.toolsWrapper.style.transform = "";
+ }
+
+ Neo.painter.setZoom(Neo.painter.zoom);
+ Neo.painter.updateDestCanvas(0, 0, canvasWidth, canvasHeight);
+};
+
+/*
+-----------------------------------------------------------------------
+投稿
+-----------------------------------------------------------------------
+*/
+
+Neo.clone = function(src) {
+ var dst = {};
+ for (var k in src) {
+ dst[k] = src[k];
+ }
+ return dst;
+};
+
+Neo.getSizeString = function(len) {
+ var result = String(len);
+ while (result.length < 8) {
+ result = "0" + result;
+ }
+ return result;
+};
+
+Neo.openURL = function(url) {
+ if (Neo.isApp) {
+ require('electron').shell.openExternal(url);
+
+ } else {
+ location.href = url;
+ }
+};
+
+Neo.submit = function(board, blob, thumbnail, thumbnail2) {
+ var url = Neo.config.url_save;
+ console.log("submit url=" + url);
+
+ var headerString = Neo.config.send_header || "";
+ var imageType = Neo.config.send_header_image_type;
+ if (imageType && imageType == "true") {
+ headerString = "image_type=png&" + headerString
+ console.log("header=" + headerString);
+ }
+
+ var header = new Blob([headerString]);
+ var headerLength = this.getSizeString(header.size);
+ var imgLength = this.getSizeString(blob.size);
+
+ var array = ['P', // PaintBBS
+ headerLength,
+ header,
+ imgLength,
+ '\r\n',
+ blob];
+
+ if (thumbnail) {
+ var thumbnailLength = this.getSizeString(thumbnail.size);
+ array.push(thumbnailLength, thumbnail);
+ }
+ if (thumbnail2) {
+ var thumbnail2Length = this.getSizeString(thumbnail2.size);
+ array.push(thumbnail2Length, thumbnail2);
+ }
+
+ var body = new Blob(array, {type: 'application/octet-binary'}); //ã“ã‚ŒãŒå¿…è¦ï¼ï¼
+
+ var request = new XMLHttpRequest();
+ request.open("POST", url, true);
+
+ request.onload = function(e) {
+ console.log(request.response);
+ Neo.uploaded = true;
+
+ var url = Neo.config.url_exit;
+ /*if (url[0] == '/') {
+ url = url.replace(/^.*\//, ''); //よãã‚ã‹ã‚“ãªã„ã‘ã©ã¨ã‚Šã‚ãˆãš
+ }*/
+
+ // ãµãŸã°ã®paintpost.phpã¯ã€ç”»åƒæŠ•ç¨¿ã«æˆåŠŸã™ã‚‹ã¨responseã«
+ // "./futaba.php?mode=paintcom&amp;painttmp=.png"
+ // ã¨ã„ã†æ–‡å­—列を返ã—ã¾ã™ã€‚
+ //
+ // NEOã§ã¯ã€responseã«æ–‡å­—列"painttmp="ãŒå«ã¾ã‚Œã‚‹å ´åˆã¯
+ // <PARAM>ã§æŒ‡å®šã•ã‚ŒãŸurl_exitを無視ã—ã¦ã€ã“ã®URLã«ã‚¸ãƒ£ãƒ³ãƒ—ã—ã¾ã™ã€‚
+ var responseURL = request.response.replace(/&amp;/g, '&');
+ if (responseURL.match(/painttmp=/)) {
+ url = responseURL;
+ }
+ //var exitURL = board + url;
+ var exitURL = url;
+
+ // ã—ãƒã¡ã‚ƒã‚“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’よã見ãŸã‚‰
+ // response㌠"URL:〜" ã®å½¢ã ã£ãŸå ´åˆã¯ãã“ã¸é£›ã°ã™ã£ã¦æ›¸ã„ã¦ã‚ã‚Šã¾ã—ãŸã€‚
+ // ã“ã£ã¡ã‚’使ã†ã¹ãã§ã—ãŸâ€¦â€¦
+ if (responseURL.match(/^URL:/)) {
+ exitURL = responseURL.replace(/^URL:/, '');
+ }
+
+ location.href = exitURL;
+ };
+ request.onerror = function(e) {
+ console.log("error");
+ };
+ request.onabort = function(e) {
+ console.log("abort");
+ };
+ request.ontimeout = function(e) {
+ console.log("timeout");
+ };
+
+ if (0) { // データã®ãƒ‡ãƒãƒƒã‚°ã®ãŸã‚é€ä¿¡ã™ã‚‹ãƒ‡ãƒ¼ã‚¿ã‚’uint8arrayã«ã‚³ãƒ”ーã—ã¦ãŠã
+ var fr = new FileReader();
+ fr.onload = function () {
+ var result = fr.result;
+ }
+ fr.readAsArrayBuffer(body);
+ }
+
+ request.send(body);
+};
+
+/*
+-----------------------------------------------------------------------
+LiveConnect
+-----------------------------------------------------------------------
+*/
+
+Neo.getColors = function() {
+ console.log("getColors");
+ return Neo.config.colors.join('\n');
+};
+
+Neo.setColors = function(colors) {
+ console.log("setColors");
+ var array = colors.split('\n');
+ for (var i = 0; i < 14; i++) {
+ var color = array[i];
+ Neo.config.colors[i] = color;
+ Neo.colorTips[i].setColor(color);
+ }
+};
+
+/*
+-----------------------------------------------------------------------
+DOMツリーã®ä½œæˆ
+-----------------------------------------------------------------------
+*/
+
+Neo.createContainer = function(applet) {
+ var neo = document.createElement("div");
+ neo.className = "NEO";
+ neo.id = "NEO";
+ neo.innerHTML = (function() {/*
+
+<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
+
+<div id="pageView" style="width:450px; height:470px; margin:auto;">
+ <div id="container" style="visibility:hidden;">
+ <div id="center">
+ <div id="painterContainer">
+ <div id="painterWrapper">
+ <div id="upper">
+ <div id="redo">Rehacer</div>
+ <div id="undo">Deshacer</div>
+ <div id="fill">Llenar</div>
+ </div>
+ <div id="painter">
+ <div id="canvas">
+ <div id="scrollH"></div>
+ <div id="scrollV"></div>
+ <div id="zoomPlusWrapper">
+ <div id="zoomPlus">+</div>
+ </div>
+ <div id="zoomMinusWrapper">
+ <div id="zoomMinus">-</div>
+ </div>
+ <div id="neoWarning"></div>
+ </div>
+ </div>
+ <div id="lower">
+ </div>
+ </div>
+ <div id="toolsWrapper">
+ <div id="tools">
+ <div id="toolSet">
+ <div id="pen"></div>
+ <div id="pen2"></div>
+ <div id="effect"></div>
+ <div id="effect2"></div>
+ <div id="eraser"></div>
+ <div id="draw"></div>
+ <div id="mask"></div>
+
+ <div class="colorTips">
+ <div id="color2"></div><div id="color1"></div><br>
+ <div id="color4"></div><div id="color3"></div><br>
+ <div id="color6"></div><div id="color5"></div><br>
+ <div id="color8"></div><div id="color7"></div><br>
+ <div id="color10"></div><div id="color9"></div><br>
+ <div id="color12"></div><div id="color11"></div><br>
+ <div id="color14"></div><div id="color13"></div>
+ </div>
+
+ <div id="sliderRed"></div>
+ <div id="sliderGreen"></div>
+ <div id="sliderBlue"></div>
+ <div id="sliderAlpha"></div>
+ <div id="sliderSize"></div>
+
+ <div class="reserveControl" style="margin-top:4px;">
+ <div id="reserve1"></div>
+ <div id="reserve2"></div>
+ <div id="reserve3"></div>
+ </div>
+ <div id="layerControl" style="margin-top:6px;"></div>
+
+ <!--<div id="toolPad" style="height:20px;"></div>-->
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="headerButtons">
+ <div id="window">Ventana</div>
+ </div>
+ <div id="footerButtons">
+ <div id="submit">Enviar</div>
+ <div id="copyright">(C)ã—ã„ã¡ã‚ƒã‚“ PaintBBS NEO</div>
+ </div>
+ </div>
+</div>
+
+<div id="windowView" style="display: none;">
+
+</div>
+
+
+*/}).toString().match(/\/\*([^]*)\*\//)[1];
+
+ var parent = applet.parentNode;
+ parent.appendChild(neo);
+ parent.insertBefore(neo, applet);
+
+// applet.style.display = "none";
+
+ // NEOを組ã¿è¾¼ã‚“ã URLをアプリ版ã§é–‹ãã¨DOMツリーãŒ2é‡ã«ã§ãã¦æ ¼å¥½æ‚ªã„ã®ã§æ¶ˆã—ã¦ãŠã
+ setTimeout(function() {
+ var tmp = document.getElementsByClassName("NEO");
+ if (tmp.length > 1) {
+ for (var i = 1; i < tmp.length; i++) {
+ tmp[i].style.display = "none";
+ }
+ }
+ }, 0);
+};
+
+
+'use strict';
+
+Neo.Painter = function() {
+ this._undoMgr = new Neo.UndoManager(50);
+};
+
+Neo.Painter.prototype.container;
+Neo.Painter.prototype._undoMgr;
+Neo.Painter.prototype.tool;
+Neo.Painter.prototype.inputText;
+
+//Canvas Info
+Neo.Painter.prototype.canvasWidth;
+Neo.Painter.prototype.canvasHeight;
+Neo.Painter.prototype.canvas = [];
+Neo.Painter.prototype.canvasCtx = [];
+Neo.Painter.prototype.visible = [];
+Neo.Painter.prototype.current = 0;
+
+//Temp Canvas Info
+Neo.Painter.prototype.tempCanvas;
+Neo.Painter.prototype.tempCanvasCtx;
+Neo.Painter.prototype.tempX = 0;
+Neo.Painter.prototype.tempY = 0;
+
+//Destination Canvas for display
+Neo.Painter.prototype.destCanvas;
+Neo.Painter.prototype.destCanvasCtx;
+
+
+Neo.Painter.prototype.backgroundColor = "#ffffff";
+Neo.Painter.prototype.foregroundColor = "#000000";
+
+Neo.Painter.prototype.lineWidth = 1;
+Neo.Painter.prototype.alpha = 1;
+Neo.Painter.prototype.zoom = 1;
+Neo.Painter.prototype.zoomX = 0;
+Neo.Painter.prototype.zoomY = 0;
+
+Neo.Painter.prototype.isMouseDown;
+Neo.Painter.prototype.isMouseDownRight;
+Neo.Painter.prototype.prevMouseX;
+Neo.Painter.prototype.prevMouseY;
+Neo.Painter.prototype.mouseX;
+Neo.Painter.prototype.mouseY;
+
+Neo.Painter.prototype.slowX = 0;
+Neo.Painter.prototype.slowY = 0;
+Neo.Painter.prototype.stab = null;
+
+Neo.Painter.prototype.isShiftDown = false;
+Neo.Painter.prototype.isCtrlDown = false;
+Neo.Painter.prototype.isAltDown = false;
+
+//Neo.Painter.prototype.onUpdateCanvas;
+Neo.Painter.prototype._roundData = [];
+Neo.Painter.prototype._toneData = [];
+Neo.Painter.prototype.toolStack = [];
+
+Neo.Painter.prototype.maskType = 0;
+Neo.Painter.prototype.drawType = 0;
+Neo.Painter.prototype.maskColor = "#000000";
+Neo.Painter.prototype._currentColor = [];
+Neo.Painter.prototype._currentMask = [];
+
+Neo.Painter.prototype.aerr;
+
+Neo.Painter.LINETYPE_NONE = 0;
+Neo.Painter.LINETYPE_PEN = 1;
+Neo.Painter.LINETYPE_ERASER = 2;
+Neo.Painter.LINETYPE_BRUSH = 3;
+Neo.Painter.LINETYPE_TONE = 4;
+Neo.Painter.LINETYPE_DODGE = 5;
+Neo.Painter.LINETYPE_BURN = 6;
+
+Neo.Painter.MASKTYPE_NONE = 0;
+Neo.Painter.MASKTYPE_NORMAL = 1;
+Neo.Painter.MASKTYPE_REVERSE = 2;
+Neo.Painter.MASKTYPE_ADD = 3;
+Neo.Painter.MASKTYPE_SUB = 4;
+
+Neo.Painter.DRAWTYPE_FREEHAND = 0;
+Neo.Painter.DRAWTYPE_LINE = 1;
+Neo.Painter.DRAWTYPE_BEZIER = 2;
+
+Neo.Painter.ALPHATYPE_NONE = 0;
+Neo.Painter.ALPHATYPE_PEN = 1;
+Neo.Painter.ALPHATYPE_FILL = 2;
+Neo.Painter.ALPHATYPE_BRUSH = 3;
+
+Neo.Painter.TOOLTYPE_NONE = 0;
+Neo.Painter.TOOLTYPE_PEN = 1;
+Neo.Painter.TOOLTYPE_ERASER = 2;
+Neo.Painter.TOOLTYPE_HAND = 3;
+Neo.Painter.TOOLTYPE_SLIDER = 4;
+Neo.Painter.TOOLTYPE_FILL = 5;
+Neo.Painter.TOOLTYPE_MASK = 6;
+Neo.Painter.TOOLTYPE_ERASEALL = 7;
+Neo.Painter.TOOLTYPE_ERASERECT = 8;
+Neo.Painter.TOOLTYPE_COPY = 9;
+Neo.Painter.TOOLTYPE_PASTE = 10;
+Neo.Painter.TOOLTYPE_MERGE = 11;
+Neo.Painter.TOOLTYPE_FLIP_H = 12;
+Neo.Painter.TOOLTYPE_FLIP_V = 13;
+
+Neo.Painter.TOOLTYPE_BRUSH = 14;
+Neo.Painter.TOOLTYPE_TEXT = 15;
+Neo.Painter.TOOLTYPE_TONE = 16;
+Neo.Painter.TOOLTYPE_BLUR = 17;
+Neo.Painter.TOOLTYPE_DODGE = 18;
+Neo.Painter.TOOLTYPE_BURN = 19;
+Neo.Painter.TOOLTYPE_RECT = 20;
+Neo.Painter.TOOLTYPE_RECTFILL = 21;
+Neo.Painter.TOOLTYPE_ELLIPSE = 22;
+Neo.Painter.TOOLTYPE_ELLIPSEFILL = 23;
+Neo.Painter.TOOLTYPE_BLURRECT = 24;
+Neo.Painter.TOOLTYPE_TURN = 25;
+
+Neo.Painter.prototype.build = function(div, width, height)
+{
+ this.container = div;
+ this._initCanvas(div, width, height);
+ this._initRoundData();
+ this._initToneData();
+ this._initInputText();
+
+ this.setTool(new Neo.PenTool());
+
+};
+
+Neo.Painter.prototype.setTool = function(tool) {
+ if (this.tool && this.tool.saveStates) this.tool.saveStates();
+
+ if (this.tool && this.tool.kill) {
+ this.tool.kill();
+ }
+ this.tool = tool;
+ tool.init();
+ if (this.tool && this.tool.loadStates) this.tool.loadStates();
+};
+
+Neo.Painter.prototype.pushTool = function(tool) {
+ this.toolStack.push(this.tool);
+ this.tool = tool;
+ tool.init();
+};
+
+Neo.Painter.prototype.popTool = function() {
+ var tool = this.tool;
+ if (tool && tool.kill) {
+ tool.kill();
+ }
+ this.tool = this.toolStack.pop();
+};
+
+Neo.Painter.prototype.getCurrentTool = function() {
+ if (this.tool) {
+ var tool = this.tool;
+ if (tool && tool.type == Neo.Painter.TOOLTYPE_SLIDER) {
+ var stack = this.toolStack;
+ if (stack.length > 0) {
+ tool = stack[stack.length - 1];
+ }
+ }
+ return tool;
+ }
+ return null;
+};
+
+Neo.Painter.prototype.setToolByType = function(toolType) {
+ switch (parseInt(toolType)) {
+ case Neo.Painter.TOOLTYPE_PEN: this.setTool(new Neo.PenTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASER: this.setTool(new Neo.EraserTool()); break;
+ case Neo.Painter.TOOLTYPE_HAND: this.setTool(new Neo.HandTool()); break;
+ case Neo.Painter.TOOLTYPE_FILL: this.setTool(new Neo.FillTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASEALL: this.setTool(new Neo.EraseAllTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASERECT: this.setTool(new Neo.EraseRectTool()); break;
+
+ case Neo.Painter.TOOLTYPE_COPY: this.setTool(new Neo.CopyTool()); break;
+ case Neo.Painter.TOOLTYPE_PASTE: this.setTool(new Neo.PasteTool()); break;
+ case Neo.Painter.TOOLTYPE_MERGE: this.setTool(new Neo.MergeTool()); break;
+ case Neo.Painter.TOOLTYPE_FLIP_H: this.setTool(new Neo.FlipHTool()); break;
+ case Neo.Painter.TOOLTYPE_FLIP_V: this.setTool(new Neo.FlipVTool()); break;
+
+ case Neo.Painter.TOOLTYPE_BRUSH: this.setTool(new Neo.BrushTool()); break;
+ case Neo.Painter.TOOLTYPE_TEXT: this.setTool(new Neo.TextTool()); break;
+ case Neo.Painter.TOOLTYPE_TONE: this.setTool(new Neo.ToneTool()); break;
+ case Neo.Painter.TOOLTYPE_BLUR: this.setTool(new Neo.BlurTool()); break;
+ case Neo.Painter.TOOLTYPE_DODGE: this.setTool(new Neo.DodgeTool()); break;
+ case Neo.Painter.TOOLTYPE_BURN: this.setTool(new Neo.BurnTool()); break;
+
+ case Neo.Painter.TOOLTYPE_RECT: this.setTool(new Neo.RectTool()); break;
+ case Neo.Painter.TOOLTYPE_RECTFILL: this.setTool(new Neo.RectFillTool()); break;
+ case Neo.Painter.TOOLTYPE_ELLIPSE: this.setTool(new Neo.EllipseTool()); break;
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:this.setTool(new Neo.EllipseFillTool()); break;
+ case Neo.Painter.TOOLTYPE_BLURRECT: this.setTool(new Neo.BlurRectTool()); break;
+ case Neo.Painter.TOOLTYPE_TURN: this.setTool(new Neo.TurnTool()); break;
+
+ default:
+ console.log("unknown toolType " + toolType);
+ break;
+ }
+};
+
+Neo.Painter.prototype._initCanvas = function(div, width, height) {
+ width = parseInt(width);
+ height = parseInt(height);
+ var destWidth = parseInt(div.clientWidth);
+ var destHeight = parseInt(div.clientHeight);
+ this.destWidth = width;
+ this.destHeight = height;
+
+ this.canvasWidth = width;
+ this.canvasHeight = height;
+ this.zoomX = width * 0.5;
+ this.zoomY = height * 0.5;
+
+ for (var i = 0; i < 2; i++) {
+ this.canvas[i] = document.createElement("canvas");
+ this.canvas[i].width = width;
+ this.canvas[i].height = height;
+ this.canvasCtx[i] = this.canvas[i].getContext("2d");
+
+ this.canvas[i].style.imageRendering = "pixelated";
+ this.canvasCtx[i].imageSmoothingEnabled = false;
+ this.canvasCtx[i].mozImageSmoothingEnabled = false;
+ this.visible[i] = true;
+ }
+
+ this.tempCanvas = document.createElement("canvas");
+ this.tempCanvas.width = width;
+ this.tempCanvas.height = height;
+ this.tempCanvasCtx = this.tempCanvas.getContext("2d");
+ this.tempCanvas.style.position = "absolute";
+ this.tempCanvas.enabled = false;
+
+ var array = this.container.getElementsByTagName("canvas");
+ if (array.length > 0) {
+ this.destCanvas = array[0];
+ } else {
+ this.destCanvas = document.createElement("canvas");
+ this.container.appendChild(this.destCanvas);
+ }
+
+ this.destCanvasCtx = this.destCanvas.getContext("2d");
+ this.destCanvas.width = destWidth;
+ this.destCanvas.height = destHeight;
+
+ this.destCanvas.style.imageRendering = "pixelated";
+ this.destCanvasCtx.imageSmoothingEnabled = false;
+ this.destCanvasCtx.mozImageSmoothingEnabled = false;
+
+ var ref = this;
+
+ var container = document.getElementById("container");
+
+ if (window.PointerEvent) {
+ container.addEventListener("pointerdown", function(e) {
+ ref._mouseDownHandler(e); });
+ container.addEventListener("pointerup", function(e) {
+ ref._mouseUpHandler(e); });
+ container.addEventListener("pointermove", function(e) {
+ ref._mouseMoveHandler(e); });
+ container.addEventListener("pointerover", function(e) {
+ ref._rollOverHandler(e); });
+ container.addEventListener("pointerout", function(e) {
+ ref._rollOutHandler(e); });
+
+ } else {
+ container.onmousedown = function(e) {ref._mouseDownHandler(e)};
+ container.onmousemove = function(e) {ref._mouseMoveHandler(e)};
+ container.onmouseup = function(e) {ref._mouseUpHandler(e)};
+ container.onmouseover = function(e) {ref._rollOverHandler(e)};
+ container.onmouseout = function(e) {ref._rollOutHandler(e)};
+
+ container.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ }, true);
+ container.addEventListener("touchmove", function(e) {
+ ref._mouseMoveHandler(e);
+ }, true);
+ container.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, true);
+ }
+
+ document.onkeydown = function(e) {ref._keyDownHandler(e)};
+ document.onkeyup = function(e) {ref._keyUpHandler(e)};
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype._initRoundData = function() {
+ for (var r = 1; r <= 30; r++) {
+ this._roundData[r] = new Uint8Array(r * r);
+ var mask = this._roundData[r];
+ var d = Math.floor(r / 2.0);
+ var index = 0;
+ for (var x = 0; x < r; x++) {
+ for (var y = 0; y < r; y++) {
+ var xx = x + 0.5 - r/2.0;
+ var yy = y + 0.5 - r/2.0;
+ mask[index++] = (xx*xx + yy*yy <= r*r/4) ? 1 : 0;
+ }
+ }
+ }
+ this._roundData[3][0] = 0;
+ this._roundData[3][2] = 0;
+ this._roundData[3][6] = 0;
+ this._roundData[3][8] = 0;
+
+ this._roundData[5][1] = 0;
+ this._roundData[5][3] = 0;
+ this._roundData[5][5] = 0;
+ this._roundData[5][9] = 0;
+ this._roundData[5][15] = 0;
+ this._roundData[5][19] = 0;
+ this._roundData[5][21] = 0;
+ this._roundData[5][23] = 0;
+};
+
+Neo.Painter.prototype._initToneData = function() {
+ var pattern = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];
+
+ for (var i = 0; i < 16; i++) {
+ this._toneData[i] = new Uint8Array(16);
+ for (var j = 0; j < 16; j++) {
+ this._toneData[i][j] = (i >= pattern[j]) ? 1 : 0;
+ }
+ }
+};
+
+Neo.Painter.prototype.getToneData = function(alpha) {
+ var alphaTable = [23,
+ 47,
+ 69,
+ 92,
+ 114,
+ 114,
+ 114,
+ 138,
+ 161,
+ 184,
+ 184,
+ 207,
+ 230,
+ 230,
+ 253,
+ ];
+
+ for (var i = 0; i < alphaTable.length; i++) {
+ if (alpha < alphaTable[i]) {
+ return this._toneData[i];
+ }
+ }
+ return this._toneData[i];
+};
+
+Neo.Painter.prototype._initInputText = function() {
+ var text = document.getElementById("inputtext");
+ if (!text) {
+ text = document.createElement("div");
+ }
+
+ text.id = "inputext";
+ text.setAttribute("contentEditable", true);
+ text.spellcheck = false;
+ text.className = "inputText";
+ text.innerHTML = "";
+
+ text.style.display = "none";
+// text.style.userSelect = "none";
+ Neo.painter.container.appendChild(text);
+ this.inputText = text;
+
+ this.updateInputText();
+};
+
+Neo.Painter.prototype.hideInputText = function() {
+ var text = this.inputText;
+ text.blur();
+ text.style.display = "none";
+};
+
+Neo.Painter.prototype.updateInputText = function() {
+ var text = this.inputText;
+ var d = this.lineWidth;
+ var fontSize = Math.round(d * 55/28 + 7);
+ var height = Math.round(d * 68/28 + 12);
+
+ text.style.fontSize = fontSize + "px";
+ text.style.lineHeight = fontSize + "px";
+ text.style.height = fontSize + "px";
+ text.style.marginTop = -fontSize + "px";
+};
+
+/*
+-----------------------------------------------------------------------
+ Mouse Event Handling
+-----------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype._keyDownHandler = function(e) {
+ this.isShiftDown = e.shiftKey;
+ this.isCtrlDown = e.ctrlKey;
+ this.isAltDown = e.altKey;
+ if (e.keyCode == 32) this.isSpaceDown = true;
+
+ if (!this.isShiftDown && this.isCtrlDown) {
+ if (!this.isAltDown) {
+ if (e.keyCode == 90 || e.keyCode == 85) this.undo(); //Ctrl+Z,Ctrl.U
+ if (e.keyCode == 89) this.redo(); //Ctrl+Y
+ } else {
+ if (e.keyCode == 90) this.redo(); //Ctrl+Alt+Z
+ }
+ }
+
+ if (!this.isShiftDown && !this.isCtrlDown && !this.isAltDown) {
+ if (e.keyCode == 107) new Neo.ZoomPlusCommand(this).execute(); // +
+ if (e.keyCode == 109) new Neo.ZoomMinusCommand(this).execute(); // -
+ }
+
+ if (this.tool.keyDownHandler) {
+ this.tool.keyDownHandler(e);
+ }
+
+ //スペース・Shift+スペースã§ã§ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«ã—ãªã„よã†ã«
+ if (document.activeElement != this.inputText) e.preventDefault();
+};
+
+Neo.Painter.prototype._keyUpHandler = function(e) {
+ this.isShiftDown = e.shiftKey;
+ this.isCtrlDown = e.ctrlKey;
+ this.isAltDown = e.altKey;
+ if (e.keyCode == 32) this.isSpaceDown = false;
+
+ if (this.tool.keyUpHandler) {
+ this.tool.keyUpHandler(oe);
+ }
+};
+
+Neo.Painter.prototype._rollOverHandler = function(e) {
+ if (this.tool.rollOverHandler) {
+ this.tool.rollOverHandler(this);
+ }
+};
+
+Neo.Painter.prototype._rollOutHandler = function(e) {
+ if (this.tool.rollOutHandler) {
+ this.tool.rollOutHandler(this);
+ }
+};
+
+Neo.Painter.prototype._mouseDownHandler = function(e) {
+ if (e.target == Neo.painter.destCanvas) {
+ //よãã‚ã‹ã‚‰ãªã„ãŒChromeã§ãƒ‰ãƒ©ãƒƒã‚°ã®æ™‚カレットãŒå‡ºã‚‹ã®ã‚’防ã
+ //http://stackoverflow.com/questions/2745028/chrome-sets-cursor-to-text-while-dragging-why
+ e.preventDefault();
+ }
+
+ if (e.button == 2) {
+ this.isMouseDownRight = true;
+
+ } else {
+ if (!e.shiftKey && e.ctrlKey && e.altKey) {
+ this.isMouseDown = true;
+
+ } else {
+ if (e.ctrlKey || e.altKey) {
+ this.isMouseDownRight = true;
+ } else {
+ this.isMouseDown = true;
+ }
+ }
+ }
+
+ this._updateMousePosition(e);
+ this.prevMouseX = this.mouseX;
+ this.prevMouseY = this.mouseY;
+
+ if (this.isMouseDownRight) {
+ this.isMouseDownRight = false;
+ if (!this.isWidget(e.target)) {
+ this.pickColor(this.mouseX, this.mouseY);
+ return;
+ }
+ }
+
+ if (!this.isUIPaused()) {
+ if (e.target['data-bar']) {
+ this.pushTool(new Neo.HandTool());
+
+ } else if (this.isSpaceDown && document.activeElement != this.inputText) {
+ this.pushTool(new Neo.HandTool());
+ this.tool.reverse = true;
+
+ } else if (e.target['data-slider'] != undefined) {
+ this.pushTool(new Neo.SliderTool());
+ this.tool.target = e.target;
+
+ } else if (e.ctrlKey && e.altKey && !e.shiftKey) {
+ this.pushTool(new Neo.SliderTool());
+ this.tool.target = Neo.sliders[Neo.SLIDERTYPE_SIZE].element;
+ this.tool.alt = true;
+
+ } else if (this.isWidget(e.target)) {
+ this.isMouseDown = false;
+ this.pushTool(new Neo.DummyTool());
+ }
+ }
+ this.tool.downHandler(this);
+
+ var ref = this;
+ document.onmouseup = function(e) {
+ ref._mouseUpHandler(e)
+ };
+};
+
+Neo.Painter.prototype._mouseUpHandler = function(e) {
+ this.isMouseDown = false;
+ this.isMouseDownRight = false;
+ this.tool.upHandler(this);
+ document.onmouseup = undefined;
+};
+
+Neo.Painter.prototype._mouseMoveHandler = function(e) {
+ this._updateMousePosition(e);
+
+ if (this.isMouseDown || this.isMouseDownRight) {
+ this.tool.moveHandler(this);
+ } else {
+ if (this.tool.upMoveHandler) {
+ this.tool.upMoveHandler(this);
+ }
+ }
+ this.prevMouseX = this.mouseX;
+ this.prevMouseY = this.mouseY;
+};
+
+
+Neo.Painter.prototype._updateMousePosition = function(e) {
+ var rect = this.destCanvas.getBoundingClientRect();
+ var x = (e.clientX !== undefined) ? e.clientX : e.touches[0].clientX;
+ var y = (e.clientY !== undefined) ? e.clientY : e.touches[0].clientY;
+
+ if (this.zoom <= 0) this.zoom = 1; //ãªãœã‹0ã«ãªã‚‹ã“ã¨ãŒã‚ã‚‹ã®ã§
+
+ this.mouseX = (x - rect.left) / this.zoom
+ + this.zoomX
+ - this.destCanvas.width * 0.5 / this.zoom;
+ this.mouseY = (y - rect.top) / this.zoom
+ + this.zoomY
+ - this.destCanvas.height * 0.5 / this.zoom;
+
+ if (isNaN(this.prevMouseX)) {
+ this.prevMouseX = this.mouseX;
+ }
+ if (isNaN(this.prevMouseY)) {
+ this.prevMosueY = this.mouseY;
+ }
+
+ this.slowX = this.slowX * 0.8 + this.mouseX * 0.2;
+ this.slowY = this.slowY * 0.8 + this.mouseY * 0.2;
+ var now = new Date().getTime();
+ if (this.stab) {
+ var pause = this.stab[3];
+ if (pause) {
+ // ãƒãƒ¼ã‚ºä¸­
+ if (now > pause) {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+
+ } else {
+ // ãƒãƒ¼ã‚ºã•ã‚Œã¦ã„ãªã„ã¨ã
+ var prev = this.stab[2];
+ if (now - prev > 150) { // 150ms以上止ã¾ã£ã¦ã„ãŸã‚‰ãƒãƒ¼ã‚ºã‚’オンã«ã™ã‚‹
+ this.stab[3] = now + 200 // 200msペンã®ä½ç½®ã‚’固定
+
+ } else {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+ }
+ } else {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+
+ this.rawMouseX = x;
+ this.rawMouseY = y;
+ this.clipMouseX = Math.max(Math.min(this.canvasWidth, this.mouseX), 0);
+ this.clipMouseY = Math.max(Math.min(this.canvasHeight, this.mouseY), 0);
+};
+
+Neo.Painter.prototype._beforeUnloadHandler = function(e) {
+ // quick save
+};
+
+Neo.Painter.prototype.getStabilized = function() {
+ return this.stab;
+};
+
+/*
+-------------------------------------------------------------------------
+ Undo
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.undo = function() {
+ var undoItem = this._undoMgr.popUndo();
+ if (undoItem) {
+ this._pushRedo();
+ this.canvasCtx[0].putImageData(undoItem.data[0], undoItem.x,undoItem.y);
+ this.canvasCtx[1].putImageData(undoItem.data[1], undoItem.x,undoItem.y);
+ this.updateDestCanvas(undoItem.x, undoItem.y, undoItem.width, undoItem.height);
+ }
+};
+
+Neo.Painter.prototype.redo = function() {
+ var undoItem = this._undoMgr.popRedo();
+ if (undoItem) {
+ this._pushUndo(0,0,this.canvasWidth, this.canvasHeight, true);
+ this.canvasCtx[0].putImageData(undoItem.data[0], undoItem.x,undoItem.y);
+ this.canvasCtx[1].putImageData(undoItem.data[1], undoItem.x,undoItem.y);
+ this.updateDestCanvas(undoItem.x, undoItem.y, undoItem.width, undoItem.height);
+ }
+};
+
+Neo.Painter.prototype.hasUndo = function() {
+ return true;
+};
+
+Neo.Painter.prototype._pushUndo = function(x, y, w, h, holdRedo) {
+ x = (x == undefined) ? 0 : x;
+ y = (y == undefined) ? 0 : y;
+ w = (w == undefined) ? this.canvasWidth : w;
+ h = (h == undefined) ? this.canvasHeight : h;
+ var undoItem = new Neo.UndoItem();
+ undoItem.x = 0;
+ undoItem.y = 0;
+ undoItem.width = w;
+ undoItem.height = h;
+ undoItem.data = [this.canvasCtx[0].getImageData(x, y, w, h),
+ this.canvasCtx[1].getImageData(x, y, w, h)];
+ this._undoMgr.pushUndo(undoItem, holdRedo);
+};
+
+Neo.Painter.prototype._pushRedo = function(x, y, w, h) {
+ x = (x == undefined) ? 0 : x;
+ y = (y == undefined) ? 0 : y;
+ w = (w == undefined) ? this.canvasWidth : w;
+ h = (h == undefined) ? this.canvasHeight : h;
+ var undoItem = new Neo.UndoItem();
+ undoItem.x = 0;
+ undoItem.y = 0;
+ undoItem.width = w;
+ undoItem.height = h;
+ undoItem.data = [this.canvasCtx[0].getImageData(x, y, w, h),
+ this.canvasCtx[1].getImageData(x, y, w, h)];
+ this._undoMgr.pushRedo(undoItem);
+};
+
+
+/*
+-------------------------------------------------------------------------
+ Data Cache for Undo / Redo
+-------------------------------------------------------------------------
+*/
+
+Neo.UndoManager = function(_maxStep){
+ this._maxStep = _maxStep;
+ this._undoItems = [];
+ this._redoItems = [];
+}
+Neo.UndoManager.prototype._maxStep;
+Neo.UndoManager.prototype._redoItems;
+Neo.UndoManager.prototype._undoItems;
+
+//アクションをã—ã¦Undo情報を更新
+Neo.UndoManager.prototype.pushUndo = function(undoItem, holdRedo) {
+ this._undoItems.push(undoItem);
+ if (this._undoItems.length > this._maxStep) {
+ this._undoItems.shift();
+ }
+
+ if (!holdRedo == true) {
+ this._redoItems = [];
+ }
+};
+
+Neo.UndoManager.prototype.popUndo = function() {
+ return this._undoItems.pop();
+}
+
+Neo.UndoManager.prototype.pushRedo = function(undoItem) {
+ this._redoItems.push(undoItem);
+}
+
+Neo.UndoManager.prototype.popRedo = function() {
+ return this._redoItems.pop();
+}
+
+
+Neo.UndoItem = function() {}
+Neo.UndoItem.prototype.data;
+Neo.UndoItem.prototype.x;
+Neo.UndoItem.prototype.y;
+Neo.UndoItem.prototype.width;
+Neo.UndoItem.prototype.height;
+
+/*
+-------------------------------------------------------------------------
+ Zoom Controller
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.setZoom = function(value) {
+ this.zoom = value;
+
+ var container = document.getElementById("container");
+ var width = this.canvasWidth * this.zoom;
+ var height = this.canvasHeight * this.zoom;
+ if (width > container.clientWidth - 100) width = container.clientWidth - 100;
+ if (height > container.clientHeight - 130) height = container.clientHeight - 130;
+ this.destWidth = width;
+ this.destHeight = height;
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight, false);
+ this.setZoomPosition(this.zoomX, this.zoomY);
+};
+
+Neo.Painter.prototype.setZoomPosition = function(x, y) {
+ var minx = (this.destCanvas.width / this.zoom) * 0.5;
+ var maxx = this.canvasWidth - minx;
+ var miny = (this.destCanvas.height / this.zoom) * 0.5;
+ var maxy = this.canvasHeight - miny;
+
+
+ x = Math.round(Math.max(Math.min(maxx,x),minx));
+ y = Math.round(Math.max(Math.min(maxy,y),miny));
+
+ this.zoomX = x;
+ this.zoomY = y;
+ this.updateDestCanvas(0,0,this.canvasWidth,this.canvasHeight,false);
+
+ this.scrollBarX = (maxx == minx) ? 0 : (x - minx) / (maxx - minx);
+ this.scrollBarY = (maxy == miny) ? 0 : (y - miny) / (maxy - miny);
+ this.scrollWidth = maxx - minx;
+ this.scrollHeight = maxy - miny;
+
+ if (Neo.scrollH) Neo.scrollH.update(this);
+ if (Neo.scrollV) Neo.scrollV.update(this);
+
+ this.hideInputText();
+};
+
+
+/*
+-------------------------------------------------------------------------
+ Drawing Helper
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.submit = function(board) {
+ var thumbnail = null;
+ var thumbnail2 = null;
+
+ if (this.useThumbnail()) {
+ thumbnail = this.getThumbnail(Neo.config.thumbnail_type || "png");
+ if (Neo.config.thumbnail_type2) {
+ thumbnail2 = this.getThumbnail(Neo.config.thumbnail_type2);
+ }
+ }
+ Neo.submit(board, this.getPNG(), thumbnail2, thumbnail);
+};
+
+Neo.Painter.prototype.useThumbnail = function() {
+ var thumbnailWidth = this.getThumbnailWidth();
+ var thumbnailHeight = this.getThumbnailHeight();
+ if (thumbnailWidth && thumbnailHeight) {
+ if (thumbnailWidth < this.canvasWidth ||
+ thumbnailHeight < this.canvasHeight) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Neo.Painter.prototype.dataURLtoBlob = function(dataURL) {
+ var byteString;
+ if (dataURL.split(',')[0].indexOf('base64') >= 0) {
+ byteString = atob(dataURL.split(',')[1]);
+ } else {
+ byteString = unescape(dataURL.split(',')[1]);
+ }
+
+ // write the bytes of the string to a typed array
+ var ia = new Uint8Array(byteString.length);
+ for (var i = 0; i < byteString.length; i++) {
+ ia[i] = byteString.charCodeAt(i);
+ }
+ return new Blob([ia], {type:'image/png'});
+};
+
+Neo.Painter.prototype.getImage = function(imageWidth, imageHeight) {
+ var width = this.canvasWidth;
+ var height = this.canvasHeight;
+ imageWidth = imageWidth || width;
+ imageHeight = imageHeight || height;
+
+ var pngCanvas = document.createElement("canvas");
+ pngCanvas.width = imageWidth;
+ pngCanvas.height = imageHeight;
+ var pngCanvasCtx = pngCanvas.getContext("2d");
+ pngCanvasCtx.fillStyle = "#ffffff";
+ pngCanvasCtx.fillRect(0, 0, imageWidth, imageHeight);
+
+ if (this.visible[0]) {
+ pngCanvasCtx.drawImage(this.canvas[0],
+ 0, 0, width, height,
+ 0, 0, imageWidth, imageHeight);
+ }
+ if (this.visible[1]) {
+ pngCanvasCtx.drawImage(this.canvas[1],
+ 0, 0, width, height,
+ 0, 0, imageWidth, imageHeight);
+ }
+ return pngCanvas;
+};
+
+Neo.Painter.prototype.getPNG = function() {
+ var image = this.getImage();
+ var dataURL = image.toDataURL('image/png');
+ return this.dataURLtoBlob(dataURL);
+};
+
+Neo.Painter.prototype.getThumbnail = function(type) {
+ if (type != "animation") {
+ var thumbnailWidth = this.getThumbnailWidth();
+ var thumbnailHeight = this.getThumbnailHeight();
+ if (thumbnailWidth || thumbnailHeight) {
+ var width = this.canvasWidth;
+ var height = this.canvasHeight;
+ if (thumbnailWidth == 0) {
+ thumbnailWidth = thumbnailHeight * width / height;
+ }
+ if (thumbnailHeight == 0) {
+ thumbnailHeight = thumbnailWidth * height / width;
+ }
+ } else {
+ thumbnailWidth = thumbnailHeight = null;
+ }
+
+ console.log("get thumbnail", thumbnailWidth, thumbnailHeight);
+
+ var image = this.getImage(thumbnailWidth, thumbnailHeight);
+ var dataURL = image.toDataURL('image/' + type);
+ return this.dataURLtoBlob(dataURL);
+
+ } else {
+ return new Blob([]); //animationã«ã¯å¯¾å¿œã—ã¦ã„ãªã„ã®ã§ãƒ€ãƒŸãƒ¼ãƒ‡ãƒ¼ã‚¿ã‚’è¿”ã™
+ }
+};
+
+Neo.Painter.prototype.getThumbnailWidth = function() {
+ var width = Neo.config.thumbnail_width;
+ if (width) {
+ if (width.match(/%$/)) {
+ return Math.floor(this.canvasWidth * (parseInt(width) / 100.0));
+ } else {
+ return parseInt(width);
+ }
+ }
+ return 0;
+};
+
+Neo.Painter.prototype.getThumbnailHeight = function() {
+ var height = Neo.config.thumbnail_height;
+ if (height) {
+ if (height.match(/%$/)) {
+ return Math.floor(this.canvasHeight * (parseInt(height) / 100.0));
+ } else {
+ return parseInt(height);
+ }
+ }
+ return 0;
+};
+
+Neo.Painter.prototype.clearCanvas = function(doConfirm) {
+ if (!doConfirm || confirm("Borrar todo")) {
+ //Register undo first;
+ this._pushUndo();
+
+ this.canvasCtx[0].clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.canvasCtx[1].clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+ }
+};
+
+Neo.Painter.prototype.updateDestCanvas = function(x, y, width, height, useTemp) {
+ var canvasWidth = this.canvasWidth;
+ var canvasHeight = this.canvasHeight;
+ var updateAll = false;
+ if (x == 0 && y == 0 && width == canvasWidth && height == canvasHeight) {
+ updateAll = true;
+ };
+
+ if (x + width > this.canvasWidth) width = this.canvasWidth - x;
+ if (y + height > this.canvasHeight) height = this.canvasHeight - y;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (width <= 0 || height <= 0) return;
+
+ var ctx = this.destCanvasCtx;
+ ctx.save();
+ ctx.fillStyle = "#ffffff";
+
+ if (updateAll) {
+ ctx.fillRect(0, 0, this.destCanvas.width, this.destCanvas.height);
+ } else {
+ //カーソルã®æ画ゴミãŒæ®‹ã‚‹ã®ã‚’ã”ã¾ã‹ã™ãŸã‚
+ if (x + width == this.canvasWidth) width++;
+ if (y + height == this.canvasHeight) height++;
+ }
+
+ ctx.translate(this.destCanvas.width*.5, this.destCanvas.height*.5);
+ ctx.scale(this.zoom, this.zoom);
+ ctx.translate(-this.zoomX, -this.zoomY);
+ ctx.globalAlpha = 1.0;
+ ctx.msImageSmoothingEnabled = 0;
+
+ if (!updateAll) {
+ ctx.fillRect(x, y, width, height);
+ }
+
+ if (this.visible[0]) {
+ ctx.drawImage(this.canvas[0],
+ x, y, width, height,
+ x, y, width, height);
+ }
+ if (this.visible[1]) {
+ ctx.drawImage(this.canvas[1],
+ x, y, width, height,
+ x, y, width, height);
+ }
+ if (useTemp) {
+ ctx.globalAlpha = 1.0; //this.alpha;
+ ctx.drawImage(this.tempCanvas,
+ x, y, width, height,
+ x + this.tempX, y + this.tempY, width, height);
+ }
+ ctx.restore();
+};
+
+Neo.Painter.prototype.getBound = function(x0, y0, x1, y1, r) {
+ var left = Math.floor((x0 < x1) ? x0 : x1);
+ var top = Math.floor((y0 < y1) ? y0 : y1);
+ var width = Math.ceil(Math.abs(x0 - x1));
+ var height = Math.ceil(Math.abs(y0 - y1));
+ r = Math.ceil(r + 1);
+
+ if (!r) {
+ width += 1;
+ height += 1;
+
+ } else {
+ left -= r;
+ top -= r;
+ width += r * 2;
+ height += r * 2;
+ }
+ return [left, top, width, height];
+};
+
+Neo.Painter.prototype.getColor = function(c) {
+ if (!c) c = this.foregroundColor;
+ var r = parseInt(c.substr(1, 2), 16);
+ var g = parseInt(c.substr(3, 2), 16);
+ var b = parseInt(c.substr(5, 2), 16);
+ var a = Math.floor(this.alpha * 255);
+ return a <<24 | b<<16 | g<<8 | r;
+};
+
+Neo.Painter.prototype.getColorString = function(c) {
+ var rgb = ("000000" + (c & 0xffffff).toString(16)).substr(-6);
+ return '#' + rgb;
+};
+
+Neo.Painter.prototype.setColor = function(c) {
+ if (typeof c != "string") c = this.getColorString(c);
+ this.foregroundColor = c;
+
+ Neo.updateUI();
+};
+
+Neo.Painter.prototype.getAlpha = function(type) {
+ var a1 = this.alpha;
+
+ switch (type) {
+ case Neo.Painter.ALPHATYPE_PEN:
+ if (a1 > 0.5) {
+ a1 = 1.0/16 + (a1 - 0.5) * 30.0/16;
+ } else {
+ a1 = Math.sqrt(2 * a1) / 16.0;
+ }
+ a1 = Math.min(1, Math.max(0, a1));
+ break;
+
+ case Neo.Painter.ALPHATYPE_FILL:
+ a1 = -0.00056 * a1 + 0.0042 / (1.0 - a1) - 0.0042;
+ a1 = Math.min(1.0, Math.max(0, a1 * 10));
+ break;
+
+ case Neo.Painter.ALPHATYPE_BRUSH:
+ a1 = -0.00056 * a1 + 0.0042 / (1.0 - a1) - 0.0042;
+ a1 = Math.min(1.0, Math.max(0, a1));
+ break;
+ }
+
+ // アルファãŒå°ã•ã„時ã¯é©å½“ã«ç‚¹ã‚’抜ã„ã¦è¦‹ãŸç›®ã®æ¿ƒåº¦ã‚’åˆã‚ã›ã‚‹
+ if (a1 < 1.0/255) {
+ this.aerr += a1;
+ a1 = 0;
+ while (this.aerr > 1.0/255) {
+ a1 = 1.0/255;
+ this.aerr -= 1.0/255;
+ }
+ }
+ return a1;
+};
+
+Neo.Painter.prototype.prepareDrawing = function () {
+ var r = parseInt(this.foregroundColor.substr(1, 2), 16);
+ var g = parseInt(this.foregroundColor.substr(3, 2), 16);
+ var b = parseInt(this.foregroundColor.substr(5, 2), 16);
+ var a = Math.floor(this.alpha * 255);
+
+ var maskR = parseInt(this.maskColor.substr(1, 2), 16);
+ var maskG = parseInt(this.maskColor.substr(3, 2), 16);
+ var maskB = parseInt(this.maskColor.substr(5, 2), 16);
+
+ this._currentColor = [r, g, b, a];
+ this._currentMask = [maskR, maskG, maskB];
+};
+
+Neo.Painter.prototype.isMasked = function (buf8, index) {
+ var r = this._currentMask[0];
+ var g = this._currentMask[1];
+ var b = this._currentMask[2];
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3];
+
+ if (a0 == 0) {
+ r0 = 0xff;
+ g0 = 0xff;
+ b0 = 0xff;
+ }
+
+ var type = this.maskType;
+
+ //TODO
+ //ã„ã‚ã„ã‚試ã—ãŸã®ã§ã™ãŒåŠé€æ˜Žã§æç”»ã™ã‚‹ã¨ãã®åŠ ç®—・逆加算をå†ç¾ã™ã‚‹æ–¹æ³•ãŒã‚ã‹ã‚Šã¾ã›ã‚“。
+ //ã¨ã‚Šã‚ãˆãšå˜ç´”ã«ç„¡è¦–ã—ã¦ã„ã¾ã™ã€‚
+ if (type == Neo.Painter.MASKTYPE_ADD ||
+ type == Neo.Painter.MASKTYPE_SUB) {
+ if (this._currentColor[3] < 250) {
+ type = Neo.Painter.MASKTYPE_NONE;
+ }
+ }
+
+ switch (type) {
+ case Neo.Painter.MASKTYPE_NONE:
+ return;
+
+ case Neo.Painter.MASKTYPE_NORMAL:
+ return (r0 == r &&
+ g0 == g &&
+ b0 == b) ? true : false;
+
+ case Neo.Painter.MASKTYPE_REVERSE:
+ return (r0 != r ||
+ g0 != g ||
+ b0 != b) ? true : false;
+
+ case Neo.Painter.MASKTYPE_ADD:
+ if (a0 > 0) {
+ var sort = this.sortColor(r0, g0, b0);
+ for (var i = 0; i < 3; i++) {
+ var c = sort[i];
+ if (buf8[index + c] < this._currentColor[c]) return true;
+ }
+ return false;
+
+ } else {
+ return false;
+ }
+
+ case Neo.Painter.MASKTYPE_SUB:
+ if (a0 > 0) {
+ var sort = this.sortColor(r0, g0, b0);
+ for (var i = 0; i < 3; i++) {
+ var c = sort[i];
+ if (buf8[index + c] > this._currentColor[c]) return true;
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }
+};
+
+Neo.Painter.prototype.setPoint = function(buf8, bufWidth, x0, y0, left, top, type) {
+ var x = x0 - left;
+ var y = y0 - top;
+
+ switch (type) {
+ case Neo.Painter.LINETYPE_PEN:
+ this.setPenPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BRUSH:
+ this.setBrushPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_TONE:
+ this.setTonePoint(buf8, bufWidth, x, y, x0, y0);
+ break;
+
+ case Neo.Painter.LINETYPE_ERASER:
+ this.setEraserPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BLUR:
+ this.setBlurPoint(buf8, bufWidth, x, y, x0, y0);
+ break;
+
+ case Neo.Painter.LINETYPE_DODGE:
+ this.setDodgePoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BURN:
+ this.setBurnPoint(buf8, bufWidth, x, y);
+ break;
+
+ default:
+ break;
+ }
+};
+
+
+Neo.Painter.prototype.setPenPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_PEN);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var a1x = Math.max(a1, 1.0/255);
+
+ var r = (r1 * a1x + r0 * a0 * (1 - a1x)) / a;
+ var g = (g1 * a1x + g0 * a0 * (1 - a1x)) / a;
+ var b = (b1 * a1x + b0 * a0 * (1 - a1x)) / a;
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBrushPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var a1x = Math.max(a1, 1.0/255);
+
+ var r = (r1 * a1x + r0 * a0) / (a0 + a1x);
+ var g = (g1 * a1x + g0 * a0) / (a0 + a1x);
+ var b = (b1 * a1x + b0 * a0) / (a0 + a1x);
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setTonePoint = function(buf8, width, x, y, x0, y0) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ if (r0%2) { x0++; y0++; } //ãªãœã‹æ¨¡æ§˜ãŒãšã‚Œã‚‹ã®ã§
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var index = (y * width + x) * 4;
+
+ var r = this._currentColor[0];
+ var g = this._currentColor[1];
+ var b = this._currentColor[2];
+ var a = this._currentColor[3];
+
+ var toneData = this.getToneData(a);
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ if (toneData[((y0+i)%4) + (((x0+j)%4) * 4)]) {
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = 255;
+ }
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setEraserPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var index = (y * width + x) * 4;
+ var a = Math.floor(this.alpha * 255);
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var k = (buf8[index + 3] / 255.0) * (1.0 - (a / 255.0));
+
+ buf8[index + 3] -= a / (d * (255.0 - a) / 255.0);
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBlurPoint = function(buf8, width, x, y, x0, y0) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var height = buf8.length / (width * 4);
+
+// var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ var a1 = this.alpha / 12;
+ if (a1 == 0) return;
+ var blur = a1;
+
+ var tmp = new Uint8ClampedArray(buf8.length);
+ for (var i = 0; i < buf8.length; i++) {
+ tmp[i] = buf8[i];
+ }
+
+ var left = x0 - x - r0;
+ var top = y0 - y - r0;
+
+ var xstart = 0, xend = d;
+ var ystart = 0, yend = d;
+ if (xstart > left) xstart = -left;
+ if (ystart > top) ystart = -top;
+ if (xend > this.canvasWidth - left) xend = this.canvasWidth - left;
+ if (yend > this.canvasHeight - top) yend = this.canvasHeight - top;
+
+ for (var j = ystart; j < yend; j++) {
+ var index = (j * width + xstart) * 4;
+ for (var i = xstart; i < xend; i++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var rgba = [0, 0, 0, 0, 0];
+
+ this.addBlur(tmp, index, 1.0 - blur*4, rgba);
+ if (i > xstart) this.addBlur(tmp, index - 4, blur, rgba);
+ if (i < xend - 1) this.addBlur(tmp, index + 4, blur, rgba);
+ if (j > ystart) this.addBlur(tmp, index - width*4, blur, rgba);
+ if (j < yend - 1) this.addBlur(tmp, index + width*4, blur, rgba);
+
+ buf8[index + 0] = Math.round(rgba[0]);
+ buf8[index + 1] = Math.round(rgba[1]);
+ buf8[index + 2] = Math.round(rgba[2]);
+ buf8[index + 3] = Math.round((rgba[3] / rgba[4]) * 255.0);
+ }
+ index += 4;
+ }
+ }
+};
+
+Neo.Painter.prototype.setDodgePoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ if (a1 != 255.0) {
+ var r1 = r0 * 255 / (255 - a1);
+ var g1 = g0 * 255 / (255 - a1);
+ var b1 = b0 * 255 / (255 - a1);
+ } else {
+ var r1 = 255.0;
+ var g1 = 255.0;
+ var b1 = 255.0;
+ }
+
+ var r = Math.ceil(r1);
+ var g = Math.ceil(g1);
+ var b = Math.ceil(b1);
+ var a = a0;
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBurnPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ if (a1 != 255.0) {
+ var r1 = 255 - (255 - r0) * 255 / (255 - a1);
+ var g1 = 255 - (255 - g0) * 255 / (255 - a1);
+ var b1 = 255 - (255 - b0) * 255 / (255 - a1);
+ } else {
+ var r1 = 0;
+ var g1 = 0;
+ var b1 = 0;
+ }
+
+ var r = Math.floor(r1);
+ var g = Math.floor(g1);
+ var b = Math.floor(b1);
+ var a = a0;
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+
+Neo.Painter.prototype.xorPixel = function(buf32, bufWidth, x, y, c) {
+ var index = y * bufWidth + x;
+ if (!c) c = 0xffffff;
+ buf32[index] ^= c;
+};
+
+Neo.Painter.prototype.getBezierPoint = function(t, x0, y0, x1, y1, x2, y2, x3, y3) {
+ var a0 = (1 - t) * (1 - t) * (1 - t);
+ var a1 = (1 - t) * (1 - t) * t * 3;
+ var a2 = (1 - t) * t * t * 3;
+ var a3 = t * t * t;
+
+ var x = x0 * a0 + x1 * a1 + x2 * a2 + x3 * a3;
+ var y = y0 * a0 + y1 * a1 + y2 * a2 + y3 * a3;
+ return [x, y];
+};
+
+var nmax = 1;
+
+Neo.Painter.prototype.drawBezier = function(ctx, x0, y0, x1, y1, x2, y2, x3, y3, type) {
+ var xmax = Math.max(x0, x1, x2, x3);
+ var xmin = Math.min(x0, x1, x2, x3);
+ var ymax = Math.max(y0, y1, y2, y3);
+ var ymin = Math.min(y0, y1, y2, y3);
+ var n = Math.ceil(((xmax - xmin) + (ymax - ymin)) * 2.5);
+
+ if (n > nmax) {
+ n = (n < nmax * 2) ? n : nmax * 2;
+ nmax = n;
+ }
+
+ for (var i = 0; i < n; i++) {
+ var t = i * 1.0 / n;
+ var p = this.getBezierPoint(t, x0, y0, x1, y1, x2, y2, x3, y3);
+ this.drawPoint(ctx, p[0], p[1], type);
+ }
+};
+
+Neo.Painter.prototype.prevLine = null; // 始点ã¾ãŸã¯çµ‚点ãŒ2度プロットã•ã‚Œã‚‹ã“ã¨ãŒã‚ã‚‹ã®ã§
+Neo.Painter.prototype.drawLine = function(ctx, x0, y0, x1, y1, type) {
+ x0 = Math.round(x0);
+ x1 = Math.round(x1);
+ y0 = Math.round(y0);
+ y1 = Math.round(y1);
+ var prev = [x0, y0, x1, y1];
+
+ var width = Math.abs(x1 - x0);
+ var height = Math.abs(y1 - y0);
+ var r = Math.ceil(this.lineWidth / 2);
+
+ var left = ((x0 < x1) ? x0 : x1) - r;
+ var top = ((y0 < y1) ? y0 : y1) - r;
+
+ var imageData = ctx.getImageData(left, top, width + r*2, height + r*2);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var dx = width, sx = x0 < x1 ? 1 : -1;
+ var dy = height, sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+ this.aerr = 0;
+
+ while (true) {
+ if (this.prevLine == null ||
+ !((this.prevLine[0] == x0 && this.prevLine[1] == y0) ||
+ (this.prevLine[2] == x0 && this.prevLine[3] == y0))) {
+ this.setPoint(buf8, imageData.width, x0, y0, left, top, type);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+
+ this.prevLine = prev;
+};
+
+Neo.Painter.prototype.drawPoint = function(ctx, x, y, type) {
+ this.drawLine(ctx, x, y, x, y, type);
+};
+
+Neo.Painter.prototype.xorRect = function(buf32, bufWidth, x, y, width, height, c) {
+ var index = y * bufWidth + x;
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ buf32[index] ^= c;
+ index++;
+ }
+ index += width - bufWidth;
+ }
+};
+
+Neo.Painter.prototype.drawXORRect = function(ctx, x, y, width, height, isFill, c) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+ if (width == 0 || height == 0) return;
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var index = 0;
+ if (!c) c = 0xffffff;
+
+ if (isFill) {
+ this.xorRect(buf32, width, 0, 0, width, height, c);
+
+ } else {
+ for (var i = 0; i < width; i++) { //top
+ buf32[index] = buf32[index] ^= c;
+ index++;
+ }
+ if (height > 1) {
+ index = width;
+ for (var i = 1; i < height; i++) { //left
+ buf32[index] = buf32[index] ^= c;
+ index += width;
+ }
+ if (width > 1) {
+ index = width * 2 - 1;
+ for (var i = 1; i < height - 1; i++) { //right
+ buf32[index] = buf32[index] ^= c;
+ index += width;
+ }
+ index = width * (height - 1) + 1;
+ for (var i = 1; i < width; i++) { // bottom
+ buf32[index] = buf32[index] ^= c;
+ index++;
+ }
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.drawXOREllipse = function(ctx, x, y, width, height, isFill, c) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+ if (width == 0 || height == 0) return;
+ if (!c) c = 0xffffff;
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+
+ var a = width-1, b = height-1, b1 = b&1; /* values of diameter */
+ var dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
+ var err = dx+dy+b1*a*a, e2; /* error of 1.step */
+
+ var x0 = x;
+ var y0 = y;
+ var x1 = x0+a;
+ var y1 = y0+b;
+
+ if (x0 > x1) { x0 = x1; x1 += a; }
+ if (y0 > y1) y0 = y1;
+ y0 += Math.floor((b+1)/2); y1 = y0-b1; /* starting pixel */
+ a *= 8*a; b1 = 8*b*b;
+ var ymin = y0 - 1;
+
+ do {
+ if (isFill) {
+ if (ymin < y0) {
+ this.xorRect(buf32, width, x0-x, y0 - y, x1 - x0, 1, c);
+ if (y0 != y1) {
+ this.xorRect(buf32, width, x0-x, y1 - y, x1 - x0, 1, c);
+ }
+ ymin = y0;
+ }
+ } else {
+ this.xorPixel(buf32, width, x1-x, y0-y, c);
+ if (x0 != x1) {
+ this.xorPixel(buf32, width, x0-x, y0-y, c);
+ }
+ if (y0 != y1) {
+ this.xorPixel(buf32, width, x0-x, y1-y, c);
+ if (x0 != x1) {
+ this.xorPixel(buf32, width, x1-x, y1-y, c);
+ }
+ }
+ }
+ e2 = 2*err;
+ if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
+ if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
+ } while (x0 <= x1);
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.drawXORLine = function(ctx, x0, y0, x1, y1, c) {
+ x0 = Math.round(x0);
+ x1 = Math.round(x1);
+ y0 = Math.round(y0);
+ y1 = Math.round(y1);
+
+ var width = Math.abs(x1 - x0);
+ var height = Math.abs(y1 - y0);
+
+ var left = ((x0 < x1) ? x0 : x1);
+ var top = ((y0 < y1) ? y0 : y1);
+// console.log("left:"+left+" top:"+top+" width:"+width+" height:"+height);
+
+ var imageData = ctx.getImageData(left, top, width + 1, height + 1);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var dx = width, sx = x0 < x1 ? 1 : -1;
+ var dy = height, sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+
+ while (true) {
+ if (this.prevLine == null ||
+ !((this.prevLine[0] == x0 && this.prevLine[1] == y0) ||
+ (this.prevLine[2] == x0 && this.prevLine[3] == y0))) {
+
+ this.xorPixel(buf32, imageData.width, x0 - left, y0 - top, c);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+};
+
+
+Neo.Painter.prototype.eraseRect = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var index = 0;
+
+ var a = 1.0 - this.alpha;
+ if (a != 0) {
+ a = Math.ceil(2.0 / a);
+ } else {
+ a = 255;
+ }
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ if (!this.isMasked(buf8, index)) {
+ buf8[index + 3] -= a;
+ }
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.flipH = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var half = Math.floor(width / 2);
+ for (var j = 0; j < height; j++) {
+ var index = j * width;
+ var index2 = index + (width - 1);
+ for (var i = 0; i < half; i++) {
+ var value = buf32[index + i];
+ buf32[index + i] = buf32[index2 -i];
+ buf32[index2 - i] = value;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.flipV = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var half = Math.floor(height / 2);
+ for (var j = 0; j < half; j++) {
+ var index = j * width;
+ var index2 = (height - 1 - j) * width;
+ for (var i = 0; i < width; i++) {
+ var value = buf32[index + i];
+ buf32[index + i] = buf32[index2 + i];
+ buf32[index2 + i] = value;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.merge = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = [];
+ var buf32 = [];
+ var buf8 = [];
+ for (var i = 0; i < 2; i++) {
+ imageData[i] = this.canvasCtx[i].getImageData(x, y, width, height);
+ buf32[i] = new Uint32Array(imageData[i].data.buffer);
+ buf8[i] = new Uint8ClampedArray(imageData[i].data.buffer);
+ }
+
+ var dst = this.current;
+ var src = (dst == 1) ? 0 : 1;
+ var size = width * height;
+ var index = 0;
+ for (var i = 0; i < size; i++) {
+ var r0 = buf8[0][index + 0];
+ var g0 = buf8[0][index + 1];
+ var b0 = buf8[0][index + 2];
+ var a0 = buf8[0][index + 3] / 255.0;
+ var r1 = buf8[1][index + 0];
+ var g1 = buf8[1][index + 1];
+ var b1 = buf8[1][index + 2];
+ var a1 = buf8[1][index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var r = Math.floor((r1 * a1 + r0 * a0 * (1 - a1)) / a + 0.5);
+ var g = Math.floor((g1 * a1 + g0 * a0 * (1 - a1)) / a + 0.5);
+ var b = Math.floor((b1 * a1 + b0 * a0 * (1 - a1)) / a + 0.5);
+ }
+ buf8[src][index + 0] = 0;
+ buf8[src][index + 1] = 0;
+ buf8[src][index + 2] = 0;
+ buf8[src][index + 3] = 0;
+ buf8[dst][index + 0] = r;
+ buf8[dst][index + 1] = g;
+ buf8[dst][index + 2] = b;
+ buf8[dst][index + 3] = Math.floor(a * 255 + 0.5);
+ index += 4;
+ }
+
+ for (var i = 0; i < 2; i++) {
+ imageData[i].data.set(buf8[i]);
+ this.canvasCtx[i].putImageData(imageData[i], x, y);
+ }
+};
+
+Neo.Painter.prototype.blurRect = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var tmp = new Uint8ClampedArray(buf8.length);
+ for (var i = 0; i < buf8.length; i++) tmp[i] = buf8[i];
+
+ var index = 0;
+ var a1 = this.alpha / 12;
+ var blur = a1;
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ var rgba = [0, 0, 0, 0, 0];
+
+ this.addBlur(tmp, index, 1.0 - blur*4, rgba);
+
+ if (i > 0) this.addBlur(tmp, index - 4, blur, rgba);
+ if (i < width - 1) this.addBlur(tmp, index + 4, blur, rgba);
+ if (j > 0) this.addBlur(tmp, index - width*4, blur, rgba);
+ if (j < height - 1) this.addBlur(tmp, index + width*4, blur, rgba);
+
+ var w = rgba[4];
+ buf8[index + 0] = Math.round(rgba[0]);
+ buf8[index + 1] = Math.round(rgba[1]);
+ buf8[index + 2] = Math.round(rgba[2]);
+ buf8[index + 3] = Math.ceil((rgba[3] / w) * 255.0);
+
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.addBlur = function(buffer, index, a, rgba) {
+ var r0 = rgba[0];
+ var g0 = rgba[1];
+ var b0 = rgba[2];
+ var a0 = rgba[3];
+ var r1 = buffer[index + 0];
+ var g1 = buffer[index + 1];
+ var b1 = buffer[index + 2];
+ var a1 = (buffer[index + 3] / 255.0) * a;
+ rgba[4] += a;
+
+ var a = a0 + a1;
+ if (a > 0) {
+ rgba[0] = (r1 * a1 + r0 * a0) / (a0 + a1);
+ rgba[1] = (g1 * a1 + g0 * a0) / (a0 + a1);
+ rgba[2] = (b1 * a1 + b0 * a0) / (a0 + a1);
+ rgba[3] = a;
+ }
+};
+
+Neo.Painter.prototype.pickColor = function(x, y) {
+ var r = 0xff, g = 0xff, b = 0xff, a;
+
+ x = Math.floor(x);
+ y = Math.floor(y);
+ if (x >= 0 && x < this.canvasWidth &&
+ y >= 0 && y < this.canvasHeight) {
+
+ for (var i = 0; i < 2; i++) {
+ if (this.visible[i]) {
+ var ctx = this.canvasCtx[i];
+ var imageData = ctx.getImageData(x, y, 1, 1);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var a = buf8[3] / 255.0;
+ r = r * (1.0 - a) + buf8[2] * a;
+ g = g * (1.0 - a) + buf8[1] * a;
+ b = b * (1.0 - a) + buf8[0] * a;
+ }
+ }
+ r = Math.max(Math.min(Math.round(r), 255), 0);
+ g = Math.max(Math.min(Math.round(g), 255), 0);
+ b = Math.max(Math.min(Math.round(b), 255), 0);
+ var result = r | g<<8 | b<<16;
+ }
+ this.setColor(result);
+
+
+ if (this.current > 0) {
+ if (a == 0 && (result == 0xffffff || this.getEmulationMode() < 2.16)) {
+ this.setToolByType(Neo.eraserTip.tools[Neo.eraserTip.mode]);
+
+ } else {
+ if (Neo.eraserTip.selected) {
+ this.setToolByType(Neo.penTip.tools[Neo.penTip.mode]);
+ }
+ }
+ }
+};
+
+Neo.Painter.prototype.fillHorizontalLine = function(buf32, x0, x1, y) {
+ var index = y * this.canvasWidth + x0;
+ var fillColor = this.getColor();
+ for (var x = x0; x <= x1; x++) {
+ buf32[index++] = fillColor;
+ }
+};
+
+Neo.Painter.prototype.scanLine = function(x0, x1, y, baseColor, buf32, stack) {
+ var width = this.canvasWidth;
+
+ while (x0 <= x1) {
+ for (; x0 <= x1; x0++) {
+ if (buf32[y * width + x0] == baseColor) break;
+ }
+ if (x1 < x0) break;
+
+ for (; x0 <= x1; x0++) {
+ if (buf32[y * width + x0] != baseColor) break;
+ }
+ stack.push({x:x0 - 1, y: y})
+ }
+};
+
+Neo.Painter.prototype.fill = function(x, y, ctx) {
+ // http://sandbox.serendip.ws/javascript_canvas_scanline_seedfill.html
+ x = Math.round(x);
+ y = Math.round(y);
+
+ var imageData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var width = imageData.width;
+ var stack = [{x: x, y: y}];
+
+ var baseColor = buf32[y * width + x];
+ var fillColor = this.getColor();
+
+ if ((baseColor & 0xffffff00) == 0 ||
+ (baseColor & 0xffffff) != (fillColor & 0xffffff)) {
+ while (stack.length > 0) {
+ var point = stack.pop();
+ var x0 = point.x;
+ var x1 = point.x;
+ var y = point.y;
+
+ if (buf32[y * width + x] == fillColor)
+ break;
+
+ for (; 0 < x0; x0--) {
+ if (buf32[y * width + (x0 - 1)] != baseColor) break;
+ }
+ for (; x1 < this.canvasHeight - 1; x1++) {
+ if (buf32[y * width + (x1 + 1)] != baseColor) break;
+ }
+ this.fillHorizontalLine(buf32, x0, x1, y);
+
+ if (y + 1 < this.canvasHeight) {
+ this.scanLine(x0, x1, y + 1, baseColor, buf32, stack);
+ }
+ if (y - 1 >= 0) {
+ this.scanLine(x0, x1, y - 1, baseColor, buf32, stack);
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.copy = function(x, y, width, height) {
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+
+ var imageData = this.canvasCtx[this.current].getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ this.temp = new Uint32Array(buf32.length);
+ for (var i = 0; i < buf32.length; i++) {
+ this.temp[i] = buf32[i];
+ }
+
+ //tempCanvasã«ä¹—ã›ã‚‹ç”»åƒã‚’作る
+ imageData = this.tempCanvasCtx.getImageData(x, y, width, height);
+ buf32 = new Uint32Array(imageData.data.buffer);
+ buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ for (var i = 0; i < buf32.length; i++) {
+ if (this.temp[i] >> 24) {
+ buf32[i] = this.temp[i] | 0xff000000;
+ } else {
+ buf32[i] = 0xffffffff;
+ }
+ }
+ imageData.data.set(buf8);
+ this.tempCanvasCtx.putImageData(imageData, x, y);
+};
+
+
+Neo.Painter.prototype.paste = function(x, y, width, height) {
+ var ctx = this.canvasCtx[this.current];
+// console.log(this.tempX, this.tempY);
+
+ var imageData = ctx.getImageData(x + this.tempX, y + this.tempY, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ for (var i = 0; i < buf32.length; i++) {
+ buf32[i] = this.temp[i];
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x + this.tempX, y + this.tempY);
+
+ this.temp = null;
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.turn = function(x, y, width, height) {
+ var ctx = this.canvasCtx[this.current];
+
+ // 傾ã‘ツールã®ãƒã‚°ã‚’å†ç¾ã™ã‚‹ãŸã‚一番上ã®ãƒ©ã‚¤ãƒ³ã§å¯¾è±¡é ˜åŸŸã‚’埋ã‚ã‚‹
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var temp = new Uint32Array(buf32.length);
+
+ var index = 0;
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ temp[index] = buf32[index];
+ if (index >= width) {
+ buf32[index] = buf32[index % width];
+ }
+ index++;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+
+ // 90度回転ã•ã›ã¦è²¼ã‚Šä»˜ã‘
+ imageData = ctx.getImageData(x, y, height, width);
+ buf32 = new Uint32Array(imageData.data.buffer);
+ buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ index = 0;
+ for (var j = height - 1; j >= 0; j--) {
+ for (var i = 0; i < width; i++) {
+ buf32[i * height + j] = temp[index++];
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.doFill = function(ctx, x, y, width, height, maskFunc) {
+ if (Math.round(x) != x) console.log("*");
+ if (Math.round(width) != width) console.log("*");
+ if (Math.round(height) != height) console.log("*");
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var index = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.ALPHATYPE_FILL);
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ if (maskFunc && maskFunc.call(this, i, j, width, height)) {
+ //ãªãœã‹åŠ ç®—逆加算ã¯é©ç”¨ã•ã‚Œãªã„
+ if (this.maskType >= Neo.Painter.MASKTYPE_ADD ||
+ !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+
+ if (a > 0) {
+ var a1x = a1;
+ var ax = 1 + a0 * (1 - a1x);
+
+ var r = (r1 + r0 * a0 * (1 - a1x)) / ax;
+ var g = (g1 + g0 * a0 * (1 - a1x)) / ax;
+ var b = (b1 + b0 * a0 * (1 - a1x)) / ax
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+ }
+ }
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.rectFillMask = function(x, y, width, height) {
+ return true;
+};
+
+Neo.Painter.prototype.rectMask = function(x, y, width, height) {
+ var d = this.lineWidth;
+ return (x < d || x > width - 1 - d ||
+ y < d || y > height - 1 - d) ? true : false;
+};
+
+Neo.Painter.prototype.ellipseFillMask = function(x, y, width, height) {
+ var cx = (width - 1) / 2.0;
+ var cy = (height - 1) / 2.0;
+ x = (x - cx) / (cx + 1);
+ y = (y - cy) / (cy + 1);
+
+ return ((x * x) + (y * y) < 1) ? true : false;
+}
+
+Neo.Painter.prototype.ellipseMask = function(x, y, width, height) {
+ var d = this.lineWidth;
+ var cx = (width - 1) / 2.0;
+ var cy = (height - 1) / 2.0;
+
+ if (cx <= d || cy <= d) return this.ellipseFillMask(x, y, width, height);
+
+ var x2 = (x - cx) / (cx - d + 1);
+ var y2 = (y - cy) / (cy - d + 1);
+
+ x = (x - cx) / (cx + 1);
+ y = (y - cy) / (cy + 1);
+
+ if ((x * x) + (y * y) < 1) {
+ if ((x2 * x2) + (y2 * y2) >= 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+-----------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.getDestCanvasPosition = function(mx, my, isClip, isCenter) {
+ var mx = Math.floor(mx); //Math.round(mx);
+ var my = Math.floor(my); //Math.round(my);
+ if (isCenter) {
+ mx += 0.499;
+ my += 0.499;
+ }
+ var x = (mx - this.zoomX + this.destCanvas.width * 0.5 / this.zoom) * this.zoom;
+ var y = (my - this.zoomY + this.destCanvas.height * 0.5 / this.zoom) * this.zoom;
+
+ if (isClip) {
+ x = Math.max(Math.min(x, this.destCanvas.width), 0);
+ y = Math.max(Math.min(y, this.destCanvas.height), 0);
+ }
+ return {x:x, y:y};
+};
+
+Neo.Painter.prototype.isWidget = function(element) {
+ while (1) {
+ if (element == null ||
+ element.id == "canvas" ||
+ element.id == "container") break;
+
+ if (element.id == "tools" ||
+ element.className == "buttonOn" ||
+ element.className == "buttonOff" ||
+ element.className == "inputText") {
+ return true;
+ }
+ element = element.parentNode;
+ }
+ return false;
+};
+
+
+Neo.Painter.prototype.loadImage = function (filename) {
+ console.log("loadImage " + filename);
+ var img = new Image();
+ img.src = filename;
+ img.onload = function() {
+ var oe = Neo.painter;
+ oe.canvasCtx[0].drawImage(img, 0, 0);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ };
+}
+
+Neo.Painter.prototype.loadSession = function (filename) {
+ if (sessionStorage) {
+ var img0 = new Image();
+ img0.src = sessionStorage.getItem('layer0');
+ img0.onload = function() {
+ var img1 = new Image();
+ img1.src = sessionStorage.getItem('layer1');
+ img1.onload = function() {
+ var oe = Neo.painter;
+ oe.canvasCtx[0].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.canvasCtx[1].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.canvasCtx[0].drawImage(img0, 0, 0);
+ oe.canvasCtx[1].drawImage(img1, 0, 0);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ }
+ }
+ }
+};
+
+Neo.Painter.prototype.saveSession = function() {
+ if (sessionStorage) {
+ sessionStorage.setItem('timestamp', +(new Date()));
+ sessionStorage.setItem('layer0', this.canvas[0].toDataURL('image/png'));
+ sessionStorage.setItem('layer1', this.canvas[1].toDataURL('image/png'));
+ }
+};
+
+Neo.Painter.prototype.clearSession = function() {
+ if (sessionStorage) {
+ sessionStorage.removeItem('timestamp');
+ sessionStorage.removeItem('layer0');
+ sessionStorage.removeItem('layer1');
+ }
+};
+
+Neo.Painter.prototype.sortColor = function(r0, g0, b0) {
+ var min = (r0 < g0) ? ((r0 < b0) ? 0 : 2) : ((g0 < b0) ? 1 : 2);
+ var max = (r0 > g0) ? ((r0 > b0) ? 0 : 2) : ((g0 > b0) ? 1 : 2);
+ var mid = (min + max == 1) ? 2 : ((min + max == 2) ? 1 : 0);
+ return [min, mid, max];
+};
+
+Neo.Painter.prototype.doText = function(x, y, string, fontSize) {
+ //テキストæç”»
+ //æç”»ä½ç½®ãŒãšã‚Œã‚‹ã®ã§é©å½“ã«èª¿æ•´
+ var offset = parseInt(fontSize, 10);
+// y -= Math.round((5.0 + offset/8) / this.zoom);
+// x += Math.round(2.0 / this.zoom);
+
+ var ctx = this.tempCanvasCtx;
+ ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ ctx.save();
+ ctx.translate(x, y);
+// ctx.scale(1/this.zoom, 1/this.zoom);
+
+ ctx.font = fontSize + " Arial";
+ ctx.fillStyle = 0;
+ ctx.fillText(string, 0, 0);
+ ctx.restore();
+
+ // é©å½“ã«äºŒå€¤åŒ–
+ var c = this.getColor();
+ var r = c & 0xff;
+ var g = (c & 0xff00) >> 8;
+ var b = (c & 0xff0000) >> 16;
+ var a = Math.round(this.alpha * 255.0);
+
+ var imageData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var length = this.canvasWidth * this.canvasHeight;
+ var index = 0;
+ for (var i = 0; i < length; i++) {
+ if (buf8[index + 3] >= 0x60) {
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ } else {
+ buf8[index + 0] = 0;
+ buf8[index + 1] = 0;
+ buf8[index + 2] = 0;
+ buf8[index + 3] = 0;
+ }
+ index += 4;
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ //キャンãƒã‚¹ã«è²¼ã‚Šä»˜ã‘
+ ctx = this.canvasCtx[this.current];
+ ctx.globalAlpha = 1.0;
+ ctx.drawImage(this.tempCanvas,
+ 0, 0, this.canvasWidth, this.canvasHeight,
+ 0, 0, this.canvasWidth, this.canvasHeight);
+
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.isUIPaused = function() {
+ if (this.drawType == Neo.Painter.DRAWTYPE_BEZIER) {
+ if (this.tool.step && this.tool.step > 0) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Neo.Painter.prototype.getEmulationMode = function() {
+ return parseFloat(Neo.config.neo_emulation_mode || 2.22)
+};
+
+'use strict';
+
+Neo.ToolBase = function() {};
+
+Neo.ToolBase.prototype.startX;
+Neo.ToolBase.prototype.startY;
+Neo.ToolBase.prototype.init = function(oe) {}
+Neo.ToolBase.prototype.kill = function(oe) {}
+Neo.ToolBase.prototype.lineType = Neo.Painter.LINETYPE_NONE;
+
+Neo.ToolBase.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+};
+
+Neo.ToolBase.prototype.upHandler = function(oe) {
+};
+
+Neo.ToolBase.prototype.moveHandler = function(oe) {
+};
+
+Neo.ToolBase.prototype.transformForZoom = function(oe) {
+ var ctx = oe.destCanvasCtx;
+ ctx.translate(oe.canvasWidth * 0.5, oe.canvasHeight * 0.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+};
+
+Neo.ToolBase.prototype.getType = function() {
+ return this.type;
+};
+
+Neo.ToolBase.prototype.getToolButton = function() {
+ switch (this.type) {
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TEXT:
+ return Neo.penTip;
+
+ case Neo.Painter.TOOLTYPE_TONE:
+ case Neo.Painter.TOOLTYPE_BLUR:
+ case Neo.Painter.TOOLTYPE_DODGE:
+ case Neo.Painter.TOOLTYPE_BURN:
+ return Neo.pen2Tip;
+
+ case Neo.Painter.TOOLTYPE_RECT:
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return Neo.effectTip;
+
+ case Neo.Painter.TOOLTYPE_COPY:
+ case Neo.Painter.TOOLTYPE_MERGE:
+ case Neo.Painter.TOOLTYPE_BLURRECT:
+ case Neo.Painter.TOOLTYPE_FLIP_H:
+ case Neo.Painter.TOOLTYPE_FLIP_V:
+ case Neo.Painter.TOOLTYPE_TURN:
+ return Neo.effect2Tip;
+
+ case Neo.Painter.TOOLTYPE_ERASER:
+ case Neo.Painter.TOOLTYPE_ERASEALL:
+ case Neo.Painter.TOOLTYPE_ERASERECT:
+ return Neo.eraserTip;
+
+ case Neo.Painter.TOOLTYPE_FILL:
+ return Neo.fillButton;
+ }
+ return null;
+};
+
+Neo.ToolBase.prototype.getReserve = function() {
+ switch (this.type) {
+ case Neo.Painter.TOOLTYPE_ERASER:
+ return Neo.reserveEraser;
+
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TONE:
+ case Neo.Painter.TOOLTYPE_ERASERECT:
+ case Neo.Painter.TOOLTYPE_ERASEALL:
+ case Neo.Painter.TOOLTYPE_COPY:
+ case Neo.Painter.TOOLTYPE_MERGE:
+ case Neo.Painter.TOOLTYPE_FIP_H:
+ case Neo.Painter.TOOLTYPE_FIP_V:
+
+ case Neo.Painter.TOOLTYPE_DODGE:
+ case Neo.Painter.TOOLTYPE_BURN:
+ case Neo.Painter.TOOLTYPE_BLUR:
+ case Neo.Painter.TOOLTYPE_BLURRECT:
+
+ case Neo.Painter.TOOLTYPE_TEXT:
+ case Neo.Painter.TOOLTYPE_TURN:
+ case Neo.Painter.TOOLTYPE_RECT:
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return Neo.reservePen;
+
+ }
+ return null;
+};
+
+Neo.ToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.updateUI();
+ }
+};
+
+Neo.ToolBase.prototype.saveStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ reserve.size = Neo.painter.lineWidth;
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ DrawToolBase(æ画ツールã®ãƒ™ãƒ¼ã‚¹ã‚¯ãƒ©ã‚¹ï¼‰
+-------------------------------------------------------------------------
+*/
+
+Neo.DrawToolBase = function() {};
+Neo.DrawToolBase.prototype = new Neo.ToolBase();
+Neo.DrawToolBase.prototype.isUpMove = false;
+Neo.DrawToolBase.prototype.step = 0;
+
+Neo.DrawToolBase.prototype.init = function() {
+ this.step = 0;
+ this.isUpMove = true;
+};
+
+Neo.DrawToolBase.prototype.downHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandDownHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineDownHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierDownHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.upHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandUpHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineUpHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierUpHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.moveHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierMoveHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.upMoveHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandUpMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineUpMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierUpMoveHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.keyDownHandler = function(e) {
+ switch (Neo.painter.drawType) {
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierKeyDownHandler(e); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.rollOverHandler= function(oe) {};
+Neo.DrawToolBase.prototype.rollOutHandler= function(oe) {
+ if (!oe.isMouseDown && !oe.isMouseDownRight){
+ oe.tempCanvasCtx.clearRect(0,0,oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.DrawToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+};
+
+
+/* FreeHand (手書ã) */
+
+Neo.DrawToolBase.prototype.freeHandDownHandler = function(oe) {
+ //Register undo first;
+ oe._pushUndo();
+
+ oe.prepareDrawing();
+ this.isUpMove = false;
+ var ctx = oe.canvasCtx[oe.current];
+ if (oe.alpha >= 1 || this.lineType != Neo.Painter.LINETYPE_BRUSH) {
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe.drawLine(ctx, x0, y0, x0, y0, this.lineType);
+ }
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ if (oe.alpha >= 1) {
+ var r = Math.ceil(oe.lineWidth / 2);
+ var rect = oe.getBound(oe.mouseX, oe.mouseY, oe.mouseX, oe.mouseY, r);
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ }
+};
+
+Neo.DrawToolBase.prototype.freeHandUpHandler = function(oe) {
+ oe.tempCanvasCtx.clearRect(0,0,oe.canvasWidth, oe.canvasHeight);
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+// oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+// this.drawCursor(oe);
+ oe.prevLine = null;
+};
+
+Neo.DrawToolBase.prototype.freeHandMoveHandler = function(oe) {
+ var ctx = oe.canvasCtx[oe.current];
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ var x1 = Math.floor(oe.prevMouseX);
+ var y1 = Math.floor(oe.prevMouseY);
+ oe.drawLine(ctx, x0, y0, x1, y1, this.lineType);
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ var r = Math.ceil(oe.lineWidth / 2);
+ var rect = oe.getBound(oe.mouseX, oe.mouseY, oe.prevMouseX, oe.prevMouseY, r);
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+};
+
+Neo.DrawToolBase.prototype.freeHandUpMoveHandler = function(oe) {
+ this.isUpMove = true;
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+ this.drawCursor(oe);
+};
+
+Neo.DrawToolBase.prototype.drawCursor = function(oe) {
+ if (oe.lineWidth <= 8) return;
+ var mx = oe.mouseX;
+ var my = oe.mouseY;
+ var d = oe.lineWidth;
+
+ var x = (mx - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y = (my - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ var r = d * 0.5 * oe.zoom;
+
+ if (!(x > -r &&
+ y > -r &&
+ x < oe.destCanvas.width + r &&
+ y < oe.destCanvas.height + r)) return;
+
+ var ctx = oe.destCanvasCtx;
+ ctx.save();
+ this.transformForZoom(oe)
+
+ var c = (this.type == Neo.Painter.TOOLTYPE_ERASER) ? 0x0000ff : 0xffff7f;
+ oe.drawXOREllipse(ctx, x-r, y-r, r*2, r*2, false, c);
+
+ ctx.restore();
+ oe.cursorRect = oe.getBound(mx, my, mx, my, Math.ceil(d / 2));
+}
+
+
+/* Line (ç›´ç·š) */
+
+Neo.DrawToolBase.prototype.lineDownHandler = function(oe) {
+ this.isUpMove = false;
+ this.startX = Math.floor(oe.mouseX);
+ this.startY = Math.floor(oe.mouseY);
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+Neo.DrawToolBase.prototype.lineUpHandler = function(oe) {
+ if (this.isUpMove == false) {
+ this.isUpMove = true;
+
+ oe._pushUndo();
+ oe.prepareDrawing();
+ var ctx = oe.canvasCtx[oe.current];
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe.drawLine(ctx, x0, y0, this.startX, this.startY, this.lineType);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.DrawToolBase.prototype.lineMoveHandler = function(oe) {
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ this.drawLineCursor(oe);
+};
+
+Neo.DrawToolBase.prototype.lineUpMoveHandler = function(oe) {
+};
+
+Neo.DrawToolBase.prototype.drawLineCursor = function(oe, mx, my) {
+ if (!mx) mx = Math.floor(oe.mouseX);
+ if (!my) my = Math.floor(oe.mouseY);
+ var nx = this.startX;
+ var ny = this.startY;
+ var ctx = oe.destCanvasCtx;
+ ctx.save();
+ this.transformForZoom(oe)
+
+ var x0 = (mx +.499 - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y0 = (my +.499 - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ var x1 = (nx +.499 - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y1 = (ny +.499 - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ oe.drawXORLine(ctx, x0, y0, x1, y1);
+
+ ctx.restore();
+};
+
+
+/* Bezier (BZ曲線) */
+
+Neo.DrawToolBase.prototype.bezierDownHandler = function(oe) {
+ this.isUpMove = false;
+
+ if (this.step == 0) {
+ this.startX = this.x0 = Math.floor(oe.mouseX);
+ this.startY = this.y0 = Math.floor(oe.mouseY);
+ }
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+Neo.DrawToolBase.prototype.bezierUpHandler = function(oe) {
+ if (this.isUpMove == false) {
+ this.isUpMove = true;
+ }
+
+ this.step++;
+ switch (this.step) {
+ case 1:
+ oe.prepareDrawing();
+ this.x3 = Math.floor(oe.mouseX);
+ this.y3 = Math.floor(oe.mouseY);
+ break;
+
+ case 2:
+ this.x1 = Math.floor(oe.mouseX);
+ this.y1 = Math.floor(oe.mouseY);
+ break;
+
+ case 3:
+ this.x2 = Math.floor(oe.mouseX);
+ this.y2 = Math.floor(oe.mouseY);
+
+ oe._pushUndo();
+ oe.drawBezier(oe.canvasCtx[oe.current],
+ this.x0, this.y0, this.x1, this.y1,
+ this.x2, this.y2, this.x3, this.y3, this.lineType);
+
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ this.step = 0;
+ break;
+
+ default:
+ this.step = 0;
+ break;
+ }
+};
+
+Neo.DrawToolBase.prototype.bezierMoveHandler = function(oe) {
+ switch (this.step) {
+ case 0:
+ if (!this.isUpMove) {
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawLineCursor(oe);
+ }
+ break;
+ case 1:
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawBezierCursor1(oe);
+ break;
+
+ case 2:
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawBezierCursor2(oe);
+ break;
+ }
+};
+
+Neo.DrawToolBase.prototype.bezierUpMoveHandler = function(oe) {
+ this.bezierMoveHandler(oe);
+};
+
+Neo.DrawToolBase.prototype.bezierKeyDownHandler = function(e) {
+ if (e.keyCode == 27) { //Escã§ã‚­ãƒ£ãƒ³ã‚»ãƒ«
+ this.step = 0;
+
+ var oe = Neo.painter;
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+
+Neo.DrawToolBase.prototype.drawBezierCursor1 = function(oe) {
+ var ctx = oe.destCanvasCtx;
+// var x = oe.mouseX; //Math.floor(oe.mouseX);
+// var y = oe.mouseY; //Math.floor(oe.mouseY);
+ var stab = oe.getStabilized();
+ var x = Math.floor(stab[0]);
+ var y = Math.floor(stab[1]);
+ var p = oe.getDestCanvasPosition(x, y, false, true);
+ var p0 = oe.getDestCanvasPosition(this.x0, this.y0, false, true);
+ var p3 = oe.getDestCanvasPosition(this.x3, this.y3, false, true);
+
+ // handle
+ oe.drawXORLine(ctx, p0.x, p0.y, p.x, p.y);
+ oe.drawXOREllipse(ctx, p.x - 4, p.y - 4, 8, 8);
+ oe.drawXOREllipse(ctx, p0.x - 4, p0.y - 4, 8, 8);
+
+ // preview
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.drawBezier(oe.tempCanvasCtx,
+ this.x0, this.y0,
+ x, y,
+ x, y,
+ this.x3, this.y3, this.lineType);
+
+ ctx.save();
+ ctx.translate(oe.destCanvas.width*.5, oe.destCanvas.height*.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+ ctx.drawImage(oe.tempCanvas,
+ 0, 0, oe.canvasWidth, oe.canvasHeight,
+ 0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ ctx.restore();
+};
+
+Neo.DrawToolBase.prototype.drawBezierCursor2 = function(oe) {
+ var ctx = oe.destCanvasCtx;
+// var x = oe.mouseX; //Math.floor(oe.mouseX);
+// var y = oe.mouseY; //Math.floor(oe.mouseY);
+ var stab = oe.getStabilized();
+ var x = Math.floor(stab[0]);
+ var y = Math.floor(stab[1]);
+ var p = oe.getDestCanvasPosition(oe.mouseX, oe.mouseY, false, true);
+ var p0 = oe.getDestCanvasPosition(this.x0, this.y0, false, true);
+ var p1 = oe.getDestCanvasPosition(this.x1, this.y1, false, true);
+ var p3 = oe.getDestCanvasPosition(this.x3, this.y3, false, true);
+
+ // handle
+ oe.drawXORLine(ctx, p3.x, p3.y, p.x, p.y);
+ oe.drawXOREllipse(ctx, p.x - 4, p.y - 4, 8, 8);
+ oe.drawXORLine(ctx, p0.x, p0.y, p1.x, p1.y);
+ oe.drawXOREllipse(ctx, p1.x - 4, p1.y - 4, 8, 8);
+ oe.drawXOREllipse(ctx, p0.x - 4, p0.y - 4, 8, 8);
+
+ // preview
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.drawBezier(oe.tempCanvasCtx,
+ this.x0, this.y0,
+ this.x1, this.y1,
+ x, y,
+ this.x3, this.y3, this.lineType);
+
+ ctx.save();
+ ctx.translate(oe.destCanvas.width*.5, oe.destCanvas.height*.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+ ctx.drawImage(oe.tempCanvas,
+ 0, 0, oe.canvasWidth, oe.canvasHeight,
+ 0, 0, oe.canvasWidth, oe.canvasHeight);
+ ctx.restore();
+};
+
+/*
+-------------------------------------------------------------------------
+ Pen(鉛筆)
+-------------------------------------------------------------------------
+*/
+
+Neo.PenTool = function() {};
+Neo.PenTool.prototype = new Neo.DrawToolBase();
+Neo.PenTool.prototype.type = Neo.Painter.TOOLTYPE_PEN;
+Neo.PenTool.prototype.lineType = Neo.Painter.LINETYPE_PEN;
+
+Neo.PenTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+}
+
+/*
+-------------------------------------------------------------------------
+ Brush(水彩)
+-------------------------------------------------------------------------
+*/
+
+Neo.BrushTool = function() {};
+Neo.BrushTool.prototype = new Neo.DrawToolBase();
+Neo.BrushTool.prototype.type = Neo.Painter.TOOLTYPE_BRUSH;
+Neo.BrushTool.prototype.lineType = Neo.Painter.LINETYPE_BRUSH;
+
+Neo.BrushTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = this.getAlpha();
+ Neo.updateUI();
+ }
+};
+
+Neo.BrushTool.prototype.getAlpha = function() {
+ var alpha = 241 - Math.floor(Neo.painter.lineWidth / 2) * 6;
+ return alpha / 255.0;
+};
+
+/*
+-------------------------------------------------------------------------
+ Tone(トーン)
+-------------------------------------------------------------------------
+*/
+
+Neo.ToneTool = function() {};
+Neo.ToneTool.prototype = new Neo.DrawToolBase();
+Neo.ToneTool.prototype.type = Neo.Painter.TOOLTYPE_TONE;
+Neo.ToneTool.prototype.lineType = Neo.Painter.LINETYPE_TONE;
+
+Neo.ToneTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 23 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Eraser(消ã—ペン)
+-------------------------------------------------------------------------
+*/
+
+Neo.EraserTool = function() {};
+Neo.EraserTool.prototype = new Neo.DrawToolBase();
+Neo.EraserTool.prototype.type = Neo.Painter.TOOLTYPE_ERASER;
+Neo.EraserTool.prototype.lineType = Neo.Painter.LINETYPE_ERASER;
+
+
+/*
+-------------------------------------------------------------------------
+ Blur(ã¼ã‹ã—)
+-------------------------------------------------------------------------
+*/
+
+Neo.BlurTool = function() {};
+Neo.BlurTool.prototype = new Neo.DrawToolBase();
+Neo.BlurTool.prototype.type = Neo.Painter.TOOLTYPE_BLUR;
+Neo.BlurTool.prototype.lineType = Neo.Painter.LINETYPE_BLUR;
+
+Neo.BlurTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Dodge(覆ã„焼ã)
+-------------------------------------------------------------------------
+*/
+
+Neo.DodgeTool = function() {};
+Neo.DodgeTool.prototype = new Neo.DrawToolBase();
+Neo.DodgeTool.prototype.type = Neo.Painter.TOOLTYPE_DODGE;
+Neo.DodgeTool.prototype.lineType = Neo.Painter.LINETYPE_DODGE;
+
+Neo.DodgeTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Burn(焼ãè¾¼ã¿ï¼‰
+-------------------------------------------------------------------------
+*/
+
+Neo.BurnTool = function() {};
+Neo.BurnTool.prototype = new Neo.DrawToolBase();
+Neo.BurnTool.prototype.type = Neo.Painter.TOOLTYPE_BURN;
+Neo.BurnTool.prototype.lineType = Neo.Painter.LINETYPE_BURN;
+
+Neo.BurnTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Hand(スクロール)
+-------------------------------------------------------------------------
+*/
+
+Neo.HandTool = function() {};
+Neo.HandTool.prototype = new Neo.ToolBase();
+Neo.HandTool.prototype.type = Neo.Painter.TOOLTYPE_HAND;
+Neo.HandTool.prototype.isUpMove = false;
+Neo.HandTool.prototype.reverse = false;
+
+Neo.HandTool.prototype.downHandler = function(oe) {
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ this.isDrag = true;
+ this.startX = oe.rawMouseX;
+ this.startY = oe.rawMouseY;
+};
+
+Neo.HandTool.prototype.upHandler = function(oe) {
+ this.isDrag = false;
+ oe.popTool();
+};
+
+Neo.HandTool.prototype.moveHandler = function(oe) {
+ if (this.isDrag) {
+ var dx = this.startX - oe.rawMouseX;
+ var dy = this.startY - oe.rawMouseY;
+
+ var ax = oe.destCanvas.width / (oe.canvasWidth * oe.zoom);
+ var ay = oe.destCanvas.height / (oe.canvasHeight * oe.zoom);
+ var barWidth = oe.destCanvas.width * ax;
+ var barHeight = oe.destCanvas.height * ay;
+ var scrollWidthInScreen = oe.destCanvas.width - barWidth - 2;
+ var scrollHeightInScreen = oe.destCanvas.height - barHeight - 2;
+
+ dx *= oe.scrollWidth / scrollWidthInScreen;
+ dy *= oe.scrollHeight / scrollHeightInScreen;
+
+ if (this.reverse) {
+ dx *= -1;
+ dy *= -1;
+ }
+
+ oe.setZoomPosition(oe.zoomX - dx, oe.zoomY - dy);
+
+ this.startX = oe.rawMouseX;
+ this.startY = oe.rawMouseY;
+ }
+};
+
+Neo.HandTool.prototype.rollOutHandler= function(oe) {};
+Neo.HandTool.prototype.upMoveHandler = function(oe) {}
+Neo.HandTool.prototype.rollOverHandler= function(oe) {}
+
+/*
+-------------------------------------------------------------------------
+ Slider(色やサイズã®ã‚¹ãƒ©ã‚¤ãƒ€ã‚’æ“作ã—ã¦ã„る時)
+-------------------------------------------------------------------------
+*/
+
+Neo.SliderTool = function() {};
+Neo.SliderTool.prototype = new Neo.ToolBase();
+Neo.SliderTool.prototype.type = Neo.Painter.TOOLTYPE_SLIDER;
+Neo.SliderTool.prototype.isUpMove = false;
+Neo.SliderTool.prototype.alt = false;
+
+Neo.SliderTool.prototype.downHandler = function(oe) {
+ if (!oe.isShiftDown) this.isDrag = true;
+
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].downHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+};
+
+Neo.SliderTool.prototype.upHandler = function(oe) {
+ this.isDrag = false;
+ oe.popTool();
+
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].upHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+};
+
+Neo.SliderTool.prototype.moveHandler = function(oe) {
+ if (this.isDrag) {
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].moveHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+ }
+};
+
+Neo.SliderTool.prototype.upMoveHandler = function(oe) {}
+Neo.SliderTool.prototype.rollOutHandler= function(oe) {};
+Neo.SliderTool.prototype.rollOverHandler= function(oe) {}
+
+/*
+-------------------------------------------------------------------------
+ Fill(塗り潰ã—)
+-------------------------------------------------------------------------
+*/
+
+Neo.FillTool = function() {};
+Neo.FillTool.prototype = new Neo.ToolBase();
+Neo.FillTool.prototype.type = Neo.Painter.TOOLTYPE_FILL;
+Neo.FillTool.prototype.isUpMove = false;
+
+Neo.FillTool.prototype.downHandler = function(oe) {
+ var x = Math.floor(oe.mouseX);
+ var y = Math.floor(oe.mouseY);
+ oe._pushUndo();
+ oe.fill(x, y, oe.canvasCtx[oe.current]);
+};
+
+Neo.FillTool.prototype.upHandler = function(oe) {
+};
+
+Neo.FillTool.prototype.moveHandler = function(oe) {
+};
+
+Neo.FillTool.prototype.rollOutHandler= function(oe) {};
+Neo.FillTool.prototype.upMoveHandler = function(oe) {}
+Neo.FillTool.prototype.rollOverHandler= function(oe) {}
+
+
+/*
+-------------------------------------------------------------------------
+ EraseAll(全消ã—)
+-------------------------------------------------------------------------
+*/
+
+Neo.EraseAllTool = function() {};
+Neo.EraseAllTool.prototype = new Neo.ToolBase();
+Neo.EraseAllTool.prototype.type = Neo.Painter.TOOLTYPE_ERASEALL;
+Neo.EraseAllTool.prototype.isUpMove = false;
+
+Neo.EraseAllTool.prototype.downHandler = function(oe) {
+ oe._pushUndo();
+
+ oe.prepareDrawing();
+ oe.canvasCtx[oe.current].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+Neo.EraseAllTool.prototype.upHandler = function(oe) {
+};
+
+Neo.EraseAllTool.prototype.moveHandler = function(oe) {
+};
+
+Neo.EraseAllTool.prototype.rollOutHandler= function(oe) {};
+Neo.EraseAllTool.prototype.upMoveHandler = function(oe) {};
+Neo.EraseAllTool.prototype.rollOverHandler= function(oe) {};
+
+
+/*
+-------------------------------------------------------------------------
+ EffectToolBase(エフェックトツールã®ãƒ™ãƒ¼ã‚¹ã‚¯ãƒ©ã‚¹ï¼‰
+-------------------------------------------------------------------------
+*/
+
+Neo.EffectToolBase = function() {};
+Neo.EffectToolBase.prototype = new Neo.ToolBase();
+Neo.EffectToolBase.prototype.isUpMove = false;
+
+Neo.EffectToolBase.prototype.downHandler = function(oe) {
+ this.isUpMove = false;
+
+ this.startX = this.endX = oe.clipMouseX;
+ this.startY = this.endY = oe.clipMouseY;
+};
+
+Neo.EffectToolBase.prototype.upHandler = function(oe) {
+ if (this.isUpMove) return;
+ this.isUpMove = true;
+
+ this.startX = Math.floor(this.startX);
+ this.startY = Math.floor(this.startY);
+ this.endX = Math.floor(this.endX);
+ this.endY = Math.floor(this.endY);
+
+ var x = (this.startX < this.endX) ? this.startX : this.endX;
+ var y = (this.startY < this.endY) ? this.startY : this.endY;
+ var width = Math.abs(this.startX - this.endX) + 1;
+ var height = Math.abs(this.startY - this.endY) + 1;
+ var ctx = oe.canvasCtx[oe.current];
+
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (x + width > oe.canvasWidth) width = oe.canvasWidth - x;
+ if (y + height > oe.canvasHeight) height = oe.canvasHeight - y;
+
+ if (width > 0 && height > 0) {
+ oe._pushUndo();
+ oe.prepareDrawing();
+ this.doEffect(oe, x, y, width, height);
+ }
+
+ if (oe.tool.type != Neo.Painter.TOOLTYPE_PASTE) {
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.EffectToolBase.prototype.moveHandler = function(oe) {
+ this.endX = oe.clipMouseX;
+ this.endY = oe.clipMouseY;
+
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ this.drawCursor(oe);
+};
+
+Neo.EffectToolBase.prototype.rollOutHandler= function(oe) {};
+Neo.EffectToolBase.prototype.upMoveHandler = function(oe) {};
+Neo.EffectToolBase.prototype.rollOverHandler= function(oe) {};
+
+Neo.EffectToolBase.prototype.drawCursor = function(oe) {
+ var ctx = oe.destCanvasCtx;
+
+ ctx.save();
+ this.transformForZoom(oe);
+
+ var start = oe.getDestCanvasPosition(this.startX, this.startY, true);
+ var end = oe.getDestCanvasPosition(this.endX, this.endY, true);
+
+ var x = (start.x < end.x) ? start.x : end.x;
+ var y = (start.y < end.y) ? start.y : end.y;
+ var width = Math.abs(start.x - end.x) + oe.zoom;
+ var height = Math.abs(start.y - end.y) + oe.zoom;
+
+ if (this.isEllipse) {
+ oe.drawXOREllipse(ctx, x, y, width, height, this.isFill);
+
+ } else {
+ oe.drawXORRect(ctx, x, y, width, height, this.isFill);
+ }
+ ctx.restore();
+};
+
+Neo.EffectToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = this.defaultAlpha || 1.0;
+ Neo.updateUI();
+ };
+};
+
+/*
+-------------------------------------------------------------------------
+ EraseRect(消ã—四角)
+-------------------------------------------------------------------------
+*/
+
+Neo.EraseRectTool = function() {};
+Neo.EraseRectTool.prototype = new Neo.EffectToolBase();
+Neo.EraseRectTool.prototype.type = Neo.Painter.TOOLTYPE_ERASERECT;
+
+Neo.EraseRectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.eraseRect(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ FlipH(左å³å転)
+-------------------------------------------------------------------------
+*/
+
+Neo.FlipHTool = function() {};
+Neo.FlipHTool.prototype = new Neo.EffectToolBase();
+Neo.FlipHTool.prototype.type = Neo.Painter.TOOLTYPE_FLIP_H;
+
+Neo.FlipHTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.flipH(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ FlipV(上下å転)
+-------------------------------------------------------------------------
+*/
+
+Neo.FlipVTool = function() {};
+Neo.FlipVTool.prototype = new Neo.EffectToolBase();
+Neo.FlipVTool.prototype.type = Neo.Painter.TOOLTYPE_FLIP_V;
+
+Neo.FlipVTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.flipV(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ DodgeRect(角å–り)
+-------------------------------------------------------------------------
+*/
+
+Neo.BlurRectTool = function() {};
+Neo.BlurRectTool.prototype = new Neo.EffectToolBase();
+Neo.BlurRectTool.prototype.type = Neo.Painter.TOOLTYPE_BLURRECT;
+
+Neo.BlurRectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.blurRect(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+Neo.BlurRectTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 0.5;
+ Neo.updateUI();
+ };
+}
+
+/*
+-------------------------------------------------------------------------
+ Turn(傾ã‘)
+-------------------------------------------------------------------------
+*/
+
+Neo.TurnTool = function() {};
+Neo.TurnTool.prototype = new Neo.EffectToolBase();
+Neo.TurnTool.prototype.type = Neo.Painter.TOOLTYPE_TURN;
+
+Neo.TurnTool.prototype.upHandler = function(oe) {
+ this.isUpMove = true;
+
+ this.startX = Math.floor(this.startX);
+ this.startY = Math.floor(this.startY);
+ this.endX = Math.floor(this.endX);
+ this.endY = Math.floor(this.endY);
+
+ var x = (this.startX < this.endX) ? this.startX : this.endX;
+ var y = (this.startY < this.endY) ? this.startY : this.endY;
+ var width = Math.abs(this.startX - this.endX) + 1;
+ var height = Math.abs(this.startY - this.endY) + 1;
+
+ if (width > 0 && height > 0) {
+ oe._pushUndo();
+ oe.turn(x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Merge(レイヤーçµåˆï¼‰
+-------------------------------------------------------------------------
+*/
+
+Neo.MergeTool = function() {};
+Neo.MergeTool.prototype = new Neo.EffectToolBase();
+Neo.MergeTool.prototype.type = Neo.Painter.TOOLTYPE_MERGE;
+
+Neo.MergeTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.merge(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ Copy(コピー)
+-------------------------------------------------------------------------
+*/
+
+Neo.CopyTool = function() {};
+Neo.CopyTool.prototype = new Neo.EffectToolBase();
+Neo.CopyTool.prototype.type = Neo.Painter.TOOLTYPE_COPY;
+
+Neo.CopyTool.prototype.doEffect = function(oe, x, y, width, height) {
+ oe.copy(x, y, width, height);
+ oe.setToolByType(Neo.Painter.TOOLTYPE_PASTE);
+ oe.tool.x = x;
+ oe.tool.y = y;
+ oe.tool.width = width;
+ oe.tool.height = height;
+};
+
+/*
+-------------------------------------------------------------------------
+ Paste(ペースト)
+-------------------------------------------------------------------------
+*/
+
+Neo.PasteTool = function() {};
+Neo.PasteTool.prototype = new Neo.ToolBase();
+Neo.PasteTool.prototype.type = Neo.Painter.TOOLTYPE_PASTE;
+
+Neo.PasteTool.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+ this.drawCursor(oe);
+};
+
+Neo.PasteTool.prototype.upHandler = function(oe) {
+ oe._pushUndo();
+
+ oe.paste(this.x, this.y, this.width, this.height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ oe.setToolByType(Neo.Painter.TOOLTYPE_COPY);
+};
+
+Neo.PasteTool.prototype.moveHandler = function(oe) {
+ var dx = Math.floor(oe.mouseX - this.startX);
+ var dy = Math.floor(oe.mouseY - this.startY);
+ oe.tempX = dx;
+ oe.tempY = dy;
+
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+// this.drawCursor(oe);
+};
+
+Neo.PasteTool.prototype.keyDownHandler = function(e) {
+ if (e.keyCode == 27) { //Escã§ã‚­ãƒ£ãƒ³ã‚»ãƒ«
+ var oe = Neo.painter;
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe.setToolByType(Neo.Painter.TOOLTYPE_COPY);
+ }
+};
+
+Neo.PasteTool.prototype.drawCursor = function(oe) {
+ var ctx = oe.destCanvasCtx;
+
+ ctx.save();
+ this.transformForZoom(oe);
+
+ var start = oe.getDestCanvasPosition(this.x, this.y, true);
+ var end = oe.getDestCanvasPosition(this.x + this.width, this.y + this.height, true);
+
+ var x = start.x + oe.tempX * oe.zoom;
+ var y = start.y + oe.tempY * oe.zoom;
+ var width = Math.abs(start.x - end.x);
+ var height = Math.abs(start.y - end.y);
+ oe.drawXORRect(ctx, x, y, width, height);
+ ctx.restore();
+};
+
+/*
+-------------------------------------------------------------------------
+ Rect(線四角)
+-------------------------------------------------------------------------
+*/
+
+Neo.RectTool = function() {};
+Neo.RectTool.prototype = new Neo.EffectToolBase();
+Neo.RectTool.prototype.type = Neo.Painter.TOOLTYPE_RECT;
+
+Neo.RectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.rectMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ RectFill(四角)
+-------------------------------------------------------------------------
+*/
+
+Neo.RectFillTool = function() {};
+Neo.RectFillTool.prototype = new Neo.EffectToolBase();
+Neo.RectFillTool.prototype.type = Neo.Painter.TOOLTYPE_RECTFILL;
+
+Neo.RectFillTool.prototype.isFill = true;
+Neo.RectFillTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.rectFillMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ Ellipse(線楕円)
+-------------------------------------------------------------------------
+*/
+
+Neo.EllipseTool = function() {};
+Neo.EllipseTool.prototype = new Neo.EffectToolBase();
+Neo.EllipseTool.prototype.type = Neo.Painter.TOOLTYPE_ELLIPSE;
+Neo.EllipseTool.prototype.isEllipse = true;
+Neo.EllipseTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.ellipseMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ EllipseFill(楕円)
+-------------------------------------------------------------------------
+*/
+
+Neo.EllipseFillTool = function() {};
+Neo.EllipseFillTool.prototype = new Neo.EffectToolBase();
+Neo.EllipseFillTool.prototype.type = Neo.Painter.TOOLTYPE_ELLIPSEFILL;
+Neo.EllipseFillTool.prototype.isEllipse = true;
+Neo.EllipseFillTool.prototype.isFill = true;
+Neo.EllipseFillTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.ellipseFillMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+-------------------------------------------------------------------------
+ Text(テキスト)
+-------------------------------------------------------------------------
+*/
+
+Neo.TextTool = function() {};
+Neo.TextTool.prototype = new Neo.ToolBase();
+Neo.TextTool.prototype.type = Neo.Painter.TOOLTYPE_TEXT;
+Neo.TextTool.prototype.isUpMove = false;
+
+Neo.TextTool.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+
+ if (Neo.painter.inputText) {
+ Neo.painter.updateInputText();
+
+ var rect = oe.container.getBoundingClientRect();
+ var text = Neo.painter.inputText;
+ var x = oe.rawMouseX - rect.left - 5;
+ var y = oe.rawMouseY - rect.top - 5;
+
+ text.style.left = x + "px";
+ text.style.top = y + "px";
+ text.style.display = "block";
+ text.focus();
+ }
+};
+
+Neo.TextTool.prototype.upHandler = function(oe) {
+};
+
+Neo.TextTool.prototype.moveHandler = function(oe) {};
+Neo.TextTool.prototype.upMoveHandler = function(oe) {};
+Neo.TextTool.prototype.rollOverHandler= function(oe) {};
+Neo.TextTool.prototype.rollOutHandler= function(oe) {};
+
+Neo.TextTool.prototype.keyDownHandler = function(e) {
+ if (e.keyCode == 13) { // Returnã§ç¢ºå®š
+ e.preventDefault();
+
+ var oe = Neo.painter;
+ var text = oe.inputText;
+ if (text) {
+ oe._pushUndo();
+ this.drawText(oe);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ text.style.display = "none";
+ text.blur();
+ }
+ }
+};
+
+Neo.TextTool.prototype.kill = function(oe) {
+ Neo.painter.hideInputText();
+};
+
+Neo.TextTool.prototype.drawText = function(oe) {
+ var text = oe.inputText;
+
+ // unescape entities
+ //var tmp = document.createElement("textarea");
+ //tmp.innerHTML = text.innerHTML;
+ //var string = tmp.value;
+
+ var string = text.textContent || text.innerText;
+
+ if (string.length <= 0) return;
+ oe.doText(this.startX, this.startY, string, text.style.fontSize);
+};
+
+Neo.TextTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+};
+
+/*
+-------------------------------------------------------------------------
+ Dummy(何もã—ãªã„時)
+-------------------------------------------------------------------------
+*/
+
+Neo.DummyTool = function() {};
+Neo.DummyTool.prototype = new Neo.ToolBase();
+Neo.DummyTool.prototype.type = Neo.Painter.TOOLTYPE_NONE;
+Neo.DummyTool.prototype.isUpMove = false;
+
+Neo.DummyTool.prototype.downHandler = function(oe) {
+};
+
+Neo.DummyTool.prototype.upHandler = function(oe) {
+ oe.popTool();
+};
+
+Neo.DummyTool.prototype.moveHandler = function(oe) {};
+Neo.DummyTool.prototype.upMoveHandler = function(oe) {}
+Neo.DummyTool.prototype.rollOverHandler= function(oe) {}
+Neo.DummyTool.prototype.rollOutHandler= function(oe) {}
+
+'use strict';
+
+Neo.CommandBase = function() {
+};
+Neo.CommandBase.prototype.data;
+Neo.CommandBase.prototype.execute = function() {}
+
+
+/*
+---------------------------------------------------
+ ZOOM
+---------------------------------------------------
+*/
+Neo.ZoomPlusCommand = function(data) {this.data = data};
+Neo.ZoomPlusCommand.prototype = new Neo.CommandBase();
+Neo.ZoomPlusCommand.prototype.execute = function() {
+ if (this.data.zoom < 12) {
+ this.data.setZoom(this.data.zoom + 1);
+ }
+ Neo.resizeCanvas();
+ Neo.painter.updateDestCanvas();
+};
+
+Neo.ZoomMinusCommand = function(data) {this.data = data};
+Neo.ZoomMinusCommand.prototype = new Neo.CommandBase();
+Neo.ZoomMinusCommand.prototype.execute = function() {
+ if (this.data.zoom >= 2) {
+ this.data.setZoom(this.data.zoom - 1);
+ }
+ Neo.resizeCanvas();
+ Neo.painter.updateDestCanvas();
+};
+
+/*
+---------------------------------------------------
+ UNDO
+---------------------------------------------------
+*/
+Neo.UndoCommand = function(data) {this.data = data};
+Neo.UndoCommand.prototype = new Neo.CommandBase();
+Neo.UndoCommand.prototype.execute = function() {
+ this.data.undo();
+};
+
+Neo.RedoCommand = function(data) {this.data = data};
+Neo.RedoCommand.prototype = new Neo.CommandBase();
+Neo.RedoCommand.prototype.execute = function() {
+ this.data.redo();
+};
+
+
+/*
+---------------------------------------------------
+---------------------------------------------------
+*/
+
+
+
+Neo.WindowCommand = function(data) {this.data = data};
+Neo.WindowCommand.prototype = new Neo.CommandBase();
+Neo.WindowCommand.prototype.execute = function() {
+ if (Neo.fullScreen) {
+ //if (confirm("¿Vista página?")) {
+ Neo.fullScreen = false;
+ Neo.updateWindow();
+ //}
+ } else {
+ //if (confirm("¿Vista ventana?")) {
+ Neo.fullScreen = true;
+ Neo.updateWindow();
+ //}
+ }
+};
+
+Neo.SubmitCommand = function(data) {this.data = data};
+Neo.SubmitCommand.prototype = new Neo.CommandBase();
+Neo.SubmitCommand.prototype.execute = function() {
+ var board = location.href.replace(/[^/]*$/, '');
+ console.log("submit: " + board);
+ this.data.submit(board);
+};
+
+Neo.CopyrightCommand = function(data) {this.data = data};
+Neo.CopyrightCommand.prototype = new Neo.CommandBase();
+Neo.CopyrightCommand.prototype.execute = function() {
+// var url = "http://hp.vector.co.jp/authors/VA016309/";
+// if (confirm(url + "\nã—ãƒã¡ã‚ƒã‚“ã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã—ã¾ã™ã‹ï¼Ÿ")) {
+ var url = "http://github.com/funige/neo/";
+ if (confirm("PaintBBS NEOã¯ã€ãŠçµµæãã—ãƒæŽ²ç¤ºæ¿ PaintBBS (©2000-2004 ã—ãƒã¡ã‚ƒã‚“) ã‚’html5化ã™ã‚‹ãƒ—ロジェクトã§ã™ã€‚\n\nPaintBBS NEOã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã—ã¾ã™ã‹ï¼Ÿ" + "\n")) {
+ Neo.openURL(url);
+ }
+};
+
+'use strict';
+
+/*
+-------------------------------------------------------------------------
+ Button
+-------------------------------------------------------------------------
+*/
+
+Neo.Button = function() {};
+Neo.Button.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.selected = false;
+ this.isMouseDown = false;
+
+ var ref = this;
+ if (window.PointerEvent) {
+ this.element.onpointerdown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onpointerup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onpointerover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onpointerout = function(e) { ref._mouseOutHandler(e); }
+
+ } else {
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ }
+ this.element.className = (!this.params.type == 'fill') ? "button" : "buttonOff";
+
+ return this;
+};
+
+Neo.Button.prototype._mouseDownHandler = function(e) {
+ if (Neo.painter.isUIPaused()) return;
+ this.isMouseDown = true;
+
+ if ((this.params.type == "fill") && (this.selected == false)) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.setSelected((this.selected) ? false : true);
+ }
+ Neo.painter.setToolByType(Neo.Painter.TOOLTYPE_FILL);
+ }
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+Neo.Button.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+Neo.Button.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.Button.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.Button.prototype.setSelected = function(selected) {
+ if (selected) {
+ this.element.className = "buttonOn";
+ } else {
+ this.element.className = "buttonOff";
+ }
+ this.selected = selected;
+};
+
+Neo.Button.prototype.update = function() {
+};
+
+/*
+-------------------------------------------------------------------------
+ ColorTip
+-------------------------------------------------------------------------
+*/
+
+Neo.colorTips = [];
+
+Neo.ColorTip = function() {};
+Neo.ColorTip.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ this.selected = (this.name == "color1") ? true : false;
+ this.isMouseDown = false;
+
+ var ref = this;
+ if (window.PointerEvent) {
+ this.element.onpointerdown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onpointerup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onpointerover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onpointerout = function(e) { ref._mouseOutHandler(e); }
+
+ } else {
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ }
+ this.element.className = "colorTipOff";
+
+ var index = parseInt(this.name.slice(5)) - 1;
+ this.element.style.left = (index % 2) ? "0px" : "26px";
+ this.element.style.top = Math.floor(index / 2) * 21 + "px";
+
+ // base64 ColorTip.png
+ this.element.innerHTML = "<img style='max-width:44px;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAASCAYAAAAg9DzcAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAANklEQVRIx+3OAQkAMADDsO3+Pe8qCj+0Akq6bQFqS2wTCpwE+R4IiyVYsGDBggULfirBgn8HX7BzCRwDx1QeAAAAAElFTkSuQmCC' />"
+
+ this.setColor(Neo.config.colors[params.index - 1]);
+
+ this.setSelected(this.selected);
+ Neo.colorTips.push(this);
+};
+
+Neo.ColorTip.prototype._mouseDownHandler = function(e) {
+ if (Neo.painter.isUIPaused()) return;
+ this.isMouseDown = true;
+
+ for (var i = 0; i < Neo.colorTips.length; i++) {
+ var colorTip = Neo.colorTips[i];
+ if (this == colorTip) {
+ if (e.shiftKey) {
+ this.setColor(Neo.config.colors[this.params.index - 1]);
+ } else if (e.button == 2 || e.ctrlKey || e.altKey) {
+ this.setColor(Neo.painter.foregroundColor);
+ }
+ }
+ colorTip.setSelected(this == colorTip) ? true : false;
+ }
+ Neo.painter.setColor(this.color);
+ Neo.updateUIColor(true, false);
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+Neo.ColorTip.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+Neo.ColorTip.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.ColorTip.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.ColorTip.prototype.setSelected = function(selected) {
+ if (selected) {
+ this.element.className = "colorTipOn";
+ } else {
+ this.element.className = "colorTipOff";
+ }
+ this.selected = selected;
+};
+
+Neo.ColorTip.prototype.setColor = function(color) {
+ this.color = color;
+ this.element.style.backgroundColor = color;
+};
+
+Neo.ColorTip.getCurrent = function() {
+ for (var i = 0; i < Neo.colorTips.length; i++) {
+ var colorTip = Neo.colorTips[i];
+ if (colorTip.selected) return colorTip;
+ }
+ return null;
+};
+
+/*
+-------------------------------------------------------------------------
+ ToolTip
+-------------------------------------------------------------------------
+*/
+
+Neo.toolTips = [];
+Neo.toolButtons = [];
+
+Neo.ToolTip = function() {};
+
+Neo.ToolTip.prototype.prevMode = -1;
+
+Neo.ToolTip.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.params.type = this.element.id;
+ this.name = name;
+ this.mode = 0;
+
+ this.isMouseDown = false;
+
+ var ref = this;
+ if (window.PointerEvent) {
+ this.element.onpointerdown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onpointerup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onpointerover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onpointerout = function(e) { ref._mouseOutHandler(e); }
+
+ } else {
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ }
+ this.selected = (this.params.type == "pen") ? true : false;
+ this.setSelected(this.selected);
+
+ this.element.innerHTML = "<canvas width=46 height=18></canvas><div class='label'></div>";
+ this.canvas = this.element.getElementsByTagName('canvas')[0];
+ this.label = this.element.getElementsByTagName('div')[0];
+
+ this.update();
+ return this;
+};
+
+Neo.ToolTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ if (this.isTool) {
+ if (this.selected == false) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.setSelected((this == toolTip) ? true : false);
+ }
+
+ } else {
+ var length = this.toolStrings.length;
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ this.mode--;
+ if (this.mode < 0) this.mode = length - 1;
+ } else {
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ }
+ }
+ Neo.painter.setToolByType(this.tools[this.mode]);
+ this.update();
+ }
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+
+Neo.ToolTip.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+
+Neo.ToolTip.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.ToolTip.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.ToolTip.prototype.setSelected = function(selected) {
+ if (this.fixed) {
+ this.element.className = "toolTipFixed";
+
+ } else {
+ if (selected) {
+ this.element.className = "toolTipOn";
+ } else {
+ this.element.className = "toolTipOff";
+ }
+ }
+ this.selected = selected;
+};
+
+Neo.ToolTip.prototype.update = function() {};
+
+Neo.ToolTip.prototype.draw = function(c) {
+ if (this.hasTintImage) {
+ if (typeof c != "string") c = Neo.painter.getColorString(c);
+ var ctx = this.canvas.getContext("2d");
+
+ if (this.prevMode != this.mode) {
+ this.prevMode = this.mode;
+
+ var img = new Image();
+ img.src = this.toolIcons[this.mode];
+ img.onload = function() {
+ var ref = this;
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ this.drawTintImage(ctx, img, c, 0, 0);
+ }.bind(this);
+
+ } else {
+ this.tintImage(ctx, c);
+ }
+ }
+};
+
+Neo.ToolTip.prototype.drawTintImage = function(ctx, img, c, x, y) {
+ ctx.drawImage(img, x, y);
+ this.tintImage(ctx, c);
+};
+
+Neo.ToolTip.prototype.tintImage = function(ctx, c) {
+ c = (Neo.painter.getColor(c) & 0xffffff);
+
+ var imageData = ctx.getImageData(0, 0, 46, 18);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ for (var i = 0; i < buf32.length; i++) {
+ var a = buf32[i] & 0xff000000;
+ if (a) {
+ buf32[i] = buf32[i] & a | c;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+};
+
+Neo.ToolTip.bezier = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAT0lEQVRIx+3SQQoAIAhE0en+h7ZVEEKBZrX5b5sjKknAkRYpNslaMLPq44ZI9wwHs0vMQ/v87u0Kk8xfsaI242jbMdjPi5Y0r/zTAAAAD3UOjRf9jcO4sgAAAABJRU5ErkJggg==";
+Neo.ToolTip.blur = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAASUlEQVRIx+3VMQ4AIAgEQeD/f8bWWBnJYUh2SgtgK82G8/MhzVKwxOtTLgIUx6tDout4laiPIICA0Qj4bXxAy0+8LZP9yACAJwsqkggS55eiZgAAAABJRU5ErkJggg==";
+Neo.ToolTip.blurrect = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAX0lEQVRIx+2XQQ4AEAwEt+I7/v+8Org6lJKt6NzLjjYE8DAKtLpYoDeCCCC7tYUd3ru2qQOzDTyndhJzB6KSAmxSgM0fAlGuzBnmlziqxB8jFJkUYJMCbAQYPxt2kF06fvYKgjPBO/IAAAAASUVORK5CYII=";
+Neo.ToolTip.brush = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAQUlEQVRIx2NgGOKAEcb4z8CweRA4xpdUPSxofJ8BdP8WcjQxDaCDqQLQY4CsUBgFo2AUjIJRMApGwSgYBaNgZAIA0CoDwDbZu8oAAAAASUVORK5CYII=";
+Neo.ToolTip.burn = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAPklEQVRIx+3PMRIAMAQAQbzM0/0sKZPeiDG57TQ4keH0Htx9VR+MCM1vOezl8xUsv4IAAkYjoBsB3QgAgL9tYXgF19rh9yoAAAAASUVORK5CYII=";
+Neo.ToolTip.copy = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAW0lEQVRIx+2XMQoAIAwDU/E7/v95Orh2KMUSC7m5Qs6AUqAxG1gzOLirwxhgmXOjOlg1oQY8sjf2mvYNSICNBNhIgE3oH/jlzfdo34AE2EiATXsBA+5mww6S5QASDwSGMt8ouwAAAABJRU5ErkJggg==";
+Neo.ToolTip.copy2 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAN0lEQVRIx+3PwQkAIBADwdPKt3MtQVCOPNz5B7JV0pNxOwRW9zng+G92n+hmQJoBaQakGSBJf9tyBgQUV/fKCAAAAABJRU5ErkJggg==";
+Neo.ToolTip.ellipse = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAATklEQVRIx+2VMQ4AIAgD6/8fjbOJi1LFmt4OPQ0KIE7LNgggCBLbHkuFM9lM+Om+QwDjpksyb4tT86vlvzgEbYxefQPyv5D8HjDGGGOk6b3jJ+lYubd8AAAAAElFTkSuQmCC";
+Neo.ToolTip.ellipsefill = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAVUlEQVRIx+2VURIAEAgFc/9D5waSHpV5+43ZHRMizRnRA1REARLHHq6NCFl01Nail+LeEDMgU34nYhlQQd6K+PsGKkSEZyArBPoK3Y6K/AOEEEJIayZHbhIKjkZrFwAAAABJRU5ErkJggg==";
+Neo.ToolTip.eraser = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAABQElEQVRIx+1WQY7CMAwcI37Cad+yXOgH4Gu8gAt9CtrDirfMHjZJbbcktVSpQnROSeMkY3vsFHhzSG3xfLpz/JVmG0mIqDkIMcc6+7Kejx6fdb0dq7w09rVFkrjejrMOunQ9vg7f/5QEIAd6E1Eo38WF8fF7n8sdALCrLerIzoFI4sI0Vtv1SYZ8CVbeF7tzF7JugIkVkxOauc6CIe8842S+XmMfsq7TN9LRTngZmTmVD4SrnzYaGYhFoxCWgajXuMjYGTuJ3dlwIBIN3U0cUVqLXCs5E7YeVsvAYJul5HWeLUhL3EpstQwooqoOTEHDOebpMn7ngkUsg3RotU8X1MkuVDrYohkIupC0YArX6T+PfX3kcbQLNV/iCKi6EB3xqXdAZ0JKthZ8B0QEl673NIEX/0I/z36Rf6ENGzZ8EP4A8Lp+9e9VWC4AAAAASUVORK5CYII=";
+Neo.ToolTip.flip = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAZklEQVRIx+2XQQoAIAgE1+g7/f95degWHSyTTXDOhTsSiUBgOtCq8mD3DiOA3NxTCVgKaLA0qHiFOsHSnC8ELKQAmxRgE15APQfWv9pzLjwX+CXsjvBPKAXYpACb8AICzM2GHeSWAfVOCIiJuQ9tAAAAAElFTkSuQmCC";
+Neo.ToolTip.freehand = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAdUlEQVRIx+2WUQrAMAhD3dj9r+y+VoSyLhYDynzQv1qiJlCR4hzeAhVRsiC3Jkj0c5hN7Lx7IQ9SphLE1ICdwko420purEWQuywN3pqxgcw2+WwAtU1GzoqiLZNwZBvMAIcO8y3YKUO8mkbmjPzjK9E0TUPjBoeyLAS0usjLAAAAAElFTkSuQmCC";
+Neo.ToolTip.line = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAU0lEQVRIx+2UQQ4AIAjD8P+PxivRGDQC47C+oN1hIgTLQAt4qIga2c23XYAVPkm3CVhlb4ShAa/rQgMi1i0NyFg3LaBq3bAA1LpfAd7/EkIIIR2YXFYSCpWS8w8AAAAASUVORK5CYII=";
+Neo.ToolTip.merge = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAW0lEQVRIx+2XQQrAQAgDx9Lv9JF9+e6h54IINlgyZ4UMOYgwmAXXmRxc3WECorJ3dAfrJtXAC7c6PPygAQuosYAaC6hJ3YHqlfyC8Q1YQI0F1IwXCHg+G3WQKhvwgwUFmFyYbwAAAABJRU5ErkJggg==";
+Neo.ToolTip.pen = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAK0lEQVRIx+3OsQkAMAwDQXn/oe3WfSAEctd9I5TA32pHJ/3AoTpfAQCAGwaa5AICJLKWSQAAAABJRU5ErkJggg==";
+Neo.ToolTip.rect = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAQElEQVRIx+3TMQ4AIAhD0WK8/5VxdcIYY8rw3wok7YAEr6iGKaU74BY0ro+6FKhyDHe4VxRwm6eFLn8AAADwwQIwTQgGo9ZMywAAAABJRU5ErkJggg==";
+Neo.ToolTip.rectfill = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAANElEQVRIx+3PIQ4AIBADwcL//3xYBMEgLiQztmab0GvcxkqqO3ALPbbO7rBXDnRzAADgYwvqDwIMJlGb5QAAAABJRU5ErkJggg==";
+Neo.ToolTip.text = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAcUlEQVRIx+2VwQ7AIAhDy7L//2V2WmIYg+ky2KEv8aCCqYQqQMgrJNpUQMXEKKDmAPHyspgSrBBvLZu3cQqZEdwhfusq0KdkVR5HlFfBvpI0mtIzeusFot7vFPqYuzZYMXUFlzc+qrIn7tf/ACGEkIwDlEQ94YZjzcgAAAAASUVORK5CYII=";
+Neo.ToolTip.tone = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAO0lEQVRIx+3PIQ4AMAgEwaP//zNVVZUELiQ7CgWstFy8IaVsPhT1Lb/T+fQEAtwIcCPAjQC39QEAgJIL6DQCFhAqsRkAAAAASUVORK5CYII=";
+
+/*
+-------------------------------------------------------------------------
+ PenTip
+-------------------------------------------------------------------------
+*/
+
+Neo.penTip;
+
+Neo.PenTip = function() {};
+Neo.PenTip.prototype = new Neo.ToolTip();
+
+Neo.PenTip.prototype.toolStrings = ["Lapiz", "Acuarela", "Texto"];
+Neo.PenTip.prototype.tools = [Neo.Painter.TOOLTYPE_PEN,
+ Neo.Painter.TOOLTYPE_BRUSH,
+ Neo.Painter.TOOLTYPE_TEXT];
+
+Neo.PenTip.prototype.hasTintImage = true;
+Neo.PenTip.prototype.toolIcons = [Neo.ToolTip.pen,
+ Neo.ToolTip.brush,
+ Neo.ToolTip.text];
+
+Neo.PenTip.prototype.init = function(name, params) {
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.PenTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ if (this.label) {
+ this.label.innerHTML = this.toolStrings[this.mode];
+ }
+};
+
+/*
+-------------------------------------------------------------------------
+ Pen2Tip
+-------------------------------------------------------------------------
+*/
+
+Neo.pen2Tip;
+
+Neo.Pen2Tip = function() {};
+Neo.Pen2Tip.prototype = new Neo.ToolTip();
+
+Neo.Pen2Tip.prototype.toolStrings = ["Tono",
+ "Gradacion",
+ "Sobreexp.",
+ "Quemar"];
+Neo.Pen2Tip.prototype.tools = [Neo.Painter.TOOLTYPE_TONE,
+ Neo.Painter.TOOLTYPE_BLUR,
+ Neo.Painter.TOOLTYPE_DODGE,
+ Neo.Painter.TOOLTYPE_BURN];
+
+Neo.Pen2Tip.prototype.hasTintImage = true;
+Neo.Pen2Tip.prototype.toolIcons = [Neo.ToolTip.tone,
+ Neo.ToolTip.blur,
+ Neo.ToolTip.burn,
+ Neo.ToolTip.burn];
+
+Neo.Pen2Tip.prototype.init = function(name, params) {
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.Pen2Tip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ switch (this.tools[this.mode]) {
+ case Neo.Painter.TOOLTYPE_TONE:
+ this.drawTone(Neo.painter.foregroundColor);
+ break;
+
+ case Neo.Painter.TOOLTYPE_DODGE:
+ this.draw(0xffc0c0c0);
+ break;
+
+ case Neo.Painter.TOOLTYPE_BURN:
+ this.draw(0xff404040);
+ break;
+
+ default:
+ this.draw(Neo.painter.foregroundColor);
+ break;
+ }
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.Pen2Tip.prototype.drawTone = function() {
+ var ctx = this.canvas.getContext("2d");
+
+ var imageData = ctx.getImageData(0, 0, 46, 18);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var c = Neo.painter.getColor() | 0xff000000;
+ var a = Math.floor(Neo.painter.alpha * 255);
+ var toneData = Neo.painter.getToneData(a);
+
+ for (var j = 0; j < 18; j++) {
+ for (var i = 0; i < 46; i++) {
+ if (j >= 1 && j < 12 &&
+ i >= 2 && i < 26 &&
+ toneData[(i%4) + (j%4) * 4]) {
+ buf32[j * 46 + i] = c;
+
+ } else {
+ buf32[j * 46 + i] = 0;
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ this.prevMode = this.mode;
+};
+
+
+/*
+-------------------------------------------------------------------------
+ EraserTip
+-------------------------------------------------------------------------
+*/
+
+Neo.eraserTip;
+
+Neo.EraserTip = function() {};
+Neo.EraserTip.prototype = new Neo.ToolTip();
+
+Neo.EraserTip.prototype.toolStrings = ["Goma", "Goma", "Borrar"];
+Neo.EraserTip.prototype.tools = [Neo.Painter.TOOLTYPE_ERASER,
+ Neo.Painter.TOOLTYPE_ERASERECT,
+ Neo.Painter.TOOLTYPE_ERASEALL];
+
+Neo.EraserTip.prototype.init = function(name, params) {
+ this.drawOnce = false;
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.EraserTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ if (this.drawOnce == false) {
+ this.draw();
+ this.drawOnce = true;
+ }
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.EraserTip.prototype.draw = function() {
+ var ctx = this.canvas.getContext("2d");
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ var img = new Image();
+
+ img.src = Neo.ToolTip.eraser;
+ img.onload = function() {
+ ctx.drawImage(img, 0, 0);
+ };
+};
+
+/*
+-------------------------------------------------------------------------
+ EffectTip
+-------------------------------------------------------------------------
+*/
+
+Neo.effectTip;
+
+Neo.EffectTip = function() {};
+Neo.EffectTip.prototype = new Neo.ToolTip();
+
+Neo.EffectTip.prototype.toolStrings = ["Cuadrado", "Cuadrado", "Circulo", "Circulo"];
+Neo.EffectTip.prototype.tools = [Neo.Painter.TOOLTYPE_RECTFILL,
+ Neo.Painter.TOOLTYPE_RECT,
+ Neo.Painter.TOOLTYPE_ELLIPSEFILL,
+ Neo.Painter.TOOLTYPE_ELLIPSE];
+
+Neo.EffectTip.prototype.hasTintImage = true;
+Neo.EffectTip.prototype.toolIcons = [Neo.ToolTip.rectfill,
+ Neo.ToolTip.rect,
+ Neo.ToolTip.ellipsefill,
+ Neo.ToolTip.ellipse];
+
+Neo.EffectTip.prototype.init = function(name, params) {
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.EffectTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+-------------------------------------------------------------------------
+ Effect2Tip
+-------------------------------------------------------------------------
+*/
+
+Neo.effect2Tip;
+
+Neo.Effect2Tip = function() {};
+Neo.Effect2Tip.prototype = new Neo.ToolTip();
+
+Neo.Effect2Tip.prototype.toolStrings = ["Copiar", "Unir",
+ "Cortar",
+ "Inv. Izq/Der", "Inv. Arr/Aba", "Inclinar"];
+Neo.Effect2Tip.prototype.tools = [Neo.Painter.TOOLTYPE_COPY,
+ Neo.Painter.TOOLTYPE_MERGE,
+ Neo.Painter.TOOLTYPE_BLURRECT,
+ Neo.Painter.TOOLTYPE_FLIP_H,
+ Neo.Painter.TOOLTYPE_FLIP_V,
+ Neo.Painter.TOOLTYPE_TURN];
+
+Neo.Effect2Tip.prototype.hasTintImage = true;
+Neo.Effect2Tip.prototype.toolIcons = [Neo.ToolTip.copy,
+ Neo.ToolTip.merge,
+ Neo.ToolTip.blurrect,
+ Neo.ToolTip.flip,
+ Neo.ToolTip.flip,
+ Neo.ToolTip.flip];
+
+Neo.Effect2Tip.prototype.init = function(name, params) {
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+
+ this.img = document.createElement("img");
+ this.img.src = Neo.ToolTip.copy2;
+ this.element.appendChild(this.img);
+ return this;
+};
+
+Neo.Effect2Tip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+-------------------------------------------------------------------------
+ MaskTip
+-------------------------------------------------------------------------
+*/
+
+Neo.maskTip;
+
+Neo.MaskTip = function() {};
+Neo.MaskTip.prototype = new Neo.ToolTip();
+
+Neo.MaskTip.prototype.toolStrings = ["Normal", "Masc.", "Masc. Inv.", "Adicion", "Substrac"];
+
+Neo.MaskTip.prototype.init = function(name, params) {
+ this.fixed = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.MaskTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ Neo.painter.maskColor = Neo.painter.foregroundColor;
+
+ } else {
+ var length = this.toolStrings.length;
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ Neo.painter.maskType = this.mode;
+ }
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+}
+
+Neo.MaskTip.prototype.update = function() {
+ this.draw(Neo.painter.maskColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.MaskTip.prototype.draw = function(c) {
+ if (typeof c != "string") c = Neo.painter.getColorString(c);
+
+ var ctx = this.canvas.getContext("2d");
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ ctx.fillStyle = c;
+ ctx.fillRect(1, 1, 43, 9);
+};
+
+/*
+-------------------------------------------------------------------------
+ DrawTip
+-------------------------------------------------------------------------
+*/
+
+Neo.drawTip;
+
+Neo.DrawTip = function() {};
+Neo.DrawTip.prototype = new Neo.ToolTip();
+
+Neo.DrawTip.prototype.toolStrings = ["Libre", "Linea", "Curva"];
+
+Neo.DrawTip.prototype.hasTintImage = true;
+Neo.DrawTip.prototype.toolIcons = [Neo.ToolTip.freehand,
+ Neo.ToolTip.line,
+ Neo.ToolTip.bezier];
+
+Neo.DrawTip.prototype.init = function(name, params) {
+ this.fixed = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.DrawTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ var length = this.toolStrings.length;
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ this.mode--;
+ if (this.mode < 0) this.mode = length - 1;
+ } else {
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ }
+ Neo.painter.drawType = this.mode;
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+}
+
+Neo.DrawTip.prototype.update = function() {
+ this.mode = Neo.painter.drawType;
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+-------------------------------------------------------------------------
+ ColorSlider
+-------------------------------------------------------------------------
+*/
+
+Neo.sliders = [];
+
+Neo.ColorSlider = function() {};
+
+Neo.ColorSlider.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+ this.value = 0;
+ this.type = this.params.type;
+
+ this.element.className = "colorSlider";
+ this.element.innerHTML = "<div class='slider'></div><div class='label'></div>";
+ this.element.innerHTML += "<div class='hit'></div>";
+
+ this.slider = this.element.getElementsByClassName('slider')[0];
+ this.label = this.element.getElementsByClassName('label')[0];
+ this.hit = this.element.getElementsByClassName('hit')[0];
+ this.hit['data-slider'] = params.type;
+
+ switch (this.type) {
+ case Neo.SLIDERTYPE_RED:
+ this.prefix = "R";
+ this.slider.style.backgroundColor = "#fa9696";
+ break;
+ case Neo.SLIDERTYPE_GREEN:
+ this.prefix = "G";
+ this.slider.style.backgroundColor = "#82f238";
+ break;
+ case Neo.SLIDERTYPE_BLUE:
+ this.prefix = "B";
+ this.slider.style.backgroundColor = "#8080ff";
+ break;
+ case Neo.SLIDERTYPE_ALPHA:
+ this.prefix = "A";
+ this.slider.style.backgroundColor = "#aaaaaa";
+ this.value = 255;
+ break;
+ }
+
+ this.update();
+ return this;
+};
+
+Neo.ColorSlider.prototype.downHandler = function(x, y) {
+ if (Neo.painter.isShiftDown) {
+ this.shift(x, y);
+
+ } else {
+ this.slide(x, y);
+ }
+};
+
+Neo.ColorSlider.prototype.moveHandler = function(x, y) {
+ this.slide(x, y);
+};
+
+Neo.ColorSlider.prototype.upHandler = function(x, y) {
+};
+
+Neo.ColorSlider.prototype.shift = function(x, y) {
+ var value;
+ if (x >= 0 && x < 60 && y >= 0 && y <= 15) {
+ var v = Math.floor((x - 5) * 5.0);
+ var min = (this.type == Neo.SLIDERTYPE_ALPHA) ? 1 : 0;
+
+ value = Math.max(Math.min(v, 255), min);
+ if (this.value > value || this.value == 255) {
+ this.value--;
+ } else {
+ this.value++;
+ }
+ this.value = Math.max(Math.min(this.value, 255), min);
+ this.value0 = this.value;
+ this.x0 = x;
+ }
+
+ if (this.type == Neo.SLIDERTYPE_ALPHA) {
+ Neo.painter.alpha = this.value / 255.0;
+ this.update();
+ Neo.updateUIColor(false, false);
+
+ } else {
+ var r = Neo.sliders[Neo.SLIDERTYPE_RED].value;
+ var g = Neo.sliders[Neo.SLIDERTYPE_GREEN].value;
+ var b = Neo.sliders[Neo.SLIDERTYPE_BLUE].value;
+
+ Neo.painter.setColor(r<<16 | g<<8 | b);
+ Neo.updateUIColor(true, true);
+ }
+};
+
+Neo.ColorSlider.prototype.slide = function(x, y) {
+ var value;
+ if (x >= 0 && x < 60 && y >= 0 && y <= 15) {
+ var v = Math.floor((x - 5) * 5.0);
+ value = Math.round(v / 5) * 5;
+
+ this.value0 = value;
+ this.x0 = x;
+
+ } else {
+ var d = (x - this.x0) / 3.0;
+ value = this.value0 + d;
+ }
+
+ var min = (this.type == Neo.SLIDERTYPE_ALPHA) ? 1 : 0;
+ this.value = Math.max(Math.min(value, 255), min);
+
+ if (this.type == Neo.SLIDERTYPE_ALPHA) {
+ Neo.painter.alpha = this.value / 255.0;
+ this.update();
+ Neo.updateUIColor(false, false);
+
+ } else {
+ var r = Neo.sliders[Neo.SLIDERTYPE_RED].value;
+ var g = Neo.sliders[Neo.SLIDERTYPE_GREEN].value;
+ var b = Neo.sliders[Neo.SLIDERTYPE_BLUE].value;
+
+ Neo.painter.setColor(r<<16 | g<<8 | b);
+// Neo.updateUIColor(true, true);
+ }
+};
+
+Neo.ColorSlider.prototype.update = function() {
+ var color = Neo.painter.getColor();
+ var alpha = Neo.painter.alpha * 255;
+
+ switch (this.type) {
+ case Neo.SLIDERTYPE_RED: this.value = (color & 0x0000ff); break;
+ case Neo.SLIDERTYPE_GREEN: this.value = (color & 0x00ff00) >> 8; break;
+ case Neo.SLIDERTYPE_BLUE: this.value = (color & 0xff0000) >> 16; break;
+ case Neo.SLIDERTYPE_ALPHA: this.value = alpha; break;
+ }
+
+ var width = this.value * 49.0 / 255.0;
+ width = Math.max(Math.min(48, width), 1);
+
+ this.slider.style.width = width.toFixed(2) + "px";
+ this.label.innerHTML = this.prefix + this.value.toFixed(0);
+};
+
+/*
+-------------------------------------------------------------------------
+ SizeSlider
+-------------------------------------------------------------------------
+*/
+
+Neo.SizeSlider = function() {};
+
+Neo.SizeSlider.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+ this.value = this.value0 = 1;
+
+ this.element.className = "sizeSlider";
+ this.element.innerHTML = "<div class='slider'></div><div class='label'></div>";
+ this.element.innerHTML += "<div class='hit'></div>"
+
+ this.slider = this.element.getElementsByClassName('slider')[0];
+ this.label = this.element.getElementsByClassName('label')[0];
+ this.hit = this.element.getElementsByClassName('hit')[0];
+ this.hit['data-slider'] = params.type;
+
+ this.slider.style.backgroundColor = Neo.painter.foregroundColor;
+ this.update();
+ return this;
+};
+
+Neo.SizeSlider.prototype.downHandler = function(x, y) {
+ if (Neo.painter.isShiftDown) {
+ this.shift(x, y);
+
+ } else {
+ this.value0 = this.value;
+ this.y0 = y;
+ this.slide(x, y);
+ }
+};
+
+Neo.SizeSlider.prototype.moveHandler = function(x, y) {
+ this.slide(x, y);
+};
+
+Neo.SizeSlider.prototype.upHandler = function(x, y) {
+};
+
+Neo.SizeSlider.prototype.shift = function(x, y) {
+ var value0 = Neo.painter.lineWidth;
+ var value;
+
+ if (!Neo.painter.tool.alt) {
+ var v = Math.floor((y - 4) * 30.0 / 33.0);
+
+ value = Math.max(Math.min(v, 30), 1);
+ if (value0 > value || value0 == 30) {
+ value0--;
+ } else {
+ value0++;
+ }
+ this.setSize(value0);
+ }
+};
+
+Neo.SizeSlider.prototype.slide = function(x, y) {
+ var value;
+ if (!Neo.painter.tool.alt) {
+ if (x >= 0 && x < 48 && y >= 0 && y < 41) {
+ var v = Math.floor((y - 4) * 30.0 / 33.0);
+ value = v;
+
+ this.value0 = value;
+ this.y0 = y;
+
+ } else {
+ var d = (y - this.y0) / 7.0;
+ value = this.value0 + d;
+ }
+ } else {
+ // Ctrl+Alt+ドラッグã§ã‚µã‚¤ã‚ºå¤‰æ›´ã™ã‚‹ã¨ã
+ var d = y - this.y0;
+ value = this.value0 + d;
+ }
+
+ value = Math.max(Math.min(value, 30), 1);
+ this.setSize(value);
+};
+
+Neo.SizeSlider.prototype.setSize = function(value) {
+ value = Math.round(value);
+ Neo.painter.lineWidth = Math.max(Math.min(30, value), 1);
+
+ var tool = Neo.painter.getCurrentTool();
+ if (tool) {
+ if (tool.type == Neo.Painter.TOOLTYPE_BRUSH) {
+ Neo.painter.alpha = tool.getAlpha();
+ Neo.sliders[Neo.SLIDERTYPE_ALPHA].update();
+
+ } else if (tool.type == Neo.Painter.TOOLTYPE_TEXT) {
+ Neo.painter.updateInputText();
+ }
+ }
+ this.update();
+};
+
+Neo.SizeSlider.prototype.update = function() {
+ this.value = Neo.painter.lineWidth;
+
+ var height = this.value * 33.0 / 30.0;
+ height = Math.max(Math.min(34, height), 1);
+
+ this.slider.style.height = height.toFixed(2) + "px";
+ this.label.innerHTML = this.value + "px";
+ this.slider.style.backgroundColor = Neo.painter.foregroundColor;
+};
+
+/*
+-------------------------------------------------------------------------
+ LayerControl
+-------------------------------------------------------------------------
+*/
+
+Neo.LayerControl = function() {};
+Neo.LayerControl.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+
+ var ref = this;
+
+ var mousedown = (window.PointerEvent) ? "onpointerdown" : "onmousedown";
+ this.element[mousedown] = function(e) { ref._mouseDownHandler(e); }
+ this.element.className = "layerControl";
+ this.element.innerHTML = "<div class='bg'></div><div class='label0'>Capa0</div><div class='label1'>Capa1</div><div class='line1'></div><div class='line0'></div>";
+
+ this.bg = this.element.getElementsByClassName('bg')[0];
+ this.label0 = this.element.getElementsByClassName('label0')[0];
+ this.label1 = this.element.getElementsByClassName('label1')[0];
+ this.line0 = this.element.getElementsByClassName('line0')[0];
+ this.line1 = this.element.getElementsByClassName('line1')[0];
+
+ this.line0.style.display = "none";
+ this.line1.style.display = "none";
+ this.label1.style.display = "none";
+
+ this.update();
+ return this;
+};
+
+Neo.LayerControl.prototype._mouseDownHandler = function(e) {
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ var visible = Neo.painter.visible[Neo.painter.current];
+ Neo.painter.visible[Neo.painter.current] = (visible) ? false : true;
+
+ } else {
+ var current = Neo.painter.current;
+ Neo.painter.current = (current) ? 0 : 1
+ }
+ Neo.painter.updateDestCanvas(0, 0, Neo.painter.canvasWidth, Neo.painter.canvasHeight);
+ if (Neo.painter.tool.type == Neo.Painter.TOOLTYPE_PASTE) {
+ Neo.painter.tool.drawCursor(Neo.painter);
+ }
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+
+Neo.LayerControl.prototype.update = function() {
+ this.label0.style.display = (Neo.painter.current == 0) ? "block" : "none";
+ this.label1.style.display = (Neo.painter.current == 1) ? "block" : "none";
+ this.line0.style.display = (Neo.painter.visible[0]) ? "none" : "block";
+ this.line1.style.display = (Neo.painter.visible[1]) ? "none" : "block";
+};
+
+/*
+-------------------------------------------------------------------------
+ ReserveControl
+-------------------------------------------------------------------------
+*/
+Neo.reserveControls = [];
+
+Neo.ReserveControl = function() {};
+Neo.ReserveControl.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ var ref = this;
+
+ var mousedown = (window.PointerEvent) ? "onpointerdown" : "onmousedown";
+ this.element[mousedown] = function(e) { ref._mouseDownHandler(e); }
+ this.element.className = "reserve";
+
+ var index = parseInt(this.name.slice(7)) - 1;
+ this.element.style.top = "1px";
+ this.element.style.left = (index * 15 + 2) + "px";
+
+ this.reserve = Neo.clone(Neo.config.reserves[index]);
+ this.update();
+
+ Neo.reserveControls.push(this);
+ return this;
+};
+
+Neo.ReserveControl.prototype._mouseDownHandler = function(e) {
+ if (e.button == 2 || e.ctrlKey || e.altKey) {
+ this.save();
+ } else {
+ this.load();
+ }
+ this.update();
+};
+
+Neo.ReserveControl.prototype.load = function() {
+ Neo.painter.setToolByType(this.reserve.tool)
+ Neo.painter.foregroundColor = this.reserve.color;
+ Neo.painter.lineWidth = this.reserve.size;
+ Neo.painter.alpha = this.reserve.alpha;
+
+ switch (this.reserve.tool) {
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TONE:
+ Neo.painter.drawType = this.reserve.drawType;
+ };
+ Neo.updateUI();
+};
+
+Neo.ReserveControl.prototype.save = function() {
+ this.reserve.color = Neo.painter.foregroundColor;
+ this.reserve.size = Neo.painter.lineWidth;
+ this.reserve.drawType = Neo.painter.drawType;
+ this.reserve.alpha = Neo.painter.alpha;
+ this.reserve.tool = Neo.painter.tool.getType();
+ this.element.style.backgroundColor = this.reserve.color;
+ this.update();
+ Neo.updateUI();
+};
+
+Neo.ReserveControl.prototype.update = function() {
+ this.element.style.backgroundColor = this.reserve.color;
+};
+
+/*
+-------------------------------------------------------------------------
+ ScrollBarButton
+-------------------------------------------------------------------------
+*/
+
+Neo.scrollH;
+Neo.scrollV;
+
+Neo.ScrollBarButton = function() {};
+Neo.ScrollBarButton.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ this.element.innerHTML = "<div></div>";
+ this.barButton = this.element.getElementsByTagName("div")[0];
+ this.element['data-bar'] = true;
+ this.barButton['data-bar'] = true;
+
+ if (name == "scrollH") Neo.scrollH = this;
+ if (name == "scrollV") Neo.scrollV = this;
+ return this;
+};
+
+Neo.ScrollBarButton.prototype.update = function(oe) {
+ if (this.name == "scrollH") {
+ var a = oe.destCanvas.width / (oe.canvasWidth * oe.zoom);
+ var barWidth = Math.ceil(oe.destCanvas.width * a);
+ var barX = (oe.scrollBarX) * (oe.destCanvas.width - barWidth);
+ this.barButton.style.width = (Math.ceil(barWidth) - 4) + "px";
+ this.barButton.style.left = Math.floor(barX) + "px";
+
+ } else {
+ var a = oe.destCanvas.height / (oe.canvasHeight * oe.zoom);
+ var barHeight = Math.ceil(oe.destCanvas.height * a);
+ var barY = (oe.scrollBarY) * (oe.destCanvas.height - barHeight);
+ this.barButton.style.height = (Math.ceil(barHeight) - 4) + "px";
+ this.barButton.style.top = Math.floor(barY) + "px";
+ }
+};
+
diff --git a/static/js/paintbbs/PaintBBS-1.3.4.css b/static/js/paintbbs/PaintBBS-1.3.4.css
new file mode 100644
index 0000000..2e5b4f7
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.3.4.css
@@ -0,0 +1,547 @@
+.NEO {
+ margin:0;
+ line-height:18px;
+
+ user-select: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+
+ touch-callout: none;
+ -webkit-touch-callout: none;
+}
+
+.NEO *:active,
+.NEO *:hover {
+ cursor: default;
+}
+
+.NEO #container{
+ width: 100%;
+ height: 100%;
+ position: relative;
+ border: 1px dotted transparent;
+}
+
+.NEO #center{
+ display: table;
+ position: relative;
+ height: 100%;
+ margin: auto;
+}
+
+.NEO #toolsWrapper{
+ width: 52px;
+ display: table;
+ position:absolute;
+ top: 0;
+ right: -3px;
+}
+
+.NEO #tools{
+ width: 52px;
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+}
+
+.NEO #painterContainer{
+ display:table-cell;
+ vertical-align: middle;
+ position: relative;
+}
+
+.NEO #painterWrapper{
+ padding: 0 55px 0 0;
+ position: relative;
+
+ float: right; /* ãªãœã‹Chrome55ã§ãšã‚Œã‚‹ã®ã§å¯¾ç­– */
+}
+
+.NEO #upper {
+ position: absolute;
+ right: 0;
+
+ height:30px;
+ padding-right: 75px; //20px;
+ text-align:right;
+}
+
+.NEO #lower {
+ height:30px;
+}
+
+.NEO #painter {
+ position: relative;
+ padding: 20px 20px 20px 20px;
+
+ margin-top: 30px;
+}
+
+.NEO #canvas {
+ position: relative;
+ width: 300px;
+ height: 300px;
+ background-color: white;
+}
+
+.NEO #headerButtons {
+ position: absolute;
+ top: 5px;
+ left: 5px;
+}
+
+.NEO #footerButtons {
+ position: absolute;
+ bottom: 5px;
+ left: 5px;
+}
+
+.NEO #window { float: left; }
+
+/*
+-----------------------
+ Modal Window
+-----------------------
+*/
+
+.NEO #pageView{
+ background-color: white;
+}
+
+.NEO #windowView{
+ z-index: 9999;
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ background-color: white;
+}
+
+/*
+-----------------------
+ Controls
+-----------------------
+*/
+
+.NEO #zoomMinus {
+ padding: 0;
+ margin: 0;
+ width:16px;
+ height:16px;
+ margin-left:1px;
+}
+
+.NEO #zoomPlus {
+ padding: 0;
+ margin: 0;
+ width:16px;
+ height:16px;
+}
+
+.NEO #zoomMinusWrapper {
+ position: absolute;
+ right: -20px;
+ bottom: -21px;
+ width: 19px;
+ height: 19px;
+ text-align:center;
+}
+
+.NEO #zoomPlusWrapper {
+ position: absolute;
+ left: -21px;
+ bottom: -21px;
+ width: 19px;
+ height: 19px;
+ text-overflow: hidden;
+ text-align:center;
+}
+
+.NEO #scrollH {
+ position: absolute;
+ left: 1px;
+ bottom: -20px;
+ width: calc(100% - 2px);
+ height: 18px;
+}
+
+.NEO #scrollV {
+ position: absolute;
+ right: -20px;
+ top: 1px;
+ width: 18px;
+ height: calc(100% - 2px);
+}
+
+.NEO #scrollH div {
+ position: absolute;
+ width: 50px;
+ height: 16px;
+}
+
+.NEO #scrollV div {
+ position: absolute;
+ width: 16px;
+ height: 50px;
+}
+
+.NEO #scrollH div:hover {}
+.NEO #scrollV div:hover {}
+
+.NEO #neoWarning {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ color: red;
+ pointer-events: none;
+ text-align: left;
+ transition: all 2s;
+}
+
+/*
+-----------------------
+ Widgets
+-----------------------
+*/
+
+.NEO .buttonOff {
+ display: inline-block;
+ border: 1px solid white;
+ height: 19px;
+ padding: 3px;
+ height: 16px;
+ font-size: 15px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ margin-right: 4px;
+
+ border-left: 1px solid rgba(0, 0, 0, 0);
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-right: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin: 1px;
+
+}
+
+.NEO .buttonOff:hover {}
+
+.NEO .buttonOff:active,
+.NEO .buttonOn {
+ display: inline-block;
+ height: 19px;
+ padding: 3px;
+ height: 16px;
+ font-size: 15px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ margin-right: 4px;
+
+ border-right: 1px solid rgba(0, 0, 0, 0);
+ border-bottom: 1px solid rgba(0, 0, 0, 0);
+
+ -webkit-font-smoothing: antialiased;
+ font-smoothing: antialiased;
+ margin: 1px;
+}
+
+.NEO #right { display: inline-block; float: right; margin-left: 10px; }
+
+.NEO .toolTipOff,
+.NEO .toolTipFixed {
+ position:relative;
+ padding: 0;
+ margin: 0;
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ width: 46px;
+ height: 18px;
+ border-top: 1px solid #ffffff;
+ border-left: 1px solid #ffffff;
+ border-right: 1px solid #9397b2;
+ border-bottom: 1px solid #9397b2;
+}
+
+.NEO .toolTipOn {
+ position:relative;
+ padding: 0;
+ margin: 0;
+ margin-top: 3px;
+ margin-bottom: 3px;
+
+ width: 46px;
+ height: 18px;
+ border-top: 1px solid rgba(0, 0, 0, 0);
+ border-left: 1px solid rgba(0, 0, 0, 0);
+ border-right: 1px solid #ffffff;
+ border-bottom: 1px solid #ffffff;
+}
+
+
+
+.NEO .toolTipOff canvas,
+.NEO .toolTipOn canvas,
+.NEO .toolTipFixed canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+}
+
+.NEO .toolTipOff .label,
+.NEO .toolTipOn .label,
+.NEO .toolTipFixed .label {
+ position: absolute;
+ bottom: -4px;
+ left: 1px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: -1px;
+ overflow: hidden !important;
+}
+
+.NEO .colorTips {
+ position:relative;
+ width: 48px;
+ height: 144px;
+ padding: 0;
+ margin: 0;
+ margin-top: 4px;
+ margin-left: 0px;
+}
+
+.NEO .colorTipOff {
+ position: absolute;
+ overflow: hidden;
+ width: 22px;
+ height: 18px;
+ margin: -1px 4px 0px 0px;
+ padding: 0;
+}
+
+.NEO .colorTipOff img {
+ left: 0;
+ opacity: 0.5;
+ position: absolute;
+ pointer-events:none;
+}
+
+.NEO .colorTipOn {
+ position: absolute;
+ overflow: hidden;
+ width: 22px;
+ height: 18px;
+ margin: -1px 4px 0px 0px;
+ padding: 0;
+}
+
+.NEO .colorTipOn img {
+ left: -22px;
+ opacity: 0.5;
+ position: absolute;
+ pointer-events:none;
+}
+
+.NEO .colorSlider {
+ width: 48px;
+ height:13px;
+ position: relative;
+ margin-top: 3px;
+}
+
+.NEO .colorSlider .label {
+ pointer-events: none;
+ position: absolute;
+ left: 2px;
+ bottom: -3px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: middle;
+}
+
+.NEO .colorSlider .slider {
+ position: absolute;
+ height: 100%;
+ left: 0px;
+ width: 50%;
+ background-color: #fa9696;
+ box-shadow: -1px 0 0 0px rgba(0, 0, 0, 0.3) inset;
+}
+
+.NEO .colorSlider .hit {
+ position:absolute;
+ width: 60px;
+ height: 13px;
+ left: -6px;
+ background-color: white;
+ opacity: 0.01;
+}
+
+.NEO .sizeSlider {
+ width: 48px;
+ height:33px;
+ position: relative;
+ margin-top: 4px;
+}
+
+.NEO .sizeSlider .label {
+ pointer-events: none;
+ position: absolute;
+ left: 2px;
+ bottom: -3px;
+ font-size:12px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: middle;
+}
+
+.NEO .sizeSlider .slider {
+ position: absolute;
+ width: 100%;
+ top: 0px;
+ height: 33%;
+ background-color: #82f238;
+ box-shadow: 0 -1px 0 0px rgba(0, 0, 0, 0.3) inset;
+}
+
+.NEO .sizeSlider .hit {
+ position:absolute;
+ width: 48px;
+ height: 41px;
+ top: -4px;
+ background-color: white;
+ opacity: 0.01;
+}
+
+.NEO .reserveControl {
+ width: 48px;
+ height: 13px;
+ position: relative;
+}
+
+.NEO .reserveControl .reserve {
+ position: absolute;
+ width: 11px;
+ height: 8px;
+ background-color: white;
+}
+
+.NEO .layerControl {
+ width: 48px;
+ height: 20px;
+ position: relative;
+ margin-top: 6px;
+}
+
+.NEO .layerControl .bg {
+ position: absolute;
+ width: 44px;
+ height: 9px;
+ margin: 0;
+
+ top: 0px;
+ left: 2px;
+}
+
+.NEO .layerControl .line1 {
+ position: absolute;
+ width: 50px;
+ height:10px;
+ margin: 0;
+ padding: 0;
+
+ top: 0px;
+ left: -1px;
+ background-image: linear-gradient(to top right, transparent, transparent 47%, red 47%, red 53%, transparent 53%, transparent);
+}
+
+.NEO .layerControl .line0 {
+ position: absolute;
+ width: 50px;
+ height: 10px;
+ margin: 0;
+ padding: 0;
+
+ top: 10px;
+ left: -1px;
+ background-image: linear-gradient(to top right, transparent, transparent 47%, red 47%, red 53%, transparent 53%, transparent);
+}
+
+.NEO .layerControl .label1 {
+ position: absolute;
+ left: 2px;
+ Top: -4px;
+ font-size:11px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: baseline;
+}
+
+.NEO .layerControl .label0 {
+ position: absolute;
+ left: 2px;
+ Top: 6px;
+ font-size:11px;
+ font-weight: 100;
+ font-family: 'Arial';
+ letter-spacing: 0;
+ vertical-align: baseline;
+}
+
+/*
+-----------------------
+ InputText
+-----------------------
+*/
+
+.NEO .inputText {
+ z-index: 100000;
+ position: absolute;
+
+ text-align: left;
+ white-space: nowrap;
+ color: #0000ff;
+
+ font-family: 'Arial';
+ padding: 1px 5px 1px 5px;
+ font-size: 32px;
+
+ line-height: 40px;
+ height: 40px;
+ min-width: 10em;
+
+ bottom: 0px;
+ left: 250px;
+
+ border: 1px solid #aaa;
+ background-color: white;
+}
+
+*[contenteditable] {
+ user-select: auto !important;
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto !important;
+}
+
+#testtext {
+ user-select: auto !important;
+ -webkit-user-select: auto !important;
+ -moz-user-select: auto;
+}
+
+[contenteditable="true"]:focus {
+ outline: 1px solid #b1d6fd;
+ border: 1px solid #b1d6fd;
+}
+
diff --git a/static/js/paintbbs/PaintBBS-1.3.4.js b/static/js/paintbbs/PaintBBS-1.3.4.js
new file mode 100644
index 0000000..8450a49
--- /dev/null
+++ b/static/js/paintbbs/PaintBBS-1.3.4.js
@@ -0,0 +1,6171 @@
+'use strict';
+
+document.addEventListener("DOMContentLoaded", function() {
+ Neo.init();
+
+ if (!navigator.userAgent.match("Electron")) {
+ Neo.start();
+ }
+});
+
+
+var Neo = function() {};
+
+Neo.version = "1.3.4";
+Neo.painter;
+Neo.fullScreen = false;
+Neo.uploaded = false;
+
+Neo.config = {
+ width: 300,
+ height: 300,
+
+ colors: [
+ "#000000", "#FFFFFF",
+ "#B47575", "#888888",
+ "#FA9696", "#C096C0",
+ "#FFB6FF", "#8080FF",
+ "#25C7C9", "#E7E58D",
+ "#E7962D", "#99CB7B",
+ "#FCECE2", "#F9DDCF"
+ ]
+};
+
+Neo.reservePen = {};
+Neo.reserveEraser = {};
+
+Neo.SLIDERTYPE_RED = 0;
+Neo.SLIDERTYPE_GREEN = 1;
+Neo.SLIDERTYPE_BLUE = 2;
+Neo.SLIDERTYPE_ALPHA = 3;
+Neo.SLIDERTYPE_SIZE = 4;
+
+document.neo = Neo;
+
+Neo.init = function() {
+ var applets = document.getElementsByTagName('applet');
+ if (applets.length == 0) {
+ applets = document.getElementsByTagName('applet-dummy');
+ }
+
+ for (var i = 0; i < applets.length; i++) {
+ var applet = applets[i];
+ var name = applet.attributes.name.value;
+ if (name == "paintbbs") {
+ Neo.applet = applet;
+ Neo.initConfig(applet);
+ Neo.createContainer(applet);
+ Neo.init2();
+ }
+ }
+};
+
+Neo.init2 = function() {
+ var pageview = document.getElementById("pageView");
+ pageview.style.width = Neo.config.applet_width + "px";
+ pageview.style.height = Neo.config.applet_height + "px";
+
+ Neo.canvas = document.getElementById("canvas");
+ Neo.container = document.getElementById("container");
+ Neo.toolsWrapper = document.getElementById("toolsWrapper");
+
+ Neo.painter = new Neo.Painter();
+ Neo.painter.build(Neo.canvas, Neo.config.width, Neo.config.height);
+
+ Neo.container.oncontextmenu = function() {return false;};
+
+ // 続ãã‹ã‚‰æã
+ if (Neo.config.image_canvas) {
+ Neo.painter.loadImage(Neo.config.image_canvas);
+ }
+
+ // æãã‹ã‘ã®ç”»åƒãŒè¦‹ã¤ã‹ã£ãŸã¨ã
+ Neo.storage = (Neo.isMobile()) ? localStorage : sessionStorage;
+ if (Neo.storage.getItem('timestamp')) {
+ setTimeout(function () {
+ if (confirm(Neo.translate("以å‰ã®ç·¨é›†ãƒ‡ãƒ¼ã‚¿ã‚’復元ã—ã¾ã™ã‹ï¼Ÿ"))) {
+ Neo.painter.loadSession();
+ }
+ }, 1);
+ }
+
+ window.addEventListener("pagehide", function(e) {
+ if (!Neo.uploaded) {
+ Neo.painter.saveSession();
+ } else {
+ Neo.painter.clearSession();
+ }
+ }, false);
+}
+
+Neo.initConfig = function(applet) {
+ if (applet) {
+ var name = applet.attributes.name.value || "neo";
+ var appletWidth = applet.attributes.width;
+ var appletHeight = applet.attributes.height;
+ if (appletWidth) Neo.config.applet_width = parseInt(appletWidth.value);
+ if (appletHeight) Neo.config.applet_height = parseInt(appletHeight.value);
+
+ var params = applet.getElementsByTagName('param');
+ for (var i = 0; i < params.length; i++) {
+ var p = params[i];
+ Neo.config[p.name] = Neo.fixConfig(p.value);
+
+ if (p.name == "image_width") Neo.config.width = parseInt(p.value);
+ if (p.name == "image_height") Neo.config.height = parseInt(p.value);
+ }
+
+ var emulationMode = Neo.config.neo_emulation_mode || "2.22_8x";
+ Neo.config.neo_alt_translation = emulationMode.slice(-1).match(/x/i);
+
+ Neo.readStyles();
+ Neo.applyStyle("color_bk", "#ccccff");
+ Neo.applyStyle("color_bk2", "#bbbbff");
+ Neo.applyStyle("color_tool_icon", "#e8dfae");
+ Neo.applyStyle("color_icon", "#ccccff");
+ Neo.applyStyle("color_iconselect", "#ffaaaa");
+ Neo.applyStyle("color_text", "#666699");
+ Neo.applyStyle("color_bar", "#6f6fae");
+ Neo.applyStyle("tool_color_button", "#e8dfae");
+ Neo.applyStyle("tool_color_button2", "#f8daaa");
+ Neo.applyStyle("tool_color_text", "#773333");
+ Neo.applyStyle("tool_color_bar", "#ddddff");
+ Neo.applyStyle("tool_color_frame", "#000000");
+
+ var e = document.getElementById("container");
+ Neo.config.inherit_color = Neo.getInheritColor(e);
+ if (!Neo.config.color_frame) Neo.config.color_frame = Neo.config.color_text;
+ }
+
+ Neo.config.reserves = [
+ { size:1,
+ color:"#000000", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_PEN,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ { size:5,
+ color:"#FFFFFF", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_ERASER,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ { size:10,
+ color:"#FFFFFF", alpha:1.0,
+ tool:Neo.Painter.TOOLTYPE_ERASER,
+ drawType:Neo.Painter.DRAWTYPE_FREEHAND
+ },
+ ];
+
+ Neo.reservePen = Neo.clone(Neo.config.reserves[0]);
+ Neo.reserveEraser = Neo.clone(Neo.config.reserves[1]);
+};
+
+Neo.fixConfig = function(value) {
+ // javaã§ã¯"#12345"を色ã¨ã—ã¦è§£é‡ˆã™ã‚‹ãŒjavascriptã§ã¯"#012345"ã«å¤‰æ›ã—ãªã„ã¨ã ã‚
+ if (value.match(/^#[0-9a-fA-F]{5}$/)) {
+ value = "#0" + value.slice(1);
+ }
+ return value;
+};
+
+Neo.initSkin = function() {
+ var sheet = document.styleSheets[0];
+ if (!sheet) {
+ var style = document.createElement("style");
+ document.head.appendChild(style); // must append before you can access sheet property
+ sheet = style.sheet;
+ }
+
+ Neo.styleSheet = sheet;
+
+ var lightBorder = Neo.multColor(Neo.config.color_icon, 1.3);
+ var darkBorder = Neo.multColor(Neo.config.color_icon, 0.7);
+ var lightBar = Neo.multColor(Neo.config.color_bar, 1.3);
+ var darkBar = Neo.multColor(Neo.config.color_bar, 0.7);
+ var bgImage = Neo.backgroundImage();
+
+ Neo.addRule(".NEO #container", "background-image", "url(" + bgImage + ")");
+ Neo.addRule(".NEO .colorSlider .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .sizeSlider .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .label1", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .label0", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .toolTipOn .label", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .toolTipOff .label", "color", Neo.config.tool_color_text);
+
+ Neo.addRule(".NEO #toolSet", "background-color", Neo.config.color_bk);
+ Neo.addRule(".NEO #tools", "color", Neo.config.tool_color_text);
+ Neo.addRule(".NEO .layerControl .bg", "border-bottom", "1px solid " + Neo.config.tool_color_text);
+
+ Neo.addRule(".NEO .buttonOn", "color", Neo.config.color_text);
+ Neo.addRule(".NEO .buttonOff", "color", Neo.config.color_text);
+
+ Neo.addRule(".NEO .buttonOff", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "border-top", "1px solid ", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "border-left", "1px solid ", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff", "box-shadow", "0 0 0 1px " + Neo.config.color_icon + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO .buttonOff:hover", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO .buttonOff:hover", "border-top", "1px solid " + lightBorder);
+ Neo.addRule(".NEO .buttonOff:hover", "border-left", "1px solid " + lightBorder);
+ Neo.addRule(".NEO .buttonOff:hover", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "background-color", darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "border-top", "1px solid " + darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "border-left", "1px solid " + darkBorder);
+ Neo.addRule(".NEO .buttonOff:active, .NEO .buttonOn", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect + ", 0 0 0 2px " + Neo.config.color_frame);
+
+
+ Neo.addRule(".NEO #canvas", "border", "1px solid " + Neo.config.color_frame);
+ Neo.addRule(".NEO #scrollH, .NEO #scrollV", "background-color", Neo.config.color_icon);
+ Neo.addRule(".NEO #scrollH, .NEO #scrollV", "box-shadow", "0 0 0 1px white" + ", 0 0 0 2px " + Neo.config.color_frame);
+
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "background-color", Neo.config.color_bar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "box-shadow", "0 0 0 1px " + Neo.config.color_icon);
+ Neo.addRule(".NEO #scrollH div:hover, .NEO #scrollV div:hover", "box-shadow", "0 0 0 1px " + Neo.config.color_iconselect);
+
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-top", "1px solid " + lightBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-left", "1px solid " + lightBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-right", "1px solid " + darkBar);
+ Neo.addRule(".NEO #scrollH div, .NEO #scrollV div", "border-bottom", "1px solid " + darkBar);
+
+ Neo.addRule(".NEO .toolTipOn", "background-color", Neo.multColor(Neo.config.tool_color_button, 0.7));
+ Neo.addRule(".NEO .toolTipOff", "background-color", Neo.config.tool_color_button);
+ Neo.addRule(".NEO .toolTipFixed", "background-color", Neo.config.tool_color_button2);
+
+ Neo.addRule(".NEO .colorSlider, .NEO .sizeSlider", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .reserveControl", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .reserveControl", "background-color", Neo.config.tool_color_bar);
+ Neo.addRule(".NEO .layerControl", "background-color", Neo.config.tool_color_bar);
+
+ Neo.addRule(".NEO .colorTipOn, .NEO .colorTipOff", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .toolTipOn, .NEO .toolTipOff", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .toolTipFixed", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .colorSlider, .NEO .sizeSlider", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .reserveControl", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .layerControl", "box-shadow", "0 0 0 1px " + Neo.config.tool_color_frame);
+ Neo.addRule(".NEO .reserveControl .reserve", "border", "1px solid " + Neo.config.tool_color_frame);
+
+ if (navigator.language.indexOf("ja") != 0) {
+ var labels = ["Fixed", "On", "Off"];
+ for (var i = 0; i < labels.length; i++) {
+ var selector = ".NEO .toolTip" + labels[i] + " .label";
+ Neo.addRule(selector, "letter-spacing", "0px !important");
+ }
+ }
+};
+
+Neo.addRule = function(selector, styleName, value, sheet) {
+ if (!sheet) sheet = Neo.styleSheet;
+ if (sheet.addRule) {
+ sheet.addRule(selector, styleName + ":" + value, sheet.rules.length);
+
+ } else if (sheet.insertRule) {
+ var rule = selector + "{" + styleName + ":" + value + "}";
+ var index = sheet.cssRules.length;
+ sheet.insertRule(rule, index);
+ }
+};
+
+Neo.readStyles = function() {
+ Neo.rules = {};
+ for (var i = 0; i < document.styleSheets.length; i++) {
+ Neo.readStyle(document.styleSheets[i]);
+ }
+};
+
+Neo.readStyle = function(sheet) {
+ try {
+ var rules = sheet.cssRules;
+ for (var i = 0; i < rules.length; i++) {
+ var rule = rules[i];
+ if (rule.styleSheet) {
+ Neo.readStyle(rule.styleSheet);
+ continue;
+ }
+
+ var selector = rule.selectorText
+ if (selector) {
+ selector = selector.replace(/^(.NEO\s+)?\./, '')
+
+ var css = rule.cssText || rule.style.cssText;
+ var result = css.match(/color:\s*(.*)\s*;/)
+ if (result) {
+ var hex = Neo.colorNameToHex(result[1]);
+ if (hex) {
+ Neo.rules[selector] = hex;
+ }
+ }
+ }
+ }
+ } catch (e) {}
+};
+
+Neo.applyStyle = function(name, defaultColor) {
+ if (Neo.config[name] == undefined) {
+ Neo.config[name] = Neo.rules[name] || defaultColor;
+ }
+};
+
+Neo.getInheritColor = function(e) {
+ var result = "#000000";
+ while (e && e.style) {
+ if (e.style.color != "") {
+ result = e.style.color;
+ break;
+ }
+ if (e.attributes["text"]) {
+ result = e.attributes["text"].value;
+ break;
+ }
+ e = e.parentNode;
+ }
+ return result;
+};
+
+Neo.backgroundImage = function() {
+ var c1 = Neo.painter.getColor(Neo.config.color_bk) | 0xff000000;
+ var c2 = Neo.painter.getColor(Neo.config.color_bk2) | 0xff000000;
+ var bgCanvas = document.createElement("canvas");
+ bgCanvas.width = 16;
+ bgCanvas.height = 16;
+ var ctx = bgCanvas.getContext("2d");
+ var imageData = ctx.getImageData(0, 0, 16, 16);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var index = 0;
+ for (var y = 0; y < 16; y++) {
+ for (var x = 0; x < 16; x++) {
+ buf32[index++] = (x == 14 || y == 14) ? c2 : c1;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+ return bgCanvas.toDataURL('image/png');
+};
+
+Neo.multColor = function(c, scale) {
+ var r = Math.round(parseInt(c.substr(1, 2), 16) * scale);
+ var g = Math.round(parseInt(c.substr(3, 2), 16) * scale);
+ var b = Math.round(parseInt(c.substr(5, 2), 16) * scale);
+ r = ("0" + Math.min(Math.max(r, 0), 255).toString(16)).substr(-2);
+ g = ("0" + Math.min(Math.max(g, 0), 255).toString(16)).substr(-2);
+ b = ("0" + Math.min(Math.max(b, 0), 255).toString(16)).substr(-2);
+ return '#' + r + g + b;
+};
+
+Neo.colorNameToHex = function(name) {
+ var colors = {"aliceblue":"#f0f8ff", "antiquewhite":"#faebd7", "aqua":"#00ffff","aquamarine":"#7fffd4", "azure":"#f0ffff", "beige":"#f5f5dc", "bisque":"#ffe4c4", "black":"#000000", "blanchedalmond":"#ffebcd", "blue":"#0000ff", "blueviolet":"#8a2be2", "brown":"#a52a2a", "burlywood":"#deb887", "cadetblue":"#5f9ea0", "chartreuse":"#7fff00", "chocolate":"#d2691e", "coral":"#ff7f50", "cornflowerblue":"#6495ed", "cornsilk":"#fff8dc", "crimson":"#dc143c", "cyan":"#00ffff", "darkblue":"#00008b", "darkcyan":"#008b8b", "darkgoldenrod":"#b8860b", "darkgray":"#a9a9a9", "darkgreen":"#006400", "darkkhaki":"#bdb76b", "darkmagenta":"#8b008b", "darkolivegreen":"#556b2f", "darkorange":"#ff8c00", "darkorchid":"#9932cc", "darkred":"#8b0000", "darksalmon":"#e9967a", "darkseagreen":"#8fbc8f", "darkslateblue":"#483d8b", "darkslategray":"#2f4f4f", "darkturquoise":"#00ced1", "darkviolet":"#9400d3", "deeppink":"#ff1493", "deepskyblue":"#00bfff", "dimgray":"#696969", "dodgerblue":"#1e90ff", "firebrick":"#b22222", "floralwhite":"#fffaf0", "forestgreen":"#228b22", "fuchsia":"#ff00ff", "gainsboro":"#dcdcdc", "ghostwhite":"#f8f8ff", "gold":"#ffd700", "goldenrod":"#daa520", "gray":"#808080", "green":"#008000", "greenyellow":"#adff2f", "honeydew":"#f0fff0", "hotpink":"#ff69b4", "indianred ":"#cd5c5c", "indigo":"#4b0082", "ivory":"#fffff0", "khaki":"#f0e68c", "lavender":"#e6e6fa", "lavenderblush":"#fff0f5", "lawngreen":"#7cfc00", "lemonchiffon":"#fffacd", "lightblue":"#add8e6", "lightcoral":"#f08080", "lightcyan":"#e0ffff", "lightgoldenrodyellow":"#fafad2", "lightgrey":"#d3d3d3", "lightgreen":"#90ee90", "lightpink":"#ffb6c1", "lightsalmon":"#ffa07a", "lightseagreen":"#20b2aa", "lightskyblue":"#87cefa", "lightslategray":"#778899", "lightsteelblue":"#b0c4de", "lightyellow":"#ffffe0", "lime":"#00ff00", "limegreen":"#32cd32", "linen":"#faf0e6", "magenta":"#ff00ff", "maroon":"#800000", "mediumaquamarine":"#66cdaa", "mediumblue":"#0000cd", "mediumorchid":"#ba55d3", "mediumpurple":"#9370d8", "mediumseagreen":"#3cb371", "mediumslateblue":"#7b68ee", "mediumspringgreen":"#00fa9a", "mediumturquoise":"#48d1cc", "mediumvioletred":"#c71585", "midnightblue":"#191970", "mintcream":"#f5fffa", "mistyrose":"#ffe4e1", "moccasin":"#ffe4b5", "navajowhite":"#ffdead", "navy":"#000080", "oldlace":"#fdf5e6", "olive":"#808000", "olivedrab":"#6b8e23", "orange":"#ffa500", "orangered":"#ff4500", "orchid":"#da70d6", "palegoldenrod":"#eee8aa", "palegreen":"#98fb98", "paleturquoise":"#afeeee", "palevioletred":"#d87093", "papayawhip":"#ffefd5", "peachpuff":"#ffdab9", "peru":"#cd853f", "pink":"#ffc0cb", "plum":"#dda0dd", "powderblue":"#b0e0e6", "purple":"#800080", "rebeccapurple":"#663399", "red":"#ff0000", "rosybrown":"#bc8f8f", "royalblue":"#4169e1", "saddlebrown":"#8b4513", "salmon":"#fa8072", "sandybrown":"#f4a460", "seagreen":"#2e8b57", "seashell":"#fff5ee", "sienna":"#a0522d", "silver":"#c0c0c0", "skyblue":"#87ceeb", "slateblue":"#6a5acd", "slategray":"#708090", "snow":"#fffafa", "springgreen":"#00ff7f", "steelblue":"#4682b4", "tan":"#d2b48c", "teal":"#008080", "thistle":"#d8bfd8", "tomato":"#ff6347", "turquoise":"#40e0d0", "violet":"#ee82ee", "wheat":"#f5deb3", "white":"#ffffff", "whitesmoke":"#f5f5f5", "yellow":"#ffff00", "yellowgreen":"#9acd32"};
+
+ var rgb = name.toLowerCase().match(/rgb\((.*),(.*),(.*)\)/);
+ if (rgb) {
+ var r = ("0" + parseInt(rgb[1]).toString(16)).slice(-2)
+ var g = ("0" + parseInt(rgb[2]).toString(16)).slice(-2)
+ var b = ("0" + parseInt(rgb[3]).toString(16)).slice(-2)
+ return "#" + r + g + b
+ }
+
+ if (typeof colors[name.toLowerCase()] != 'undefined') {
+ return colors[name.toLowerCase()];
+ }
+ return false;
+};
+
+Neo.initComponents = function() {
+ document.getElementById("copyright").innerHTML += "v" + Neo.version;
+
+ // アプレットã®borderã®å‹•ä½œã‚’エミュレート
+ if (navigator.userAgent.search("FireFox") > -1) {
+ var container = document.getElementById("container");
+ container.addEventListener("mousedown", function(e) {
+ container.style.borderColor = Neo.config.inherit_color;
+ e.stopPropagation();
+ }, false);
+ document.addEventListener("mousedown", function(e) {
+ container.style.borderColor = 'transparent';
+ }, false);
+ }
+
+ // ドラッグã—ãŸã¾ã¾ç”»é¢å¤–ã«ç§»å‹•ã—ãŸæ™‚
+ document.addEventListener("mouseup", function(e) {
+ if (Neo.painter && !Neo.painter.isContainer(e.target)) {
+ Neo.painter.cancelTool(e.target);
+ }
+ }, false);
+
+ // 投稿ã«å¤±æ•—ã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚‹ã¨ãã¯è­¦å‘Šã‚’表示ã™ã‚‹
+ Neo.showWarning();
+
+ if (Neo.styleSheet) {
+ Neo.addRule("*", "user-select", "none");
+ Neo.addRule("*", "-webkit-user-select", "none");
+ Neo.addRule("*", "-ms-user-select", "none");
+ }
+}
+
+Neo.initButtons = function() {
+ new Neo.Button().init("undo").onmouseup = function() {
+ new Neo.UndoCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("redo").onmouseup = function () {
+ new Neo.RedoCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("window").onmouseup = function() {
+ new Neo.WindowCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("submit").onmouseup = function() {
+ new Neo.SubmitCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("copyright").onmouseup = function() {
+ new Neo.CopyrightCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("zoomPlus").onmouseup = function() {
+ new Neo.ZoomPlusCommand(Neo.painter).execute();
+ };
+ new Neo.Button().init("zoomMinus").onmouseup = function() {
+ new Neo.ZoomMinusCommand(Neo.painter).execute();
+ };
+
+ Neo.fillButton = new Neo.FillButton().init("fill");
+ Neo.rightButton = new Neo.RightButton().init("right");
+
+ if (Neo.isMobile()) {
+ Neo.rightButton.element.style.display = "block";
+ }
+
+ // toolTip
+ Neo.penTip = new Neo.PenTip().init("pen");
+ Neo.pen2Tip = new Neo.Pen2Tip().init("pen2");
+ Neo.effectTip = new Neo.EffectTip().init("effect");
+ Neo.effect2Tip = new Neo.Effect2Tip().init("effect2");
+ Neo.eraserTip = new Neo.EraserTip().init("eraser");
+ Neo.drawTip = new Neo.DrawTip().init("draw");
+ Neo.maskTip = new Neo.MaskTip().init("mask");
+
+ Neo.toolButtons = [Neo.fillButton,
+ Neo.penTip,
+ Neo.pen2Tip,
+ Neo.effectTip,
+ Neo.effect2Tip,
+ Neo.drawTip,
+ Neo.eraserTip];
+
+ // colorTip
+ for (var i = 1; i <= 14; i++) {
+ new Neo.ColorTip().init("color" + i, {index:i});
+ };
+
+ // colorSlider
+ Neo.sliders[Neo.SLIDERTYPE_RED] = new Neo.ColorSlider().init(
+ "sliderRed", {type:Neo.SLIDERTYPE_RED});
+ Neo.sliders[Neo.SLIDERTYPE_GREEN] = new Neo.ColorSlider().init(
+ "sliderGreen", {type:Neo.SLIDERTYPE_GREEN});
+ Neo.sliders[Neo.SLIDERTYPE_BLUE] = new Neo.ColorSlider().init(
+ "sliderBlue", {type:Neo.SLIDERTYPE_BLUE});
+ Neo.sliders[Neo.SLIDERTYPE_ALPHA] = new Neo.ColorSlider().init(
+ "sliderAlpha", {type:Neo.SLIDERTYPE_ALPHA});
+
+ // sizeSlider
+ Neo.sliders[Neo.SLIDERTYPE_SIZE] = new Neo.SizeSlider().init(
+ "sliderSize", {type:Neo.SLIDERTYPE_SIZE});
+
+ // reserveControl
+ for (var i = 1; i <= 3; i++) {
+ new Neo.ReserveControl().init("reserve" + i, {index:i});
+ };
+
+ new Neo.LayerControl().init("layerControl");
+ new Neo.ScrollBarButton().init("scrollH");
+ new Neo.ScrollBarButton().init("scrollV");
+};
+
+Neo.start = function(isApp) {
+ if (!Neo.painter) return;
+
+ Neo.initSkin();
+ Neo.initComponents();
+ Neo.initButtons();
+
+ Neo.isApp = isApp;
+ if (Neo.applet) {
+ var name = Neo.applet.attributes.name.value || "paintbbs";
+ Neo.applet.outerHTML = "";
+ document[name] = Neo;
+
+ Neo.resizeCanvas();
+ Neo.container.style.visibility = "visible";
+
+ if (Neo.isApp) {
+ var ipc = require('electron').ipcRenderer;
+ ipc.sendToHost('neo-status', 'ok');
+
+ } else {
+ if (document.paintBBSCallback) {
+ document.paintBBSCallback('start');
+ }
+ }
+ }
+};
+
+Neo.isIE = function() {
+ var ms = false;
+ if (/MSIE 10/i.test(navigator.userAgent)) {
+ ms = true; // This is internet explorer 10
+ }
+ if (/MSIE 9/i.test(navigator.userAgent) ||
+ /rv:11.0/i.test(navigator.userAgent)) {
+ ms = true; // This is internet explorer 9 or 11
+ }
+ return ms
+};
+
+Neo.isMobile = function() {
+ return navigator.userAgent.match(/Android|iPhone|iPad|iPod/i);
+};
+
+Neo.showWarning = function() {
+ var futaba = location.hostname.match(/2chan.net/i);
+ var samplebbs = location.hostname.match(/neo.websozai.jp/i);
+
+ var chrome = navigator.userAgent.match(/Chrome\/(\d+)/i);
+ if (chrome && chrome.length > 1) chrome = chrome[1];
+
+ var edge = navigator.userAgent.match(/Edge\/(\d+)/i);
+ if (edge && edge.length > 1) edge = edge[1];
+
+ var ms = Neo.isIE();
+
+ var str = "";
+ if (futaba || samplebbs) {
+ if (ms || (edge && edge < 15)) {
+ str = Neo.translate("ã“ã®ãƒ–ラウザã§ã¯<br>投稿ã«å¤±æ•—ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™<br>");
+ }
+ }
+
+ // ã‚‚ã—<PARAM NAME="neo_warning" VALUE="...">ãŒã‚ã‚Œã°è¡¨ç¤ºã™ã‚‹
+ if (Neo.config.neo_warning) {
+ str += Neo.config.neo_warning;
+ }
+
+ var warning = document.getElementById("neoWarning")
+ warning.innerHTML = str;
+ setTimeout(function() { warning.style.opacity = "0"; }, 15000);
+};
+
+/*
+ -----------------------------------------------------------------------
+ UIã®æ›´æ–°
+ -----------------------------------------------------------------------
+*/
+
+Neo.updateUI = function() {
+ var current = Neo.painter.tool.getToolButton();
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ if (current) {
+ if (current == toolTip) {
+ toolTip.setSelected(true);
+ toolTip.update();
+ } else {
+ toolTip.setSelected(false);
+ }
+ }
+ }
+ if (Neo.drawTip) {
+ Neo.drawTip.update();
+ }
+
+ Neo.updateUIColor(true, false);
+}
+
+Neo.updateUIColor = function(updateSlider, updateColorTip) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.update();
+ }
+
+ if (updateSlider) {
+ for (var i = 0; i < Neo.sliders.length; i++) {
+ var slider = Neo.sliders[i];
+ slider.update();
+ }
+ }
+
+ // パレットを変更ã™ã‚‹ã¨ã
+ if (updateColorTip) {
+ var colorTip = Neo.ColorTip.getCurrent();
+ if (colorTip) {
+ colorTip.setColor(Neo.painter.foregroundColor);
+ }
+ }
+};
+
+/*
+ -----------------------------------------------------------------------
+ リサイズ対応
+ -----------------------------------------------------------------------
+*/
+
+Neo.updateWindow = function() {
+ if (Neo.fullScreen) {
+ document.getElementById("windowView").style.display = "block";
+ document.getElementById("windowView").appendChild(Neo.container);
+
+ } else {
+ document.getElementById("windowView").style.display = "none";
+ document.getElementById("pageView").appendChild(Neo.container);
+ }
+ Neo.resizeCanvas();
+};
+
+Neo.resizeCanvas = function() {
+ var appletWidth = Neo.container.clientWidth;
+ var appletHeight = Neo.container.clientHeight;
+
+ var canvasWidth = Neo.painter.canvasWidth;
+ var canvasHeight = Neo.painter.canvasHeight;
+
+ var width0 = canvasWidth * Neo.painter.zoom;
+ var height0 = canvasHeight * Neo.painter.zoom;
+
+ var width = (width0 < appletWidth - 100) ? width0 : appletWidth - 100;
+ var height = (height0 < appletHeight - 120) ? height0 : appletHeight - 120;
+
+ //width, heightã¯å¶æ•°ã§ãªã„ã¨èª¤å·®ãŒå‡ºã‚‹ãŸã‚
+ width = Math.floor(width / 2) * 2;
+ height = Math.floor(height / 2) * 2;
+
+ Neo.painter.destWidth = width;
+ Neo.painter.destHeight = height;
+
+ Neo.painter.destCanvas.width = width;
+ Neo.painter.destCanvas.height = height;
+ Neo.painter.destCanvasCtx = Neo.painter.destCanvas.getContext("2d");
+ Neo.painter.destCanvasCtx.imageSmoothingEnabled = false;
+ Neo.painter.destCanvasCtx.mozImageSmoothingEnabled = false;
+
+ Neo.canvas.style.width = width + "px";
+ Neo.canvas.style.height = height + "px";
+
+ var top = (Neo.container.clientHeight - toolsWrapper.clientHeight) / 2;
+ Neo.toolsWrapper.style.top = ((top > 0) ? top : 0) + "px";
+
+ if (top < 0) {
+ var s = Neo.container.clientHeight / toolsWrapper.clientHeight;
+ Neo.toolsWrapper.style.transform =
+ "translate(0, " + top + "px) scale(1," + s + ")";
+ } else {
+ Neo.toolsWrapper.style.transform = "";
+ }
+
+ Neo.painter.setZoom(Neo.painter.zoom);
+ Neo.painter.updateDestCanvas(0, 0, canvasWidth, canvasHeight);
+};
+
+/*
+ -----------------------------------------------------------------------
+ 投稿
+ -----------------------------------------------------------------------
+*/
+
+Neo.clone = function(src) {
+ var dst = {};
+ for (var k in src) {
+ dst[k] = src[k];
+ }
+ return dst;
+};
+
+Neo.getSizeString = function(len) {
+ var result = String(len);
+ while (result.length < 8) {
+ result = "0" + result;
+ }
+ return result;
+};
+
+Neo.openURL = function(url) {
+ if (Neo.isApp) {
+ require('electron').shell.openExternal(url);
+
+ } else {
+ window.open(url, '_blank');
+ }
+};
+
+Neo.submit = function(board, blob, thumbnail, thumbnail2) {
+ var url = Neo.config.url_save;
+ var headerString = Neo.str_header || "";
+ console.log("submit url=" + url + " header=" + headerString);
+
+ if (document.paintBBSCallback) {
+ var result = document.paintBBSCallback('check')
+ if (result == 0 || result == "false") {
+ return;
+ }
+
+ result = document.paintBBSCallback('header')
+ if (result && typeof result == "string") {
+ headerString == result;
+ }
+ }
+ if (!headerString) headerString = Neo.config.send_header || "";
+
+ var imageType = Neo.config.send_header_image_type;
+ if (imageType && imageType == "true") {
+ headerString = "image_type=png&" + headerString
+ console.log("header=" + headerString);
+ }
+
+ var header = new Blob([headerString]);
+ var headerLength = this.getSizeString(header.size);
+ var imgLength = this.getSizeString(blob.size);
+
+ var array = ['P', // PaintBBS
+ headerLength,
+ header,
+ imgLength,
+ '\r\n',
+ blob];
+
+ if (thumbnail) {
+ var thumbnailLength = this.getSizeString(thumbnail.size);
+ array.push(thumbnailLength, thumbnail);
+ }
+ if (thumbnail2) {
+ var thumbnail2Length = this.getSizeString(thumbnail2.size);
+ array.push(thumbnail2Length, thumbnail2);
+ }
+
+ var body = new Blob(array, {type: 'application/octet-binary'}); //ã“ã‚ŒãŒå¿…è¦ï¼ï¼
+
+ var request = new XMLHttpRequest();
+ request.open("POST", url, true);
+
+ request.onload = function(e) {
+ console.log(request.response);
+ Neo.uploaded = true;
+
+ /*var url = Neo.config.url_exit;
+ if (url[0] == '/') {
+ url = url.replace(/^.*\//, ''); //よãã‚ã‹ã‚“ãªã„ã‘ã©ã¨ã‚Šã‚ãˆãš
+ }
+
+ // ãµãŸã°ã®paintpost.phpã¯ã€ç”»åƒæŠ•ç¨¿ã«æˆåŠŸã™ã‚‹ã¨responseã«
+ // "./futaba.php?mode=paintcom&amp;painttmp=.png"
+ // ã¨ã„ã†æ–‡å­—列を返ã—ã¾ã™ã€‚
+ //
+ // NEOã§ã¯ã€responseã«æ–‡å­—列"painttmp="ãŒå«ã¾ã‚Œã‚‹å ´åˆã¯
+ // <PARAM>ã§æŒ‡å®šã•ã‚ŒãŸurl_exitを無視ã—ã¦ã€ã“ã®URLã«ã‚¸ãƒ£ãƒ³ãƒ—ã—ã¾ã™ã€‚
+ var responseURL = request.response.replace(/&amp;/g, '&');
+ if (responseURL.match(/painttmp=/)) {
+ url = responseURL;
+ }
+ var exitURL = url;
+
+ // ã—ãƒã¡ã‚ƒã‚“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’よã見ãŸã‚‰
+ // response㌠"URL:〜" ã®å½¢ã ã£ãŸå ´åˆã¯ãã“ã¸é£›ã°ã™ã£ã¦æ›¸ã„ã¦ã‚ã‚Šã¾ã—ãŸã€‚
+ // ã“ã£ã¡ã‚’使ã†ã¹ãã§ã—ãŸâ€¦â€¦
+ if (responseURL.match(/^URL:/)) {
+ exitURL = responseURL.replace(/^URL:/, '');
+ }
+
+ location.href = exitURL;*/
+ location.href = Neo.config.url_exit;
+ };
+ request.onerror = function(e) {
+ console.log("error");
+ };
+ request.onabort = function(e) {
+ console.log("abort");
+ };
+ request.ontimeout = function(e) {
+ console.log("timeout");
+ };
+
+ request.send(body);
+};
+
+/*
+ -----------------------------------------------------------------------
+ LiveConnect
+ -----------------------------------------------------------------------
+*/
+
+Neo.getColors = function() {
+ console.log("getColors")
+ console.log("defaultColors==", Neo.config.colors.join('\n'));
+ var array = []
+ for (var i = 0; i < 14; i++) {
+ array.push(Neo.colorTips[i].color)
+ }
+ return array.join('\n');
+ // return Neo.config.colors.join('\n');
+};
+
+Neo.setColors = function(colors) {
+ console.log("setColors");
+ var array = colors.split('\n');
+ for (var i = 0; i < 14; i++) {
+ var color = array[i];
+ Neo.config.colors[i] = color;
+ Neo.colorTips[i].setColor(color);
+ }
+};
+
+
+Neo.pExit = function() {
+ new Neo.SubmitCommand(Neo.painter).execute();
+};
+
+Neo.str_header = "";
+
+/*
+ -----------------------------------------------------------------------
+ DOMツリーã®ä½œæˆ
+ -----------------------------------------------------------------------
+*/
+
+Neo.createContainer = function(applet) {
+ var neo = document.createElement("div");
+ neo.className = "NEO";
+ neo.id = "NEO";
+ var html = (function() {/*
+
+<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
+
+<div id="pageView" style="width:450px; height:470px; margin:auto;">
+<div id="container" style="visibility:hidden;" class="o">
+<div id="center" class="o">
+<div id="painterContainer" class="o">
+<div id="painterWrapper" class="o">
+<div id="upper" class="o">
+<div id="redo">[ã‚„ã‚Šç›´ã—]</div>
+<div id="undo">[å…ƒã«æˆ»ã™]</div>
+<div id="fill">[å¡—ã‚Šæ½°ã—]</div>
+<div id="right" style="display:none;">[å³]</div>
+</div>
+<div id="painter">
+<div id="canvas"> <!-- class="o">-->
+<div id="scrollH"></div>
+<div id="scrollV"></div>
+<div id="zoomPlusWrapper">
+<div id="zoomPlus">+</div>
+</div>
+<div id="zoomMinusWrapper">
+<div id="zoomMinus">-</div>
+</div>
+<div id="neoWarning"></div>
+</div>
+</div>
+<div id="lower" class="o">
+</div>
+</div>
+<div id="toolsWrapper">
+<div id="tools">
+<div id="toolSet">
+<div id="pen"></div>
+<div id="pen2"></div>
+<div id="effect"></div>
+<div id="effect2"></div>
+<div id="eraser"></div>
+<div id="draw"></div>
+<div id="mask"></div>
+
+<div class="colorTips">
+<div id="color2"></div><div id="color1"></div><br>
+<div id="color4"></div><div id="color3"></div><br>
+<div id="color6"></div><div id="color5"></div><br>
+<div id="color8"></div><div id="color7"></div><br>
+<div id="color10"></div><div id="color9"></div><br>
+<div id="color12"></div><div id="color11"></div><br>
+<div id="color14"></div><div id="color13"></div>
+</div>
+
+<div id="sliderRed"></div>
+<div id="sliderGreen"></div>
+<div id="sliderBlue"></div>
+<div id="sliderAlpha"></div>
+<div id="sliderSize"></div>
+
+<div class="reserveControl" style="margin-top:4px;">
+<div id="reserve1"></div>
+<div id="reserve2"></div>
+<div id="reserve3"></div>
+</div>
+<div id="layerControl" style="margin-top:6px;"></div>
+
+<!--<div id="toolPad" style="height:20px;"></div>-->
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="headerButtons">
+<div id="window">[窓]</div>
+</div>
+<div id="footerButtons">
+<div id="submit">[投稿]</div>
+<div id="copyright">[(C)ã—ãƒã¡ã‚ƒã‚“ PaintBBS NEO]</div>
+</div>
+</div>
+</div>
+
+<div id="windowView" style="display: none;">
+
+</div>
+
+
+ */}).toString().match(/\/\*([^]*)\*\//)[1];
+
+ neo.innerHTML = html.replace(/\[(.*?)\]/g, function(match, str) {
+ return Neo.translate(str)
+ })
+
+ var parent = applet.parentNode;
+ parent.appendChild(neo);
+ parent.insertBefore(neo, applet);
+
+ // applet.style.display = "none";
+
+ // NEOを組ã¿è¾¼ã‚“ã URLをアプリ版ã§é–‹ãã¨DOMツリーãŒ2é‡ã«ã§ãã¦æ ¼å¥½æ‚ªã„ã®ã§æ¶ˆã—ã¦ãŠã
+ setTimeout(function() {
+ var tmp = document.getElementsByClassName("NEO");
+ if (tmp.length > 1) {
+ for (var i = 1; i < tmp.length; i++) {
+ tmp[i].style.display = "none";
+ }
+ }
+ }, 0);
+};
+
+
+'use strict';
+
+Neo.dictionary = {
+ "ja": {},
+ "en": {
+ "ã‚„ã‚Šç›´ã—": "Redo",
+ "å…ƒã«æˆ»ã™": "Undo",
+ "å¡—ã‚Šæ½°ã—": "Paint",
+ "窓": "F&nbsp;",
+ "投稿": "Send",
+ "(C)ã—ãƒã¡ã‚ƒã‚“ PaintBBS NEO": "(C)shi-chan PaintBBS NEO",
+ "鉛筆": "Solid",
+ "水彩": "WaterC",
+ "テキスト": "Text",
+ "トーン": "Tone",
+ "ã¼ã‹ã—": "ShadeOff",
+ "覆ã„焼ã": "HLight",
+ "焼ãè¾¼ã¿": "Dark",
+ "消ã—ペン": "White",
+ "消ã—四角": "WhiteRect",
+ "全消ã—": "Clear",
+ "四角": "Rect",
+ "線四角": "LineRect",
+ "楕円": "Oval",
+ "線楕円": "LineOval",
+ "コピー": "Copy",
+ "レイヤçµåˆ": "lay-unif",
+ "角å–ã‚Š": "Antialias",
+ "å·¦å³å転": "reverseL",
+ "上下å転": "reverseU",
+ "傾ã‘": "lie",
+ "通常": "Normal",
+ "マスク": "Mask",
+ "逆ï¾ï½½ï½¸": "ReMask",
+ "加算": "And",
+ "逆加算": "Div",
+ "手書ã": "FreeLine",
+ "ç›´ç·š": "Straight",
+ "BZ曲線": "Bezie",
+ "ページビュー?": "Page view?",
+ "ウィンドウビュー?": "Window view?",
+ "以å‰ã®ç·¨é›†ãƒ‡ãƒ¼ã‚¿ã‚’復元ã—ã¾ã™ã‹ï¼Ÿ": "Restore session?",
+ "å³": "Right Click",
+
+ "PaintBBS NEOã¯ã€ãŠçµµæãã—ãƒæŽ²ç¤ºæ¿ PaintBBS (©2000-2004 ã—ãƒã¡ã‚ƒã‚“) ã‚’html5化ã™ã‚‹ãƒ—ロジェクトã§ã™ã€‚\n\nPaintBBS NEOã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã—ã¾ã™ã‹ï¼Ÿ": "PaintBBS NEO is an HTML5 port of Oekaki Shi-BBS PaintBBS (©2000-2004 shi-chan). Show the project page?",
+ "ã“ã®ãƒ–ラウザã§ã¯<br>投稿ã«å¤±æ•—ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™<br>": "This browser may fail to send your picture.<br>",
+ },
+ "enx": {
+ "ã‚„ã‚Šç›´ã—": "Redo",
+ "å…ƒã«æˆ»ã™": "Undo",
+ "å¡—ã‚Šæ½°ã—": "Fill",
+ "窓": "Float",
+ "投稿": "Send",
+ "(C)ã—ãƒã¡ã‚ƒã‚“ PaintBBS NEO": "&copy;shi-cyan PaintBBS NEO",
+ "鉛筆": "Solid",
+ "水彩": "WaterCo",
+ "テキスト": "Text",
+ "トーン": "Halftone",
+ "ã¼ã‹ã—": "Blur",
+ "覆ã„焼ã": "Light",
+ "焼ãè¾¼ã¿": "Dark",
+ "消ã—ペン": "White",
+ "消ã—四角": "WhiteRe",
+ "全消ã—": "Clear",
+ "四角": "Rect",
+ "線四角": "LineRect",
+ "楕円": "Oval",
+ "線楕円": "LineOval",
+ "コピー": "Copy",
+ "レイヤçµåˆ": "layerUnit",
+ "角å–ã‚Š": "antiAlias",
+ "å·¦å³å転": "flipHorita",
+ "上下å転": "flipVertic",
+ "傾ã‘": "rotate",
+ "通常": "Normal",
+ "マスク": "Mask",
+ "逆ï¾ï½½ï½¸": "ReMask",
+ "加算": "And",
+ "逆加算": "Divide",
+ "手書ã": "Freehan",
+ "ç›´ç·š": "Line",
+ "BZ曲線": "Bezier",
+ "Layer0": "LayerBG",
+ "Layer1": "LayerFG",
+ "ページビュー?": "Page view?",
+ "ウィンドウビュー?": "Window view?",
+ "以å‰ã®ç·¨é›†ãƒ‡ãƒ¼ã‚¿ã‚’復元ã—ã¾ã™ã‹ï¼Ÿ": "Restore session?",
+ "å³": "Right Click",
+
+ "PaintBBS NEOã¯ã€ãŠçµµæãã—ãƒæŽ²ç¤ºæ¿ PaintBBS (©2000-2004 ã—ãƒã¡ã‚ƒã‚“) ã‚’html5化ã™ã‚‹ãƒ—ロジェクトã§ã™ã€‚\n\nPaintBBS NEOã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã—ã¾ã™ã‹ï¼Ÿ": "PaintBBS NEO is an HTML5 port of Oekaki Shi-BBS PaintBBS (©2000-2004 shi-chan). Show the project page?",
+ "ã“ã®ãƒ–ラウザã§ã¯<br>投稿ã«å¤±æ•—ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™<br>": "This browser may fail to send your picture.<br>",
+ },
+ "es": {
+ "ã‚„ã‚Šç›´ã—": "Rehacer",
+ "å…ƒã«æˆ»ã™": "Deshacer",
+ "å¡—ã‚Šæ½°ã—": "Llenar",
+ "窓": "Ventana",
+ "投稿": "Enviar",
+ "(C)ã—ãƒã¡ã‚ƒã‚“ PaintBBS NEO": "&copy;shi-cyan PaintBBS NEO",
+ "鉛筆": "Lápiz",
+ "水彩": "Acuarela",
+ "テキスト": "Texto",
+ "トーン": "Tono",
+ "ã¼ã‹ã—": "Gradación",
+ "覆ã„焼ã": "Sobreexp.",
+ "焼ãè¾¼ã¿": "Quemar",
+ "消ã—ペン": "Goma",
+ "消ã—四角": "GomaRect",
+ "全消ã—": "Borrar",
+ "四角": "Rect",
+ "線四角": "LíneaRect",
+ "楕円": "Óvalo",
+ "線楕円": "LíneaÓvalo",
+ "コピー": "Copiar",
+ "レイヤçµåˆ": "UnirCapa",
+ "角å–ã‚Š": "Antialias",
+ "å·¦å³å転": "Inv.Izq/Der",
+ "上下å転": "Inv.Arr/Aba",
+ "傾ã‘": "Inclinar",
+ "通常": "Normal",
+ "マスク": "Masc.",
+ "逆ï¾ï½½ï½¸": "Masc.Inv",
+ "加算": "Adición",
+ "逆加算": "Subtrac",
+ "手書ã": "Libre",
+ "直線": "Línea",
+ "BZ曲線": "Curva",
+ "Layer0": "Capa0",
+ "Layer1": "Capa1",
+ "ページビュー?": "¿Vista de página?",
+ "ウィンドウビュー?": "¿Vista de ventana?",
+ "以å‰ã®ç·¨é›†ãƒ‡ãƒ¼ã‚¿ã‚’復元ã—ã¾ã™ã‹ï¼Ÿ": "¿Restaurar sesión anterior?",
+ "å³": "Clic derecho",
+
+ "PaintBBS NEOã¯ã€ãŠçµµæãã—ãƒæŽ²ç¤ºæ¿ PaintBBS (©2000-2004 ã—ãƒã¡ã‚ƒã‚“) ã‚’html5化ã™ã‚‹ãƒ—ロジェクトã§ã™ã€‚\n\nPaintBBS NEOã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã—ã¾ã™ã‹ï¼Ÿ":
+ "PaintBBS NEO es una versión para HTML5 de Oekaki Shi-BBS PaintBBS (© 2000-2004 shi-chan). ¿Mostrar la página del proyecto?",
+ "ã“ã®ãƒ–ラウザã§ã¯<br>投稿ã«å¤±æ•—ã™ã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™<br>": "Este navegador podría no enviar su imagen.<br>",
+ },
+};
+
+Neo.translate = function () {
+ var language = (window.navigator.languages && window.navigator.languages[0]) ||
+ window.navigator.language ||
+ window.navigator.userLanguage ||
+ window.navigator.browserLanguage;
+
+ var lang = "en";
+ for (var key in Neo.dictionary) {
+ if (language.indexOf(key) == 0) {
+ lang = key;
+ break;
+ }
+ }
+
+ return function(string) {
+ if (Neo.config.neo_alt_translation) {
+ if (lang == "en") lang = "enx"
+ } else {
+ if (lang != "ja") lang = "en"
+ }
+ return Neo.dictionary[lang][string] || string;
+ }
+}();
+
+
+'use strict';
+
+Neo.Painter = function() {
+ this._undoMgr = new Neo.UndoManager(50);
+};
+
+Neo.Painter.prototype.container;
+Neo.Painter.prototype._undoMgr;
+Neo.Painter.prototype.tool;
+Neo.Painter.prototype.inputText;
+
+//Canvas Info
+Neo.Painter.prototype.canvasWidth;
+Neo.Painter.prototype.canvasHeight;
+Neo.Painter.prototype.canvas = [];
+Neo.Painter.prototype.canvasCtx = [];
+Neo.Painter.prototype.visible = [];
+Neo.Painter.prototype.current = 0;
+
+//Temp Canvas Info
+Neo.Painter.prototype.tempCanvas;
+Neo.Painter.prototype.tempCanvasCtx;
+Neo.Painter.prototype.tempX = 0;
+Neo.Painter.prototype.tempY = 0;
+
+//Destination Canvas for display
+Neo.Painter.prototype.destCanvas;
+Neo.Painter.prototype.destCanvasCtx;
+
+
+Neo.Painter.prototype.backgroundColor = "#ffffff";
+Neo.Painter.prototype.foregroundColor = "#000000";
+
+Neo.Painter.prototype.lineWidth = 1;
+Neo.Painter.prototype.alpha = 1;
+Neo.Painter.prototype.zoom = 1;
+Neo.Painter.prototype.zoomX = 0;
+Neo.Painter.prototype.zoomY = 0;
+
+Neo.Painter.prototype.isMouseDown;
+Neo.Painter.prototype.isMouseDownRight;
+Neo.Painter.prototype.prevMouseX;
+Neo.Painter.prototype.prevMouseY;
+Neo.Painter.prototype.mouseX;
+Neo.Painter.prototype.mouseY;
+
+Neo.Painter.prototype.slowX = 0;
+Neo.Painter.prototype.slowY = 0;
+Neo.Painter.prototype.stab = null;
+
+Neo.Painter.prototype.isShiftDown = false;
+Neo.Painter.prototype.isCtrlDown = false;
+Neo.Painter.prototype.isAltDown = false;
+
+//Neo.Painter.prototype.touchModifier = null;
+Neo.Painter.prototype.virtualRight = false;
+Neo.Painter.prototype.virtualShift = false;
+
+//Neo.Painter.prototype.onUpdateCanvas;
+Neo.Painter.prototype._roundData = [];
+Neo.Painter.prototype._toneData = [];
+Neo.Painter.prototype.toolStack = [];
+
+Neo.Painter.prototype.maskType = 0;
+Neo.Painter.prototype.drawType = 0;
+Neo.Painter.prototype.maskColor = "#000000";
+Neo.Painter.prototype._currentColor = [];
+Neo.Painter.prototype._currentMask = [];
+
+Neo.Painter.prototype.aerr;
+
+Neo.Painter.LINETYPE_NONE = 0;
+Neo.Painter.LINETYPE_PEN = 1;
+Neo.Painter.LINETYPE_ERASER = 2;
+Neo.Painter.LINETYPE_BRUSH = 3;
+Neo.Painter.LINETYPE_TONE = 4;
+Neo.Painter.LINETYPE_DODGE = 5;
+Neo.Painter.LINETYPE_BURN = 6;
+
+Neo.Painter.MASKTYPE_NONE = 0;
+Neo.Painter.MASKTYPE_NORMAL = 1;
+Neo.Painter.MASKTYPE_REVERSE = 2;
+Neo.Painter.MASKTYPE_ADD = 3;
+Neo.Painter.MASKTYPE_SUB = 4;
+
+Neo.Painter.DRAWTYPE_FREEHAND = 0;
+Neo.Painter.DRAWTYPE_LINE = 1;
+Neo.Painter.DRAWTYPE_BEZIER = 2;
+
+Neo.Painter.ALPHATYPE_NONE = 0;
+Neo.Painter.ALPHATYPE_PEN = 1;
+Neo.Painter.ALPHATYPE_FILL = 2;
+Neo.Painter.ALPHATYPE_BRUSH = 3;
+
+Neo.Painter.TOOLTYPE_NONE = 0;
+Neo.Painter.TOOLTYPE_PEN = 1;
+Neo.Painter.TOOLTYPE_ERASER = 2;
+Neo.Painter.TOOLTYPE_HAND = 3;
+Neo.Painter.TOOLTYPE_SLIDER = 4;
+Neo.Painter.TOOLTYPE_FILL = 5;
+Neo.Painter.TOOLTYPE_MASK = 6;
+Neo.Painter.TOOLTYPE_ERASEALL = 7;
+Neo.Painter.TOOLTYPE_ERASERECT = 8;
+Neo.Painter.TOOLTYPE_COPY = 9;
+Neo.Painter.TOOLTYPE_PASTE = 10;
+Neo.Painter.TOOLTYPE_MERGE = 11;
+Neo.Painter.TOOLTYPE_FLIP_H = 12;
+Neo.Painter.TOOLTYPE_FLIP_V = 13;
+
+Neo.Painter.TOOLTYPE_BRUSH = 14;
+Neo.Painter.TOOLTYPE_TEXT = 15;
+Neo.Painter.TOOLTYPE_TONE = 16;
+Neo.Painter.TOOLTYPE_BLUR = 17;
+Neo.Painter.TOOLTYPE_DODGE = 18;
+Neo.Painter.TOOLTYPE_BURN = 19;
+Neo.Painter.TOOLTYPE_RECT = 20;
+Neo.Painter.TOOLTYPE_RECTFILL = 21;
+Neo.Painter.TOOLTYPE_ELLIPSE = 22;
+Neo.Painter.TOOLTYPE_ELLIPSEFILL = 23;
+Neo.Painter.TOOLTYPE_BLURRECT = 24;
+Neo.Painter.TOOLTYPE_TURN = 25;
+
+Neo.Painter.prototype.build = function(div, width, height)
+{
+ this.container = div;
+ this._initCanvas(div, width, height);
+ this._initRoundData();
+ this._initToneData();
+ this._initInputText();
+
+ this.setTool(new Neo.PenTool());
+
+};
+
+Neo.Painter.prototype.setTool = function(tool) {
+ if (this.tool && this.tool.saveStates) this.tool.saveStates();
+
+ if (this.tool && this.tool.kill) {
+ this.tool.kill();
+ }
+ this.tool = tool;
+ tool.init();
+ if (this.tool && this.tool.loadStates) this.tool.loadStates();
+};
+
+Neo.Painter.prototype.pushTool = function(tool) {
+ this.toolStack.push(this.tool);
+ this.tool = tool;
+ tool.init();
+};
+
+Neo.Painter.prototype.popTool = function() {
+ var tool = this.tool;
+ if (tool && tool.kill) {
+ tool.kill();
+ }
+ this.tool = this.toolStack.pop();
+};
+
+Neo.Painter.prototype.getCurrentTool = function() {
+ if (this.tool) {
+ var tool = this.tool;
+ if (tool && tool.type == Neo.Painter.TOOLTYPE_SLIDER) {
+ var stack = this.toolStack;
+ if (stack.length > 0) {
+ tool = stack[stack.length - 1];
+ }
+ }
+ return tool;
+ }
+ return null;
+};
+
+Neo.Painter.prototype.setToolByType = function(toolType) {
+ switch (parseInt(toolType)) {
+ case Neo.Painter.TOOLTYPE_PEN: this.setTool(new Neo.PenTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASER: this.setTool(new Neo.EraserTool()); break;
+ case Neo.Painter.TOOLTYPE_HAND: this.setTool(new Neo.HandTool()); break;
+ case Neo.Painter.TOOLTYPE_FILL: this.setTool(new Neo.FillTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASEALL: this.setTool(new Neo.EraseAllTool()); break;
+ case Neo.Painter.TOOLTYPE_ERASERECT: this.setTool(new Neo.EraseRectTool()); break;
+
+ case Neo.Painter.TOOLTYPE_COPY: this.setTool(new Neo.CopyTool()); break;
+ case Neo.Painter.TOOLTYPE_PASTE: this.setTool(new Neo.PasteTool()); break;
+ case Neo.Painter.TOOLTYPE_MERGE: this.setTool(new Neo.MergeTool()); break;
+ case Neo.Painter.TOOLTYPE_FLIP_H: this.setTool(new Neo.FlipHTool()); break;
+ case Neo.Painter.TOOLTYPE_FLIP_V: this.setTool(new Neo.FlipVTool()); break;
+
+ case Neo.Painter.TOOLTYPE_BRUSH: this.setTool(new Neo.BrushTool()); break;
+ case Neo.Painter.TOOLTYPE_TEXT: this.setTool(new Neo.TextTool()); break;
+ case Neo.Painter.TOOLTYPE_TONE: this.setTool(new Neo.ToneTool()); break;
+ case Neo.Painter.TOOLTYPE_BLUR: this.setTool(new Neo.BlurTool()); break;
+ case Neo.Painter.TOOLTYPE_DODGE: this.setTool(new Neo.DodgeTool()); break;
+ case Neo.Painter.TOOLTYPE_BURN: this.setTool(new Neo.BurnTool()); break;
+
+ case Neo.Painter.TOOLTYPE_RECT: this.setTool(new Neo.RectTool()); break;
+ case Neo.Painter.TOOLTYPE_RECTFILL: this.setTool(new Neo.RectFillTool()); break;
+ case Neo.Painter.TOOLTYPE_ELLIPSE: this.setTool(new Neo.EllipseTool()); break;
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:this.setTool(new Neo.EllipseFillTool()); break;
+ case Neo.Painter.TOOLTYPE_BLURRECT: this.setTool(new Neo.BlurRectTool()); break;
+ case Neo.Painter.TOOLTYPE_TURN: this.setTool(new Neo.TurnTool()); break;
+
+ default:
+ console.log("unknown toolType " + toolType);
+ break;
+ }
+};
+
+Neo.Painter.prototype._initCanvas = function(div, width, height) {
+ width = parseInt(width);
+ height = parseInt(height);
+ var destWidth = parseInt(div.clientWidth);
+ var destHeight = parseInt(div.clientHeight);
+ this.destWidth = width;
+ this.destHeight = height;
+
+ this.canvasWidth = width;
+ this.canvasHeight = height;
+ this.zoomX = width * 0.5;
+ this.zoomY = height * 0.5;
+
+ for (var i = 0; i < 2; i++) {
+ this.canvas[i] = document.createElement("canvas");
+ this.canvas[i].width = width;
+ this.canvas[i].height = height;
+ this.canvasCtx[i] = this.canvas[i].getContext("2d");
+
+ this.canvas[i].style.imageRendering = "pixelated";
+ this.canvasCtx[i].imageSmoothingEnabled = false;
+ this.canvasCtx[i].mozImageSmoothingEnabled = false;
+ this.visible[i] = true;
+ }
+
+ this.tempCanvas = document.createElement("canvas");
+ this.tempCanvas.width = width;
+ this.tempCanvas.height = height;
+ this.tempCanvasCtx = this.tempCanvas.getContext("2d");
+ this.tempCanvas.style.position = "absolute";
+ this.tempCanvas.enabled = false;
+
+ var array = this.container.getElementsByTagName("canvas");
+ if (array.length > 0) {
+ this.destCanvas = array[0];
+ } else {
+ this.destCanvas = document.createElement("canvas");
+ this.container.appendChild(this.destCanvas);
+ }
+
+ this.destCanvasCtx = this.destCanvas.getContext("2d");
+ this.destCanvas.width = destWidth;
+ this.destCanvas.height = destHeight;
+
+ this.destCanvas.style.imageRendering = "pixelated";
+ this.destCanvasCtx.imageSmoothingEnabled = false;
+ this.destCanvasCtx.mozImageSmoothingEnabled = false;
+
+ var ref = this;
+
+ var container = document.getElementById("container");
+
+ container.onmousedown = function(e) {ref._mouseDownHandler(e)};
+ container.onmousemove = function(e) {ref._mouseMoveHandler(e)};
+ container.onmouseup = function(e) {ref._mouseUpHandler(e)};
+ container.onmouseover = function(e) {ref._rollOverHandler(e)};
+ container.onmouseout = function(e) {ref._rollOutHandler(e)};
+ container.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ }, false);
+ container.addEventListener("touchmove", function(e) {
+ ref._mouseMoveHandler(e);
+ }, false);
+ container.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, false);
+
+ document.onkeydown = function(e) {ref._keyDownHandler(e)};
+ document.onkeyup = function(e) {ref._keyUpHandler(e)};
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype._initRoundData = function() {
+ for (var r = 1; r <= 30; r++) {
+ this._roundData[r] = new Uint8Array(r * r);
+ var mask = this._roundData[r];
+ var d = Math.floor(r / 2.0);
+ var index = 0;
+ for (var x = 0; x < r; x++) {
+ for (var y = 0; y < r; y++) {
+ var xx = x + 0.5 - r/2.0;
+ var yy = y + 0.5 - r/2.0;
+ mask[index++] = (xx*xx + yy*yy <= r*r/4) ? 1 : 0;
+ }
+ }
+ }
+ this._roundData[3][0] = 0;
+ this._roundData[3][2] = 0;
+ this._roundData[3][6] = 0;
+ this._roundData[3][8] = 0;
+
+ this._roundData[5][1] = 0;
+ this._roundData[5][3] = 0;
+ this._roundData[5][5] = 0;
+ this._roundData[5][9] = 0;
+ this._roundData[5][15] = 0;
+ this._roundData[5][19] = 0;
+ this._roundData[5][21] = 0;
+ this._roundData[5][23] = 0;
+};
+
+Neo.Painter.prototype._initToneData = function() {
+ var pattern = [0, 8, 2, 10, 12, 4, 14, 6, 3, 11, 1, 9, 15, 7, 13, 5];
+
+ for (var i = 0; i < 16; i++) {
+ this._toneData[i] = new Uint8Array(16);
+ for (var j = 0; j < 16; j++) {
+ this._toneData[i][j] = (i >= pattern[j]) ? 1 : 0;
+ }
+ }
+};
+
+Neo.Painter.prototype.getToneData = function(alpha) {
+ var alphaTable = [23,
+ 47,
+ 69,
+ 92,
+ 114,
+ 114,
+ 114,
+ 138,
+ 161,
+ 184,
+ 184,
+ 207,
+ 230,
+ 230,
+ 253,
+ ];
+
+ for (var i = 0; i < alphaTable.length; i++) {
+ if (alpha < alphaTable[i]) {
+ return this._toneData[i];
+ }
+ }
+ return this._toneData[i];
+};
+
+Neo.Painter.prototype._initInputText = function() {
+ var text = document.getElementById("inputtext");
+ if (!text) {
+ text = document.createElement("div");
+ }
+
+ text.id = "inputext";
+ text.setAttribute("contentEditable", true);
+ text.spellcheck = false;
+ text.className = "inputText";
+ text.innerHTML = "";
+
+ text.style.display = "none";
+// text.style.userSelect = "none";
+ Neo.painter.container.appendChild(text);
+ this.inputText = text;
+
+ this.updateInputText();
+};
+
+Neo.Painter.prototype.hideInputText = function() {
+ var text = this.inputText;
+ text.blur();
+ text.style.display = "none";
+};
+
+Neo.Painter.prototype.updateInputText = function() {
+ var text = this.inputText;
+ var d = this.lineWidth;
+ var fontSize = Math.round(d * 55/28 + 7);
+ var height = Math.round(d * 68/28 + 12);
+
+ text.style.fontSize = fontSize + "px";
+ text.style.lineHeight = fontSize + "px";
+ text.style.height = fontSize + "px";
+ text.style.marginTop = -fontSize + "px";
+};
+
+/*
+-----------------------------------------------------------------------
+ Mouse Event Handling
+-----------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype._keyDownHandler = function(e) {
+ this.isShiftDown = e.shiftKey;
+ this.isCtrlDown = e.ctrlKey;
+ this.isAltDown = e.altKey;
+ if (e.keyCode == 32) this.isSpaceDown = true;
+
+ if (!this.isShiftDown && this.isCtrlDown) {
+ if (!this.isAltDown) {
+ if (e.keyCode == 90 || e.keyCode == 85) this.undo(); //Ctrl+Z,Ctrl.U
+ if (e.keyCode == 89) this.redo(); //Ctrl+Y
+ } else {
+ if (e.keyCode == 90) this.redo(); //Ctrl+Alt+Z
+ }
+ }
+
+ if (!this.isShiftDown && !this.isCtrlDown && !this.isAltDown) {
+ if (e.keyCode == 107) new Neo.ZoomPlusCommand(this).execute(); // +
+ if (e.keyCode == 109) new Neo.ZoomMinusCommand(this).execute(); // -
+ }
+
+ if (this.tool.keyDownHandler) {
+ this.tool.keyDownHandler(e);
+ }
+
+ //スペース・Shift+スペースã§ã§ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«ã—ãªã„よã†ã«
+ if (document.activeElement != this.inputText) e.preventDefault();
+};
+
+Neo.Painter.prototype._keyUpHandler = function(e) {
+ this.isShiftDown = e.shiftKey;
+ this.isCtrlDown = e.ctrlKey;
+ this.isAltDown = e.altKey;
+ if (e.keyCode == 32) this.isSpaceDown = false;
+
+ if (this.tool.keyUpHandler) {
+ this.tool.keyUpHandler(oe);
+ }
+};
+
+Neo.Painter.prototype._rollOverHandler = function(e) {
+ if (this.tool.rollOverHandler) {
+ this.tool.rollOverHandler(this);
+ }
+};
+
+Neo.Painter.prototype._rollOutHandler = function(e) {
+ if (this.tool.rollOutHandler) {
+ this.tool.rollOutHandler(this);
+ }
+};
+
+Neo.Painter.prototype._mouseDownHandler = function(e) {
+ if (e.target == Neo.painter.destCanvas) {
+ //よãã‚ã‹ã‚‰ãªã„ãŒChromeã§ãƒ‰ãƒ©ãƒƒã‚°ã®æ™‚カレットãŒå‡ºã‚‹ã®ã‚’防ã
+ //http://stackoverflow.com/questions/2745028/chrome-sets-cursor-to-text-while-dragging-why
+ e.preventDefault();
+ }
+
+ if (e.type == "touchstart" && e.touches.length > 1) return;
+
+ if (e.button == 2 || this.virtualRight) {
+ this.isMouseDownRight = true;
+
+ } else {
+ if (!e.shiftKey && e.ctrlKey && e.altKey) {
+ this.isMouseDown = true;
+
+ } else {
+ if (e.ctrlKey || e.altKey) {
+ this.isMouseDownRight = true;
+ } else {
+ this.isMouseDown = true;
+ }
+ }
+ }
+
+ this._updateMousePosition(e);
+ this.prevMouseX = this.mouseX;
+ this.prevMouseY = this.mouseY;
+
+ if (this.isMouseDownRight) {
+ this.isMouseDownRight = false;
+ if (!this.isWidget(e.target)) {
+ this.pickColor(this.mouseX, this.mouseY);
+ return;
+ }
+ }
+
+ if (!this.isUIPaused()) {
+ if (e.target['data-bar']) {
+ this.pushTool(new Neo.HandTool());
+
+ } else if (this.isSpaceDown && document.activeElement != this.inputText) {
+ this.pushTool(new Neo.HandTool());
+ this.tool.reverse = true;
+
+ } else if (e.target['data-slider'] != undefined) {
+ this.pushTool(new Neo.SliderTool());
+ this.tool.target = e.target;
+
+ } else if (e.ctrlKey && e.altKey && !e.shiftKey) {
+ this.pushTool(new Neo.SliderTool());
+ this.tool.target = Neo.sliders[Neo.SLIDERTYPE_SIZE].element;
+ this.tool.alt = true;
+
+ } else if (this.isWidget(e.target)) {
+ this.isMouseDown = false;
+ this.pushTool(new Neo.DummyTool());
+
+ }
+ }
+
+// console.warn("down -" + e.target.id + e.target.className)
+ if (!(e.target.className == "o" && e.type == "touchdown")) {
+ this.tool.downHandler(this);
+ }
+
+// var ref = this;
+// document.onmouseup = function(e) {
+// ref._mouseUpHandler(e)
+// };
+};
+
+Neo.Painter.prototype._mouseUpHandler = function(e) {
+ this.isMouseDown = false;
+ this.isMouseDownRight = false;
+ this.tool.upHandler(this);
+// document.onmouseup = undefined;
+
+ if (e.target.id != "right") {
+ this.virtualRight = false;
+ Neo.RightButton.clear();
+ }
+
+// if (e.changedTouches) {
+// for (var i = 0; i < e.changedTouches.length; i++) {
+// var touch = e.changedTouches[i];
+// if (touch.identifier == this.touchModifier) {
+// this.touchModifier = null;
+// }
+// }
+// }
+};
+
+Neo.Painter.prototype._mouseMoveHandler = function(e) {
+ this._updateMousePosition(e);
+
+ if (e.type == "touchmove" && e.touches.length > 1) return;
+
+ if (this.isMouseDown || this.isMouseDownRight) {
+ this.tool.moveHandler(this);
+
+ } else {
+ if (this.tool.upMoveHandler) {
+ this.tool.upMoveHandler(this);
+ }
+ }
+
+ this.prevMouseX = this.mouseX;
+ this.prevMouseY = this.mouseY;
+
+ // ç”»é¢å¤–をタップã—ãŸæ™‚スクロールå¯èƒ½ã«ã™ã‚‹ãŸã‚
+// console.warn("move -" + e.target.id + e.target.className)
+ if (!(e.target.className == "o" && e.type == "touchmove")) {
+ e.preventDefault();
+ }
+};
+
+
+Neo.Painter.prototype.getPosition = function(e) {
+ if (e.clientX !== undefined) {
+ return {x: e.clientX, y: e.clientY, e: e.type};
+
+ } else {
+ var touch = e.changedTouches[0];
+ return {x: touch.clientX, y: touch.clientY, e: e.type};
+
+// for (var i = 0; i < e.changedTouches.length; i++) {
+// var touch = e.changedTouches[i];
+// if (!this.touchModifier || this.touchModifier != touch.identifier) {
+// return {x: touch.clientX, y: touch.clientY, e: e.type};
+// }
+// }
+// console.log("getPosition error");
+// return {x:0, y:0};
+ }
+}
+
+Neo.Painter.prototype._updateMousePosition = function(e) {
+ var rect = this.destCanvas.getBoundingClientRect();
+// var x = (e.clientX !== undefined) ? e.clientX : e.touches[0].clientX;
+// var y = (e.clientY !== undefined) ? e.clientY : e.touches[0].clientY;
+ var pos = this.getPosition(e);
+ var x = pos.x;
+ var y = pos.y;
+
+ if (this.zoom <= 0) this.zoom = 1; //ãªãœã‹0ã«ãªã‚‹ã“ã¨ãŒã‚ã‚‹ã®ã§
+
+ this.mouseX = (x - rect.left) / this.zoom
+ + this.zoomX
+ - this.destCanvas.width * 0.5 / this.zoom;
+ this.mouseY = (y - rect.top) / this.zoom
+ + this.zoomY
+ - this.destCanvas.height * 0.5 / this.zoom;
+
+ if (isNaN(this.prevMouseX)) {
+ this.prevMouseX = this.mouseX;
+ }
+ if (isNaN(this.prevMouseY)) {
+ this.prevMosueY = this.mouseY;
+ }
+
+ this.slowX = this.slowX * 0.8 + this.mouseX * 0.2;
+ this.slowY = this.slowY * 0.8 + this.mouseY * 0.2;
+ var now = new Date().getTime();
+ if (this.stab) {
+ var pause = this.stab[3];
+ if (pause) {
+ // ãƒãƒ¼ã‚ºä¸­
+ if (now > pause) {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+
+ } else {
+ // ãƒãƒ¼ã‚ºã•ã‚Œã¦ã„ãªã„ã¨ã
+ var prev = this.stab[2];
+ if (now - prev > 150) { // 150ms以上止ã¾ã£ã¦ã„ãŸã‚‰ãƒãƒ¼ã‚ºã‚’オンã«ã™ã‚‹
+ this.stab[3] = now + 200 // 200msペンã®ä½ç½®ã‚’固定
+
+ } else {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+ }
+ } else {
+ this.stab = [this.slowX, this.slowY, now];
+ }
+
+ this.rawMouseX = x;
+ this.rawMouseY = y;
+ this.clipMouseX = Math.max(Math.min(this.canvasWidth, this.mouseX), 0);
+ this.clipMouseY = Math.max(Math.min(this.canvasHeight, this.mouseY), 0);
+};
+
+Neo.Painter.prototype._beforeUnloadHandler = function(e) {
+ // quick save
+};
+
+Neo.Painter.prototype.getStabilized = function() {
+ return this.stab;
+};
+
+/*
+-------------------------------------------------------------------------
+ Undo
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.undo = function() {
+ var undoItem = this._undoMgr.popUndo();
+ if (undoItem) {
+ this._pushRedo();
+ this.canvasCtx[0].putImageData(undoItem.data[0], undoItem.x,undoItem.y);
+ this.canvasCtx[1].putImageData(undoItem.data[1], undoItem.x,undoItem.y);
+ this.updateDestCanvas(undoItem.x, undoItem.y, undoItem.width, undoItem.height);
+ }
+};
+
+Neo.Painter.prototype.redo = function() {
+ var undoItem = this._undoMgr.popRedo();
+ if (undoItem) {
+ this._pushUndo(0,0,this.canvasWidth, this.canvasHeight, true);
+ this.canvasCtx[0].putImageData(undoItem.data[0], undoItem.x,undoItem.y);
+ this.canvasCtx[1].putImageData(undoItem.data[1], undoItem.x,undoItem.y);
+ this.updateDestCanvas(undoItem.x, undoItem.y, undoItem.width, undoItem.height);
+ }
+};
+
+Neo.Painter.prototype.hasUndo = function() {
+ return true;
+};
+
+Neo.Painter.prototype._pushUndo = function(x, y, w, h, holdRedo) {
+ x = (x === undefined) ? 0 : x;
+ y = (y === undefined) ? 0 : y;
+ w = (w === undefined) ? this.canvasWidth : w;
+ h = (h === undefined) ? this.canvasHeight : h;
+ var undoItem = new Neo.UndoItem();
+ undoItem.x = 0;
+ undoItem.y = 0;
+ undoItem.width = w;
+ undoItem.height = h;
+ undoItem.data = [this.canvasCtx[0].getImageData(x, y, w, h),
+ this.canvasCtx[1].getImageData(x, y, w, h)];
+ this._undoMgr.pushUndo(undoItem, holdRedo);
+};
+
+Neo.Painter.prototype._pushRedo = function(x, y, w, h) {
+ x = (x === undefined) ? 0 : x;
+ y = (y === undefined) ? 0 : y;
+ w = (w === undefined) ? this.canvasWidth : w;
+ h = (h === undefined) ? this.canvasHeight : h;
+ var undoItem = new Neo.UndoItem();
+ undoItem.x = 0;
+ undoItem.y = 0;
+ undoItem.width = w;
+ undoItem.height = h;
+ undoItem.data = [this.canvasCtx[0].getImageData(x, y, w, h),
+ this.canvasCtx[1].getImageData(x, y, w, h)];
+ this._undoMgr.pushRedo(undoItem);
+};
+
+
+/*
+-------------------------------------------------------------------------
+ Data Cache for Undo / Redo
+-------------------------------------------------------------------------
+*/
+
+Neo.UndoManager = function(_maxStep){
+ this._maxStep = _maxStep;
+ this._undoItems = [];
+ this._redoItems = [];
+}
+Neo.UndoManager.prototype._maxStep;
+Neo.UndoManager.prototype._redoItems;
+Neo.UndoManager.prototype._undoItems;
+
+//アクションをã—ã¦Undo情報を更新
+Neo.UndoManager.prototype.pushUndo = function(undoItem, holdRedo) {
+ this._undoItems.push(undoItem);
+ if (this._undoItems.length > this._maxStep) {
+ this._undoItems.shift();
+ }
+
+ if (!holdRedo == true) {
+ this._redoItems = [];
+ }
+};
+
+Neo.UndoManager.prototype.popUndo = function() {
+ return this._undoItems.pop();
+}
+
+Neo.UndoManager.prototype.pushRedo = function(undoItem) {
+ this._redoItems.push(undoItem);
+}
+
+Neo.UndoManager.prototype.popRedo = function() {
+ return this._redoItems.pop();
+}
+
+
+Neo.UndoItem = function() {}
+Neo.UndoItem.prototype.data;
+Neo.UndoItem.prototype.x;
+Neo.UndoItem.prototype.y;
+Neo.UndoItem.prototype.width;
+Neo.UndoItem.prototype.height;
+
+/*
+-------------------------------------------------------------------------
+ Zoom Controller
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.setZoom = function(value) {
+ this.zoom = value;
+
+ var container = document.getElementById("container");
+ var width = this.canvasWidth * this.zoom;
+ var height = this.canvasHeight * this.zoom;
+ if (width > container.clientWidth - 100) width = container.clientWidth - 100;
+ if (height > container.clientHeight - 130) height = container.clientHeight - 130;
+ this.destWidth = width;
+ this.destHeight = height;
+
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight, false);
+ this.setZoomPosition(this.zoomX, this.zoomY);
+};
+
+Neo.Painter.prototype.setZoomPosition = function(x, y) {
+ var minx = (this.destCanvas.width / this.zoom) * 0.5;
+ var maxx = this.canvasWidth - minx;
+ var miny = (this.destCanvas.height / this.zoom) * 0.5;
+ var maxy = this.canvasHeight - miny;
+
+
+ x = Math.round(Math.max(Math.min(maxx,x),minx));
+ y = Math.round(Math.max(Math.min(maxy,y),miny));
+
+ this.zoomX = x;
+ this.zoomY = y;
+ this.updateDestCanvas(0,0,this.canvasWidth,this.canvasHeight,false);
+
+ this.scrollBarX = (maxx == minx) ? 0 : (x - minx) / (maxx - minx);
+ this.scrollBarY = (maxy == miny) ? 0 : (y - miny) / (maxy - miny);
+ this.scrollWidth = maxx - minx;
+ this.scrollHeight = maxy - miny;
+
+ if (Neo.scrollH) Neo.scrollH.update(this);
+ if (Neo.scrollV) Neo.scrollV.update(this);
+
+ this.hideInputText();
+};
+
+
+/*
+-------------------------------------------------------------------------
+ Drawing Helper
+-------------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.submit = function(board) {
+ var thumbnail = null;
+ var thumbnail2 = null;
+
+ if (this.useThumbnail()) {
+ thumbnail = this.getThumbnail(Neo.config.thumbnail_type || "png");
+ if (Neo.config.thumbnail_type2) {
+ thumbnail2 = this.getThumbnail(Neo.config.thumbnail_type2);
+ }
+ }
+ Neo.submit(board, this.getPNG(), thumbnail2, thumbnail);
+};
+
+Neo.Painter.prototype.useThumbnail = function() {
+ var thumbnailWidth = this.getThumbnailWidth();
+ var thumbnailHeight = this.getThumbnailHeight();
+ if (thumbnailWidth && thumbnailHeight) {
+ if (thumbnailWidth < this.canvasWidth ||
+ thumbnailHeight < this.canvasHeight) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Neo.Painter.prototype.dataURLtoBlob = function(dataURL) {
+ var byteString;
+ if (dataURL.split(',')[0].indexOf('base64') >= 0) {
+ byteString = atob(dataURL.split(',')[1]);
+ } else {
+ byteString = unescape(dataURL.split(',')[1]);
+ }
+
+ // write the bytes of the string to a typed array
+ var ia = new Uint8Array(byteString.length);
+ for (var i = 0; i < byteString.length; i++) {
+ ia[i] = byteString.charCodeAt(i);
+ }
+ return new Blob([ia], {type:'image/png'});
+};
+
+Neo.Painter.prototype.getImage = function(imageWidth, imageHeight) {
+ var width = this.canvasWidth;
+ var height = this.canvasHeight;
+ imageWidth = imageWidth || width;
+ imageHeight = imageHeight || height;
+
+ var pngCanvas = document.createElement("canvas");
+ pngCanvas.width = imageWidth;
+ pngCanvas.height = imageHeight;
+ var pngCanvasCtx = pngCanvas.getContext("2d");
+ pngCanvasCtx.fillStyle = "#ffffff";
+ pngCanvasCtx.fillRect(0, 0, imageWidth, imageHeight);
+
+ if (this.visible[0]) {
+ pngCanvasCtx.drawImage(this.canvas[0],
+ 0, 0, width, height,
+ 0, 0, imageWidth, imageHeight);
+ }
+ if (this.visible[1]) {
+ pngCanvasCtx.drawImage(this.canvas[1],
+ 0, 0, width, height,
+ 0, 0, imageWidth, imageHeight);
+ }
+ return pngCanvas;
+};
+
+Neo.Painter.prototype.getPNG = function() {
+ var image = this.getImage();
+ var dataURL = image.toDataURL('image/png');
+ return this.dataURLtoBlob(dataURL);
+};
+
+Neo.Painter.prototype.getThumbnail = function(type) {
+ if (type != "animation") {
+ var thumbnailWidth = this.getThumbnailWidth();
+ var thumbnailHeight = this.getThumbnailHeight();
+ if (thumbnailWidth || thumbnailHeight) {
+ var width = this.canvasWidth;
+ var height = this.canvasHeight;
+ if (thumbnailWidth == 0) {
+ thumbnailWidth = thumbnailHeight * width / height;
+ }
+ if (thumbnailHeight == 0) {
+ thumbnailHeight = thumbnailWidth * height / width;
+ }
+ } else {
+ thumbnailWidth = thumbnailHeight = null;
+ }
+
+ console.log("get thumbnail", thumbnailWidth, thumbnailHeight);
+
+ var image = this.getImage(thumbnailWidth, thumbnailHeight);
+ var dataURL = image.toDataURL('image/' + type);
+ return this.dataURLtoBlob(dataURL);
+
+ } else {
+ return new Blob([]); //animationã«ã¯å¯¾å¿œã—ã¦ã„ãªã„ã®ã§ãƒ€ãƒŸãƒ¼ãƒ‡ãƒ¼ã‚¿ã‚’è¿”ã™
+ }
+};
+
+Neo.Painter.prototype.getThumbnailWidth = function() {
+ var width = Neo.config.thumbnail_width;
+ if (width) {
+ if (width.match(/%$/)) {
+ return Math.floor(this.canvasWidth * (parseInt(width) / 100.0));
+ } else {
+ return parseInt(width);
+ }
+ }
+ return 0;
+};
+
+Neo.Painter.prototype.getThumbnailHeight = function() {
+ var height = Neo.config.thumbnail_height;
+ if (height) {
+ if (height.match(/%$/)) {
+ return Math.floor(this.canvasHeight * (parseInt(height) / 100.0));
+ } else {
+ return parseInt(height);
+ }
+ }
+ return 0;
+};
+
+Neo.Painter.prototype.clearCanvas = function(doConfirm) {
+ if (!doConfirm || confirm("全消ã—ã—ã¾ã™")) {
+ //Register undo first;
+ this._pushUndo();
+
+ this.canvasCtx[0].clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.canvasCtx[1].clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+ }
+};
+
+Neo.Painter.prototype.updateDestCanvas = function(x, y, width, height, useTemp) {
+ var canvasWidth = this.canvasWidth;
+ var canvasHeight = this.canvasHeight;
+ var updateAll = false;
+ if (x == 0 && y == 0 && width == canvasWidth && height == canvasHeight) {
+ updateAll = true;
+ };
+
+ if (x + width > this.canvasWidth) width = this.canvasWidth - x;
+ if (y + height > this.canvasHeight) height = this.canvasHeight - y;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (width <= 0 || height <= 0) return;
+
+ var ctx = this.destCanvasCtx;
+ ctx.save();
+ ctx.fillStyle = "#ffffff";
+
+ var fillWidth = width
+ var fillHeight = height
+
+ if (updateAll) {
+ ctx.fillRect(0, 0, this.destCanvas.width, this.destCanvas.height);
+
+ } else {
+ //カーソルã®æ画ゴミãŒæ®‹ã‚‹ã®ã‚’ã”ã¾ã‹ã™ãŸã‚
+ if (x + width == this.canvasWidth) fillWidth = width + 1;
+ if (y + height == this.canvasHeight) fillHeight = height + 1;
+ }
+
+ ctx.translate(this.destCanvas.width*.5, this.destCanvas.height*.5);
+ ctx.scale(this.zoom, this.zoom);
+ ctx.translate(-this.zoomX, -this.zoomY);
+ ctx.globalAlpha = 1.0;
+ ctx.msImageSmoothingEnabled = 0;
+
+ if (!updateAll) {
+ ctx.fillRect(x, y, fillWidth, fillHeight);
+ }
+
+ if (this.visible[0]) {
+ ctx.drawImage(this.canvas[0],
+ x, y, width, height,
+ x, y, width, height);
+ }
+ if (this.visible[1]) {
+ ctx.drawImage(this.canvas[1],
+ x, y, width, height,
+ x, y, width, height);
+ }
+ if (useTemp) {
+ ctx.globalAlpha = 1.0; //this.alpha;
+ ctx.drawImage(this.tempCanvas,
+ x, y, width, height,
+ x + this.tempX, y + this.tempY, width, height);
+ }
+ ctx.restore();
+};
+
+Neo.Painter.prototype.getBound = function(x0, y0, x1, y1, r) {
+ var left = Math.floor((x0 < x1) ? x0 : x1);
+ var top = Math.floor((y0 < y1) ? y0 : y1);
+ var width = Math.ceil(Math.abs(x0 - x1));
+ var height = Math.ceil(Math.abs(y0 - y1));
+ r = Math.ceil(r + 1);
+
+ if (!r) {
+ width += 1;
+ height += 1;
+
+ } else {
+ left -= r;
+ top -= r;
+ width += r * 2;
+ height += r * 2;
+ }
+ return [left, top, width, height];
+};
+
+Neo.Painter.prototype.getColor = function(c) {
+ if (!c) c = this.foregroundColor;
+ var r = parseInt(c.substr(1, 2), 16);
+ var g = parseInt(c.substr(3, 2), 16);
+ var b = parseInt(c.substr(5, 2), 16);
+ var a = Math.floor(this.alpha * 255);
+ return a <<24 | b<<16 | g<<8 | r;
+};
+
+Neo.Painter.prototype.getColorString = function(c) {
+ var rgb = ("000000" + (c & 0xffffff).toString(16)).substr(-6);
+ return '#' + rgb;
+};
+
+Neo.Painter.prototype.setColor = function(c) {
+ if (typeof c != "string") c = this.getColorString(c);
+ this.foregroundColor = c;
+
+ Neo.updateUI();
+};
+
+Neo.Painter.prototype.getAlpha = function(type) {
+ var a1 = this.alpha;
+
+ switch (type) {
+ case Neo.Painter.ALPHATYPE_PEN:
+ if (a1 > 0.5) {
+ a1 = 1.0/16 + (a1 - 0.5) * 30.0/16;
+ } else {
+ a1 = Math.sqrt(2 * a1) / 16.0;
+ }
+ a1 = Math.min(1, Math.max(0, a1));
+ break;
+
+ case Neo.Painter.ALPHATYPE_FILL:
+ a1 = -0.00056 * a1 + 0.0042 / (1.0 - a1) - 0.0042;
+ a1 = Math.min(1.0, Math.max(0, a1 * 10));
+ break;
+
+ case Neo.Painter.ALPHATYPE_BRUSH:
+ a1 = -0.00056 * a1 + 0.0042 / (1.0 - a1) - 0.0042;
+ a1 = Math.min(1.0, Math.max(0, a1));
+ break;
+ }
+
+ // アルファãŒå°ã•ã„時ã¯é©å½“ã«ç‚¹ã‚’抜ã„ã¦è¦‹ãŸç›®ã®æ¿ƒåº¦ã‚’åˆã‚ã›ã‚‹
+ if (a1 < 1.0/255) {
+ this.aerr += a1;
+ a1 = 0;
+ while (this.aerr > 1.0/255) {
+ a1 = 1.0/255;
+ this.aerr -= 1.0/255;
+ }
+ }
+ return a1;
+};
+
+Neo.Painter.prototype.prepareDrawing = function () {
+ var r = parseInt(this.foregroundColor.substr(1, 2), 16);
+ var g = parseInt(this.foregroundColor.substr(3, 2), 16);
+ var b = parseInt(this.foregroundColor.substr(5, 2), 16);
+ var a = Math.floor(this.alpha * 255);
+
+ var maskR = parseInt(this.maskColor.substr(1, 2), 16);
+ var maskG = parseInt(this.maskColor.substr(3, 2), 16);
+ var maskB = parseInt(this.maskColor.substr(5, 2), 16);
+
+ this._currentColor = [r, g, b, a];
+ this._currentMask = [maskR, maskG, maskB];
+};
+
+Neo.Painter.prototype.isMasked = function (buf8, index) {
+ var r = this._currentMask[0];
+ var g = this._currentMask[1];
+ var b = this._currentMask[2];
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3];
+
+ if (a0 == 0) {
+ r0 = 0xff;
+ g0 = 0xff;
+ b0 = 0xff;
+ }
+
+ var type = this.maskType;
+
+ //TODO
+ //ã„ã‚ã„ã‚試ã—ãŸã®ã§ã™ãŒåŠé€æ˜Žã§æç”»ã™ã‚‹ã¨ãã®åŠ ç®—・逆加算をå†ç¾ã™ã‚‹æ–¹æ³•ãŒã‚ã‹ã‚Šã¾ã›ã‚“。
+ //ã¨ã‚Šã‚ãˆãšå˜ç´”ã«ç„¡è¦–ã—ã¦ã„ã¾ã™ã€‚
+ if (type == Neo.Painter.MASKTYPE_ADD ||
+ type == Neo.Painter.MASKTYPE_SUB) {
+ if (this._currentColor[3] < 250) {
+ type = Neo.Painter.MASKTYPE_NONE;
+ }
+ }
+
+ switch (type) {
+ case Neo.Painter.MASKTYPE_NONE:
+ return;
+
+ case Neo.Painter.MASKTYPE_NORMAL:
+ return (r0 == r &&
+ g0 == g &&
+ b0 == b) ? true : false;
+
+ case Neo.Painter.MASKTYPE_REVERSE:
+ return (r0 != r ||
+ g0 != g ||
+ b0 != b) ? true : false;
+
+ case Neo.Painter.MASKTYPE_ADD:
+ if (a0 > 0) {
+ var sort = this.sortColor(r0, g0, b0);
+ for (var i = 0; i < 3; i++) {
+ var c = sort[i];
+ if (buf8[index + c] < this._currentColor[c]) return true;
+ }
+ return false;
+
+ } else {
+ return false;
+ }
+
+ case Neo.Painter.MASKTYPE_SUB:
+ if (a0 > 0) {
+ var sort = this.sortColor(r0, g0, b0);
+ for (var i = 0; i < 3; i++) {
+ var c = sort[i];
+ if (buf8[index + c] > this._currentColor[c]) return true;
+ }
+ return false;
+ } else {
+ return true;
+ }
+ }
+};
+
+Neo.Painter.prototype.setPoint = function(buf8, bufWidth, x0, y0, left, top, type) {
+ var x = x0 - left;
+ var y = y0 - top;
+
+ switch (type) {
+ case Neo.Painter.LINETYPE_PEN:
+ this.setPenPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BRUSH:
+ this.setBrushPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_TONE:
+ this.setTonePoint(buf8, bufWidth, x, y, x0, y0);
+ break;
+
+ case Neo.Painter.LINETYPE_ERASER:
+ this.setEraserPoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BLUR:
+ this.setBlurPoint(buf8, bufWidth, x, y, x0, y0);
+ break;
+
+ case Neo.Painter.LINETYPE_DODGE:
+ this.setDodgePoint(buf8, bufWidth, x, y);
+ break;
+
+ case Neo.Painter.LINETYPE_BURN:
+ this.setBurnPoint(buf8, bufWidth, x, y);
+ break;
+
+ default:
+ break;
+ }
+};
+
+
+Neo.Painter.prototype.setPenPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_PEN);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var a1x = Math.max(a1, 1.0/255);
+
+ var r = (r1 * a1x + r0 * a0 * (1 - a1x)) / a;
+ var g = (g1 * a1x + g0 * a0 * (1 - a1x)) / a;
+ var b = (b1 * a1x + b0 * a0 * (1 - a1x)) / a;
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBrushPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var a1x = Math.max(a1, 1.0/255);
+
+ var r = (r1 * a1x + r0 * a0) / (a0 + a1x);
+ var g = (g1 * a1x + g0 * a0) / (a0 + a1x);
+ var b = (b1 * a1x + b0 * a0) / (a0 + a1x);
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setTonePoint = function(buf8, width, x, y, x0, y0) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+
+ x -= r0;
+ y -= r0;
+ x0 -= r0;
+ y0 -= r0;
+// x -= r0;
+// y -= r0;
+// if (r0%2) { x0++; y0++; } //ãªãœã‹æ¨¡æ§˜ãŒãšã‚Œã‚‹ã®ã§
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var index = (y * width + x) * 4;
+
+ var r = this._currentColor[0];
+ var g = this._currentColor[1];
+ var b = this._currentColor[2];
+ var a = this._currentColor[3];
+
+ var toneData = this.getToneData(a);
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ if (toneData[((y0+i)%4) + (((x0+j)%4) * 4)]) {
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = 255;
+ }
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setEraserPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var index = (y * width + x) * 4;
+ var a = Math.floor(this.alpha * 255);
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var k = (buf8[index + 3] / 255.0) * (1.0 - (a / 255.0));
+
+ buf8[index + 3] -= a / (d * (255.0 - a) / 255.0);
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBlurPoint = function(buf8, width, x, y, x0, y0) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+ var height = buf8.length / (width * 4);
+
+// var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ var a1 = this.alpha / 12;
+ if (a1 == 0) return;
+ var blur = a1;
+
+ var tmp = new Uint8ClampedArray(buf8.length);
+ for (var i = 0; i < buf8.length; i++) {
+ tmp[i] = buf8[i];
+ }
+
+ var left = x0 - x - r0;
+ var top = y0 - y - r0;
+
+ var xstart = 0, xend = d;
+ var ystart = 0, yend = d;
+ if (xstart > left) xstart = -left;
+ if (ystart > top) ystart = -top;
+ if (xend > this.canvasWidth - left) xend = this.canvasWidth - left;
+ if (yend > this.canvasHeight - top) yend = this.canvasHeight - top;
+
+ for (var j = ystart; j < yend; j++) {
+ var index = (j * width + xstart) * 4;
+ for (var i = xstart; i < xend; i++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var rgba = [0, 0, 0, 0, 0];
+
+ this.addBlur(tmp, index, 1.0 - blur*4, rgba);
+ if (i > xstart) this.addBlur(tmp, index - 4, blur, rgba);
+ if (i < xend - 1) this.addBlur(tmp, index + 4, blur, rgba);
+ if (j > ystart) this.addBlur(tmp, index - width*4, blur, rgba);
+ if (j < yend - 1) this.addBlur(tmp, index + width*4, blur, rgba);
+
+ buf8[index + 0] = Math.round(rgba[0]);
+ buf8[index + 1] = Math.round(rgba[1]);
+ buf8[index + 2] = Math.round(rgba[2]);
+ buf8[index + 3] = Math.round((rgba[3] / rgba[4]) * 255.0);
+ }
+ index += 4;
+ }
+ }
+};
+
+Neo.Painter.prototype.setDodgePoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ if (a1 != 255.0) {
+ var r1 = r0 * 255 / (255 - a1);
+ var g1 = g0 * 255 / (255 - a1);
+ var b1 = b0 * 255 / (255 - a1);
+ } else {
+ var r1 = 255.0;
+ var g1 = 255.0;
+ var b1 = 255.0;
+ }
+
+ var r = Math.ceil(r1);
+ var g = Math.ceil(g1);
+ var b = Math.ceil(b1);
+ var a = a0;
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+Neo.Painter.prototype.setBurnPoint = function(buf8, width, x, y) {
+ var d = this.lineWidth;
+ var r0 = Math.floor(d / 2);
+ x -= r0;
+ y -= r0;
+
+ var index = (y * width + x) * 4;
+
+ var shape = this._roundData[d];
+ var shapeIndex = 0;
+
+ var a1 = this.getAlpha(Neo.Painter.ALPHATYPE_BRUSH);
+ if (a1 == 0) return;
+
+ for (var i = 0; i < d; i++) {
+ for (var j = 0; j < d; j++) {
+ if (shape[shapeIndex++] && !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ if (a1 != 255.0) {
+ var r1 = 255 - (255 - r0) * 255 / (255 - a1);
+ var g1 = 255 - (255 - g0) * 255 / (255 - a1);
+ var b1 = 255 - (255 - b0) * 255 / (255 - a1);
+ } else {
+ var r1 = 0;
+ var g1 = 0;
+ var b1 = 0;
+ }
+
+ var r = Math.floor(r1);
+ var g = Math.floor(g1);
+ var b = Math.floor(b1);
+ var a = a0;
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ }
+ index += 4;
+ }
+ index += (width - d) * 4;
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+
+Neo.Painter.prototype.xorPixel = function(buf32, bufWidth, x, y, c) {
+ var index = y * bufWidth + x;
+ if (!c) c = 0xffffff;
+ buf32[index] ^= c;
+};
+
+Neo.Painter.prototype.getBezierPoint = function(t, x0, y0, x1, y1, x2, y2, x3, y3) {
+ var a0 = (1 - t) * (1 - t) * (1 - t);
+ var a1 = (1 - t) * (1 - t) * t * 3;
+ var a2 = (1 - t) * t * t * 3;
+ var a3 = t * t * t;
+
+ var x = x0 * a0 + x1 * a1 + x2 * a2 + x3 * a3;
+ var y = y0 * a0 + y1 * a1 + y2 * a2 + y3 * a3;
+ return [x, y];
+};
+
+var nmax = 1;
+
+Neo.Painter.prototype.drawBezier = function(ctx, x0, y0, x1, y1, x2, y2, x3, y3, type) {
+ var xmax = Math.max(x0, x1, x2, x3);
+ var xmin = Math.min(x0, x1, x2, x3);
+ var ymax = Math.max(y0, y1, y2, y3);
+ var ymin = Math.min(y0, y1, y2, y3);
+ var n = Math.ceil(((xmax - xmin) + (ymax - ymin)) * 2.5);
+
+ if (n > nmax) {
+ n = (n < nmax * 2) ? n : nmax * 2;
+ nmax = n;
+ }
+
+ for (var i = 0; i < n; i++) {
+ var t = i * 1.0 / n;
+ var p = this.getBezierPoint(t, x0, y0, x1, y1, x2, y2, x3, y3);
+ this.drawPoint(ctx, p[0], p[1], type);
+ }
+};
+
+Neo.Painter.prototype.prevLine = null; // 始点ã¾ãŸã¯çµ‚点ãŒ2度プロットã•ã‚Œã‚‹ã“ã¨ãŒã‚ã‚‹ã®ã§
+Neo.Painter.prototype.drawLine = function(ctx, x0, y0, x1, y1, type) {
+ x0 = Math.round(x0);
+ x1 = Math.round(x1);
+ y0 = Math.round(y0);
+ y1 = Math.round(y1);
+ var prev = [x0, y0, x1, y1];
+
+ var width = Math.abs(x1 - x0);
+ var height = Math.abs(y1 - y0);
+ var r = Math.ceil(this.lineWidth / 2);
+
+ var left = ((x0 < x1) ? x0 : x1) - r;
+ var top = ((y0 < y1) ? y0 : y1) - r;
+
+ var imageData = ctx.getImageData(left, top, width + r*2, height + r*2);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var dx = width, sx = x0 < x1 ? 1 : -1;
+ var dy = height, sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+ this.aerr = 0;
+
+ while (true) {
+ if (this.prevLine == null ||
+ !((this.prevLine[0] == x0 && this.prevLine[1] == y0) ||
+ (this.prevLine[2] == x0 && this.prevLine[3] == y0))) {
+ this.setPoint(buf8, imageData.width, x0, y0, left, top, type);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+
+ this.prevLine = prev;
+};
+
+Neo.Painter.prototype.drawPoint = function(ctx, x, y, type) {
+ this.drawLine(ctx, x, y, x, y, type);
+};
+
+Neo.Painter.prototype.xorRect = function(buf32, bufWidth, x, y, width, height, c) {
+ var index = y * bufWidth + x;
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ buf32[index] ^= c;
+ index++;
+ }
+ index += width - bufWidth;
+ }
+};
+
+Neo.Painter.prototype.drawXORRect = function(ctx, x, y, width, height, isFill, c) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+ if (width == 0 || height == 0) return;
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var index = 0;
+ if (!c) c = 0xffffff;
+
+ if (isFill) {
+ this.xorRect(buf32, width, 0, 0, width, height, c);
+
+ } else {
+ for (var i = 0; i < width; i++) { //top
+ buf32[index] = buf32[index] ^= c;
+ index++;
+ }
+ if (height > 1) {
+ index = width;
+ for (var i = 1; i < height; i++) { //left
+ buf32[index] = buf32[index] ^= c;
+ index += width;
+ }
+ if (width > 1) {
+ index = width * 2 - 1;
+ for (var i = 1; i < height - 1; i++) { //right
+ buf32[index] = buf32[index] ^= c;
+ index += width;
+ }
+ index = width * (height - 1) + 1;
+ for (var i = 1; i < width; i++) { // bottom
+ buf32[index] = buf32[index] ^= c;
+ index++;
+ }
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.drawXOREllipse = function(ctx, x, y, width, height, isFill, c) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+ if (width == 0 || height == 0) return;
+ if (!c) c = 0xffffff;
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+
+ var a = width-1, b = height-1, b1 = b&1; /* values of diameter */
+ var dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
+ var err = dx+dy+b1*a*a, e2; /* error of 1.step */
+
+ var x0 = x;
+ var y0 = y;
+ var x1 = x0+a;
+ var y1 = y0+b;
+
+ if (x0 > x1) { x0 = x1; x1 += a; }
+ if (y0 > y1) y0 = y1;
+ y0 += Math.floor((b+1)/2); y1 = y0-b1; /* starting pixel */
+ a *= 8*a; b1 = 8*b*b;
+ var ymin = y0 - 1;
+
+ do {
+ if (isFill) {
+ if (ymin < y0) {
+ this.xorRect(buf32, width, x0-x, y0 - y, x1 - x0, 1, c);
+ if (y0 != y1) {
+ this.xorRect(buf32, width, x0-x, y1 - y, x1 - x0, 1, c);
+ }
+ ymin = y0;
+ }
+ } else {
+ this.xorPixel(buf32, width, x1-x, y0-y, c);
+ if (x0 != x1) {
+ this.xorPixel(buf32, width, x0-x, y0-y, c);
+ }
+ if (y0 != y1) {
+ this.xorPixel(buf32, width, x0-x, y1-y, c);
+ if (x0 != x1) {
+ this.xorPixel(buf32, width, x1-x, y1-y, c);
+ }
+ }
+ }
+ e2 = 2*err;
+ if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
+ if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
+ } while (x0 <= x1);
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.drawXORLine = function(ctx, x0, y0, x1, y1, c) {
+ x0 = Math.round(x0);
+ x1 = Math.round(x1);
+ y0 = Math.round(y0);
+ y1 = Math.round(y1);
+
+ var width = Math.abs(x1 - x0);
+ var height = Math.abs(y1 - y0);
+
+ var left = ((x0 < x1) ? x0 : x1);
+ var top = ((y0 < y1) ? y0 : y1);
+// console.log("left:"+left+" top:"+top+" width:"+width+" height:"+height);
+
+ var imageData = ctx.getImageData(left, top, width + 1, height + 1);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var dx = width, sx = x0 < x1 ? 1 : -1;
+ var dy = height, sy = y0 < y1 ? 1 : -1;
+ var err = (dx > dy ? dx : -dy) / 2;
+
+ while (true) {
+ if (this.prevLine == null ||
+ !((this.prevLine[0] == x0 && this.prevLine[1] == y0) ||
+ (this.prevLine[2] == x0 && this.prevLine[3] == y0))) {
+
+ this.xorPixel(buf32, imageData.width, x0 - left, y0 - top, c);
+ }
+
+ if (x0 === x1 && y0 === y1) break;
+ var e2 = err;
+ if (e2 > -dx) { err -= dy; x0 += sx; }
+ if (e2 < dy) { err += dx; y0 += sy; }
+ }
+
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, left, top);
+};
+
+
+Neo.Painter.prototype.eraseRect = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var index = 0;
+
+ var a = 1.0 - this.alpha;
+ if (a != 0) {
+ a = Math.ceil(2.0 / a);
+ } else {
+ a = 255;
+ }
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ if (!this.isMasked(buf8, index)) {
+ buf8[index + 3] -= a;
+ }
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.flipH = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var half = Math.floor(width / 2);
+ for (var j = 0; j < height; j++) {
+ var index = j * width;
+ var index2 = index + (width - 1);
+ for (var i = 0; i < half; i++) {
+ var value = buf32[index + i];
+ buf32[index + i] = buf32[index2 -i];
+ buf32[index2 - i] = value;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.flipV = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var half = Math.floor(height / 2);
+ for (var j = 0; j < half; j++) {
+ var index = j * width;
+ var index2 = (height - 1 - j) * width;
+ for (var i = 0; i < width; i++) {
+ var value = buf32[index + i];
+ buf32[index + i] = buf32[index2 + i];
+ buf32[index2 + i] = value;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.merge = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = [];
+ var buf32 = [];
+ var buf8 = [];
+ for (var i = 0; i < 2; i++) {
+ imageData[i] = this.canvasCtx[i].getImageData(x, y, width, height);
+ buf32[i] = new Uint32Array(imageData[i].data.buffer);
+ buf8[i] = new Uint8ClampedArray(imageData[i].data.buffer);
+ }
+
+ var dst = this.current;
+ var src = (dst == 1) ? 0 : 1;
+ var size = width * height;
+ var index = 0;
+ for (var i = 0; i < size; i++) {
+ var r0 = buf8[0][index + 0];
+ var g0 = buf8[0][index + 1];
+ var b0 = buf8[0][index + 2];
+ var a0 = buf8[0][index + 3] / 255.0;
+ var r1 = buf8[1][index + 0];
+ var g1 = buf8[1][index + 1];
+ var b1 = buf8[1][index + 2];
+ var a1 = buf8[1][index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+ if (a > 0) {
+ var r = Math.floor((r1 * a1 + r0 * a0 * (1 - a1)) / a + 0.5);
+ var g = Math.floor((g1 * a1 + g0 * a0 * (1 - a1)) / a + 0.5);
+ var b = Math.floor((b1 * a1 + b0 * a0 * (1 - a1)) / a + 0.5);
+ }
+ buf8[src][index + 0] = 0;
+ buf8[src][index + 1] = 0;
+ buf8[src][index + 2] = 0;
+ buf8[src][index + 3] = 0;
+ buf8[dst][index + 0] = r;
+ buf8[dst][index + 1] = g;
+ buf8[dst][index + 2] = b;
+ buf8[dst][index + 3] = Math.floor(a * 255 + 0.5);
+ index += 4;
+ }
+
+ for (var i = 0; i < 2; i++) {
+ imageData[i].data.set(buf8[i]);
+ this.canvasCtx[i].putImageData(imageData[i], x, y);
+ }
+};
+
+Neo.Painter.prototype.blurRect = function(ctx, x, y, width, height) {
+ x = Math.round(x);
+ y = Math.round(y);
+ width = Math.round(width);
+ height = Math.round(height);
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var tmp = new Uint8ClampedArray(buf8.length);
+ for (var i = 0; i < buf8.length; i++) tmp[i] = buf8[i];
+
+ var index = 0;
+ var a1 = this.alpha / 12;
+ var blur = a1;
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ var rgba = [0, 0, 0, 0, 0];
+
+ this.addBlur(tmp, index, 1.0 - blur*4, rgba);
+
+ if (i > 0) this.addBlur(tmp, index - 4, blur, rgba);
+ if (i < width - 1) this.addBlur(tmp, index + 4, blur, rgba);
+ if (j > 0) this.addBlur(tmp, index - width*4, blur, rgba);
+ if (j < height - 1) this.addBlur(tmp, index + width*4, blur, rgba);
+
+ var w = rgba[4];
+ buf8[index + 0] = Math.round(rgba[0]);
+ buf8[index + 1] = Math.round(rgba[1]);
+ buf8[index + 2] = Math.round(rgba[2]);
+ buf8[index + 3] = Math.ceil((rgba[3] / w) * 255.0);
+
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.addBlur = function(buffer, index, a, rgba) {
+ var r0 = rgba[0];
+ var g0 = rgba[1];
+ var b0 = rgba[2];
+ var a0 = rgba[3];
+ var r1 = buffer[index + 0];
+ var g1 = buffer[index + 1];
+ var b1 = buffer[index + 2];
+ var a1 = (buffer[index + 3] / 255.0) * a;
+ rgba[4] += a;
+
+ var a = a0 + a1;
+ if (a > 0) {
+ rgba[0] = (r1 * a1 + r0 * a0) / (a0 + a1);
+ rgba[1] = (g1 * a1 + g0 * a0) / (a0 + a1);
+ rgba[2] = (b1 * a1 + b0 * a0) / (a0 + a1);
+ rgba[3] = a;
+ }
+};
+
+Neo.Painter.prototype.pickColor = function(x, y) {
+ var r = 0xff, g = 0xff, b = 0xff, a;
+
+ x = Math.floor(x);
+ y = Math.floor(y);
+ if (x >= 0 && x < this.canvasWidth &&
+ y >= 0 && y < this.canvasHeight) {
+
+ for (var i = 0; i < 2; i++) {
+ if (this.visible[i]) {
+ var ctx = this.canvasCtx[i];
+ var imageData = ctx.getImageData(x, y, 1, 1);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var a = buf8[3] / 255.0;
+ r = r * (1.0 - a) + buf8[2] * a;
+ g = g * (1.0 - a) + buf8[1] * a;
+ b = b * (1.0 - a) + buf8[0] * a;
+ }
+ }
+ r = Math.max(Math.min(Math.round(r), 255), 0);
+ g = Math.max(Math.min(Math.round(g), 255), 0);
+ b = Math.max(Math.min(Math.round(b), 255), 0);
+ var result = r | g<<8 | b<<16;
+ }
+ this.setColor(result);
+
+
+ if (this.current > 0) {
+ if (a == 0 && (result == 0xffffff || this.getEmulationMode() < 2.16)) {
+ this.setToolByType(Neo.eraserTip.tools[Neo.eraserTip.mode]);
+
+ } else {
+ if (Neo.eraserTip.selected) {
+ this.setToolByType(Neo.penTip.tools[Neo.penTip.mode]);
+ }
+ }
+ }
+};
+
+Neo.Painter.prototype.fillHorizontalLine = function(buf32, x0, x1, y) {
+ var index = y * this.canvasWidth + x0;
+ var fillColor = this.getColor();
+ for (var x = x0; x <= x1; x++) {
+ buf32[index++] = fillColor;
+ }
+};
+
+Neo.Painter.prototype.scanLine = function(x0, x1, y, baseColor, buf32, stack) {
+ var width = this.canvasWidth;
+ for (var x = x0; x <= x1; x++) {
+ stack.push({x:x, y: y})
+ }
+/*
+ while (x0 <= x1) {
+ for (; x0 <= x1; x0++) {
+ if (buf32[y * width + x0] == baseColor) break;
+ }
+ if (x1 < x0) break;
+
+ for (; x0 <= x1; x0++) {
+ if (buf32[y * width + x0] != baseColor) break;
+ }
+ stack.push({x:x0 - 1, y: y})
+ }
+*/
+};
+
+Neo.Painter.prototype.fill = function(x, y, ctx) {
+ x = Math.round(x);
+ y = Math.round(y);
+
+ if (x < 0 || x >= this.canvasWidth || y < 0 || y >= this.canvasHeight) {
+ return;
+ }
+
+ var imageData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var width = imageData.width;
+ var stack = [{x: x, y: y}];
+
+ var baseColor = buf32[y * width + x];
+ var fillColor = this.getColor();
+
+ if ((baseColor & 0xff000000) == 0 || (baseColor != fillColor)) {
+ while (stack.length > 0) {
+ if (stack.length > 1000000) {
+ console.log('too much stack')
+ break;
+ }
+ var point = stack.pop();
+ var x = point.x;
+ var y = point.y;
+ var x0 = x;
+ var x1 = x;
+ if (buf32[y * width + x] == fillColor) continue;
+ if (buf32[y * width + x] != baseColor) continue;
+
+ for (; 0 < x0; x0--) {
+ if (buf32[y * width + (x0 - 1)] != baseColor) break;
+ }
+ for (; x1 < this.canvasWidth - 1; x1++) {
+ if (buf32[y * width + (x1 + 1)] != baseColor) break;
+ }
+ this.fillHorizontalLine(buf32, x0, x1, y);
+
+ if (y + 1 < this.canvasHeight) {
+ this.scanLine(x0, x1, y + 1, baseColor, buf32, stack);
+ }
+ if (y - 1 >= 0) {
+ this.scanLine(x0, x1, y - 1, baseColor, buf32, stack);
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+ this.updateDestCanvas(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.copy = function(x, y, width, height) {
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+
+ var imageData = this.canvasCtx[this.current].getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ this.temp = new Uint32Array(buf32.length);
+ for (var i = 0; i < buf32.length; i++) {
+ this.temp[i] = buf32[i];
+ }
+
+ //tempCanvasã«ä¹—ã›ã‚‹ç”»åƒã‚’作る
+ imageData = this.tempCanvasCtx.getImageData(x, y, width, height);
+ buf32 = new Uint32Array(imageData.data.buffer);
+ buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ for (var i = 0; i < buf32.length; i++) {
+ if (this.temp[i] >> 24) {
+ buf32[i] = this.temp[i] | 0xff000000;
+ } else {
+ buf32[i] = 0xffffffff;
+ }
+ }
+ imageData.data.set(buf8);
+ this.tempCanvasCtx.putImageData(imageData, x, y);
+};
+
+
+Neo.Painter.prototype.paste = function(x, y, width, height) {
+ var ctx = this.canvasCtx[this.current];
+// console.log(this.tempX, this.tempY);
+
+ var imageData = ctx.getImageData(x + this.tempX, y + this.tempY, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ for (var i = 0; i < buf32.length; i++) {
+ buf32[i] = this.temp[i];
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x + this.tempX, y + this.tempY);
+
+ this.temp = null;
+ this.tempX = 0;
+ this.tempY = 0;
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.turn = function(x, y, width, height) {
+ var ctx = this.canvasCtx[this.current];
+
+ // 傾ã‘ツールã®ãƒã‚°ã‚’å†ç¾ã™ã‚‹ãŸã‚一番上ã®ãƒ©ã‚¤ãƒ³ã§å¯¾è±¡é ˜åŸŸã‚’埋ã‚ã‚‹
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var temp = new Uint32Array(buf32.length);
+
+ var index = 0;
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ temp[index] = buf32[index];
+ if (index >= width) {
+ buf32[index] = buf32[index % width];
+ }
+ index++;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+
+ // 90度回転ã•ã›ã¦è²¼ã‚Šä»˜ã‘
+ imageData = ctx.getImageData(x, y, height, width);
+ buf32 = new Uint32Array(imageData.data.buffer);
+ buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ index = 0;
+ for (var j = height - 1; j >= 0; j--) {
+ for (var i = 0; i < width; i++) {
+ buf32[i * height + j] = temp[index++];
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.doFill = function(ctx, x, y, width, height, maskFunc) {
+ if (Math.round(x) != x) console.log("*");
+ if (Math.round(width) != width) console.log("*");
+ if (Math.round(height) != height) console.log("*");
+
+ var imageData = ctx.getImageData(x, y, width, height);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ var index = 0;
+
+ var r1 = this._currentColor[0];
+ var g1 = this._currentColor[1];
+ var b1 = this._currentColor[2];
+ var a1 = this.getAlpha(Neo.ALPHATYPE_FILL);
+
+ for (var j = 0; j < height; j++) {
+ for (var i = 0; i < width; i++) {
+ if (maskFunc && maskFunc.call(this, i, j, width, height)) {
+ //ãªãœã‹åŠ ç®—逆加算ã¯é©ç”¨ã•ã‚Œãªã„
+ if (this.maskType >= Neo.Painter.MASKTYPE_ADD ||
+ !this.isMasked(buf8, index)) {
+ var r0 = buf8[index + 0];
+ var g0 = buf8[index + 1];
+ var b0 = buf8[index + 2];
+ var a0 = buf8[index + 3] / 255.0;
+
+ var a = a0 + a1 - a0 * a1;
+
+ if (a > 0) {
+ var a1x = a1;
+ var ax = 1 + a0 * (1 - a1x);
+
+ var r = (r1 + r0 * a0 * (1 - a1x)) / ax;
+ var g = (g1 + g0 * a0 * (1 - a1x)) / ax;
+ var b = (b1 + b0 * a0 * (1 - a1x)) / ax
+
+ r = (r1 > r0) ? Math.ceil(r) : Math.floor(r);
+ g = (g1 > g0) ? Math.ceil(g) : Math.floor(g);
+ b = (b1 > b0) ? Math.ceil(b) : Math.floor(b);
+ }
+
+ var tmp = a * 255;
+ a = Math.ceil(tmp);
+
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+ }
+ }
+ index += 4;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, x, y);
+};
+
+Neo.Painter.prototype.rectFillMask = function(x, y, width, height) {
+ return true;
+};
+
+Neo.Painter.prototype.rectMask = function(x, y, width, height) {
+ var d = this.lineWidth;
+ return (x < d || x > width - 1 - d ||
+ y < d || y > height - 1 - d) ? true : false;
+};
+
+Neo.Painter.prototype.ellipseFillMask = function(x, y, width, height) {
+ var cx = (width - 1) / 2.0;
+ var cy = (height - 1) / 2.0;
+ x = (x - cx) / (cx + 1);
+ y = (y - cy) / (cy + 1);
+
+ return ((x * x) + (y * y) < 1) ? true : false;
+}
+
+Neo.Painter.prototype.ellipseMask = function(x, y, width, height) {
+ var d = this.lineWidth;
+ var cx = (width - 1) / 2.0;
+ var cy = (height - 1) / 2.0;
+
+ if (cx <= d || cy <= d) return this.ellipseFillMask(x, y, width, height);
+
+ var x2 = (x - cx) / (cx - d + 1);
+ var y2 = (y - cy) / (cy - d + 1);
+
+ x = (x - cx) / (cx + 1);
+ y = (y - cy) / (cy + 1);
+
+ if ((x * x) + (y * y) < 1) {
+ if ((x2 * x2) + (y2 * y2) >= 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/*
+-----------------------------------------------------------------------
+*/
+
+Neo.Painter.prototype.getDestCanvasPosition = function(mx, my, isClip, isCenter) {
+ var mx = Math.floor(mx); //Math.round(mx);
+ var my = Math.floor(my); //Math.round(my);
+ if (isCenter) {
+ mx += 0.499;
+ my += 0.499;
+ }
+ var x = (mx - this.zoomX + this.destCanvas.width * 0.5 / this.zoom) * this.zoom;
+ var y = (my - this.zoomY + this.destCanvas.height * 0.5 / this.zoom) * this.zoom;
+
+ if (isClip) {
+ x = Math.max(Math.min(x, this.destCanvas.width), 0);
+ y = Math.max(Math.min(y, this.destCanvas.height), 0);
+ }
+ return {x:x, y:y};
+};
+
+Neo.Painter.prototype.isWidget = function(element) {
+ while (1) {
+ if (element == null ||
+ element.id == "canvas" ||
+ element.id == "container") break;
+
+ if (element.id == "tools" ||
+ element.className == "buttonOn" ||
+ element.className == "buttonOff" ||
+ element.className == "inputText") {
+ return true;
+ }
+ element = element.parentNode;
+ }
+ return false;
+};
+
+Neo.Painter.prototype.isContainer = function(element) {
+ while (1) {
+ if (element == null) break;
+ if (element.id == "container") return true;
+ element = element.parentNode;
+ }
+ return false;
+};
+
+Neo.Painter.prototype.cancelTool = function(e) {
+ if (this.tool) {
+ this.isMouseDown = false;
+ this.tool.upHandler(this);
+
+// switch (this.tool.type) {
+// case Neo.Painter.TOOLTYPE_HAND:
+// case Neo.Painter.TOOLTYPE_SLIDER:
+// this.isMouseDown = false;
+// this.tool.upHandler(this);
+// }
+ }
+};
+
+Neo.Painter.prototype.loadImage = function (filename) {
+ console.log("loadImage " + filename);
+ var img = new Image();
+ img.src = filename;
+ img.onload = function() {
+ var oe = Neo.painter;
+ oe.canvasCtx[0].drawImage(img, 0, 0);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ };
+};
+
+Neo.Painter.prototype.loadSession = function (filename) {
+ if (Neo.storage) {
+ var img0 = new Image();
+ img0.src = Neo.storage.getItem('layer0');
+ img0.onload = function() {
+ var img1 = new Image();
+ img1.src = Neo.storage.getItem('layer1');
+ img1.onload = function() {
+ var oe = Neo.painter;
+ oe.canvasCtx[0].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.canvasCtx[1].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.canvasCtx[0].drawImage(img0, 0, 0);
+ oe.canvasCtx[1].drawImage(img1, 0, 0);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight);
+ }
+ }
+ }
+};
+
+Neo.Painter.prototype.saveSession = function() {
+ if (Neo.storage) {
+ Neo.storage.setItem('timestamp', +(new Date()));
+ Neo.storage.setItem('layer0', this.canvas[0].toDataURL('image/png'));
+ Neo.storage.setItem('layer1', this.canvas[1].toDataURL('image/png'));
+ }
+};
+
+Neo.Painter.prototype.clearSession = function() {
+ if (Neo.storage) {
+ Neo.storage.removeItem('timestamp');
+ Neo.storage.removeItem('layer0');
+ Neo.storage.removeItem('layer1');
+ }
+};
+
+Neo.Painter.prototype.sortColor = function(r0, g0, b0) {
+ var min = (r0 < g0) ? ((r0 < b0) ? 0 : 2) : ((g0 < b0) ? 1 : 2);
+ var max = (r0 > g0) ? ((r0 > b0) ? 0 : 2) : ((g0 > b0) ? 1 : 2);
+ var mid = (min + max == 1) ? 2 : ((min + max == 2) ? 1 : 0);
+ return [min, mid, max];
+};
+
+Neo.Painter.prototype.doText = function(x, y, string, fontSize) {
+ //テキストæç”»
+ //æç”»ä½ç½®ãŒãšã‚Œã‚‹ã®ã§é©å½“ã«èª¿æ•´
+ var offset = parseInt(fontSize, 10);
+// y -= Math.round((5.0 + offset/8) / this.zoom);
+// x += Math.round(2.0 / this.zoom);
+
+ var ctx = this.tempCanvasCtx;
+ ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+ ctx.save();
+ ctx.translate(x, y);
+// ctx.scale(1/this.zoom, 1/this.zoom);
+
+ var fontFamily = Neo.painter.inputText.style.fontFamily || "Arial";
+ ctx.font = fontSize + " " + fontFamily;
+
+ ctx.fillStyle = 0;
+ ctx.fillText(string, 0, 0);
+ ctx.restore();
+
+ // é©å½“ã«äºŒå€¤åŒ–
+ var c = this.getColor();
+ var r = c & 0xff;
+ var g = (c & 0xff00) >> 8;
+ var b = (c & 0xff0000) >> 16;
+ var a = Math.round(this.alpha * 255.0);
+
+ var imageData = ctx.getImageData(0, 0, this.canvasWidth, this.canvasHeight);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var length = this.canvasWidth * this.canvasHeight;
+ var index = 0;
+ for (var i = 0; i < length; i++) {
+ if (buf8[index + 3] >= 0x60) {
+ buf8[index + 0] = r;
+ buf8[index + 1] = g;
+ buf8[index + 2] = b;
+ buf8[index + 3] = a;
+
+ } else {
+ buf8[index + 0] = 0;
+ buf8[index + 1] = 0;
+ buf8[index + 2] = 0;
+ buf8[index + 3] = 0;
+ }
+ index += 4;
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ //キャンãƒã‚¹ã«è²¼ã‚Šä»˜ã‘
+ ctx = this.canvasCtx[this.current];
+ ctx.globalAlpha = 1.0;
+ ctx.drawImage(this.tempCanvas,
+ 0, 0, this.canvasWidth, this.canvasHeight,
+ 0, 0, this.canvasWidth, this.canvasHeight);
+
+ this.tempCanvasCtx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
+};
+
+Neo.Painter.prototype.isUIPaused = function() {
+ if (this.drawType == Neo.Painter.DRAWTYPE_BEZIER) {
+ if (this.tool.step && this.tool.step > 0) {
+ return true;
+ }
+ }
+ return false;
+};
+
+Neo.Painter.prototype.getEmulationMode = function() {
+ return parseFloat(Neo.config.neo_emulation_mode || 2.22)
+};
+
+'use strict';
+
+Neo.ToolBase = function() {};
+
+Neo.ToolBase.prototype.startX;
+Neo.ToolBase.prototype.startY;
+Neo.ToolBase.prototype.init = function(oe) {}
+Neo.ToolBase.prototype.kill = function(oe) {}
+Neo.ToolBase.prototype.lineType = Neo.Painter.LINETYPE_NONE;
+
+Neo.ToolBase.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+};
+
+Neo.ToolBase.prototype.upHandler = function(oe) {
+};
+
+Neo.ToolBase.prototype.moveHandler = function(oe) {
+};
+
+Neo.ToolBase.prototype.transformForZoom = function(oe) {
+ var ctx = oe.destCanvasCtx;
+ ctx.translate(oe.canvasWidth * 0.5, oe.canvasHeight * 0.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+};
+
+Neo.ToolBase.prototype.getType = function() {
+ return this.type;
+};
+
+Neo.ToolBase.prototype.getToolButton = function() {
+ switch (this.type) {
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TEXT:
+ return Neo.penTip;
+
+ case Neo.Painter.TOOLTYPE_TONE:
+ case Neo.Painter.TOOLTYPE_BLUR:
+ case Neo.Painter.TOOLTYPE_DODGE:
+ case Neo.Painter.TOOLTYPE_BURN:
+ return Neo.pen2Tip;
+
+ case Neo.Painter.TOOLTYPE_RECT:
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return Neo.effectTip;
+
+ case Neo.Painter.TOOLTYPE_COPY:
+ case Neo.Painter.TOOLTYPE_MERGE:
+ case Neo.Painter.TOOLTYPE_BLURRECT:
+ case Neo.Painter.TOOLTYPE_FLIP_H:
+ case Neo.Painter.TOOLTYPE_FLIP_V:
+ case Neo.Painter.TOOLTYPE_TURN:
+ return Neo.effect2Tip;
+
+ case Neo.Painter.TOOLTYPE_ERASER:
+ case Neo.Painter.TOOLTYPE_ERASEALL:
+ case Neo.Painter.TOOLTYPE_ERASERECT:
+ return Neo.eraserTip;
+
+ case Neo.Painter.TOOLTYPE_FILL:
+ return Neo.fillButton;
+ }
+ return null;
+};
+
+Neo.ToolBase.prototype.getReserve = function() {
+ switch (this.type) {
+ case Neo.Painter.TOOLTYPE_ERASER:
+ return Neo.reserveEraser;
+
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TONE:
+ case Neo.Painter.TOOLTYPE_ERASERECT:
+ case Neo.Painter.TOOLTYPE_ERASEALL:
+ case Neo.Painter.TOOLTYPE_COPY:
+ case Neo.Painter.TOOLTYPE_MERGE:
+ case Neo.Painter.TOOLTYPE_FIP_H:
+ case Neo.Painter.TOOLTYPE_FIP_V:
+
+ case Neo.Painter.TOOLTYPE_DODGE:
+ case Neo.Painter.TOOLTYPE_BURN:
+ case Neo.Painter.TOOLTYPE_BLUR:
+ case Neo.Painter.TOOLTYPE_BLURRECT:
+
+ case Neo.Painter.TOOLTYPE_TEXT:
+ case Neo.Painter.TOOLTYPE_TURN:
+ case Neo.Painter.TOOLTYPE_RECT:
+ case Neo.Painter.TOOLTYPE_RECTFILL:
+ case Neo.Painter.TOOLTYPE_ELLIPSE:
+ case Neo.Painter.TOOLTYPE_ELLIPSEFILL:
+ return Neo.reservePen;
+
+ }
+ return null;
+};
+
+Neo.ToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.updateUI();
+ }
+};
+
+Neo.ToolBase.prototype.saveStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ reserve.size = Neo.painter.lineWidth;
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ DrawToolBase(æ画ツールã®ãƒ™ãƒ¼ã‚¹ã‚¯ãƒ©ã‚¹ï¼‰
+ -------------------------------------------------------------------------
+*/
+
+Neo.DrawToolBase = function() {};
+Neo.DrawToolBase.prototype = new Neo.ToolBase();
+Neo.DrawToolBase.prototype.isUpMove = false;
+Neo.DrawToolBase.prototype.step = 0;
+
+Neo.DrawToolBase.prototype.init = function() {
+ this.step = 0;
+ this.isUpMove = true;
+};
+
+Neo.DrawToolBase.prototype.downHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandDownHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineDownHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierDownHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.upHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandUpHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineUpHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierUpHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.moveHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierMoveHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.upMoveHandler = function(oe) {
+ switch (oe.drawType) {
+ case Neo.Painter.DRAWTYPE_FREEHAND:
+ this.freeHandUpMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_LINE:
+ this.lineUpMoveHandler(oe); break;
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierUpMoveHandler(oe); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.keyDownHandler = function(e) {
+ switch (Neo.painter.drawType) {
+ case Neo.Painter.DRAWTYPE_BEZIER:
+ this.bezierKeyDownHandler(e); break;
+ }
+};
+
+Neo.DrawToolBase.prototype.rollOverHandler= function(oe) {};
+Neo.DrawToolBase.prototype.rollOutHandler= function(oe) {
+ if (!oe.isMouseDown && !oe.isMouseDownRight){
+ oe.tempCanvasCtx.clearRect(0,0,oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.DrawToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+};
+
+
+/* FreeHand (手書ã) */
+
+Neo.DrawToolBase.prototype.freeHandDownHandler = function(oe) {
+ //Register undo first;
+ oe._pushUndo();
+
+ oe.prepareDrawing();
+ this.isUpMove = false;
+ var ctx = oe.canvasCtx[oe.current];
+ if (oe.alpha >= 1 || this.lineType != Neo.Painter.LINETYPE_BRUSH) {
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe.drawLine(ctx, x0, y0, x0, y0, this.lineType);
+ }
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ if (oe.alpha >= 1) {
+ var r = Math.ceil(oe.lineWidth / 2);
+ var rect = oe.getBound(oe.mouseX, oe.mouseY, oe.mouseX, oe.mouseY, r);
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ }
+};
+
+Neo.DrawToolBase.prototype.freeHandUpHandler = function(oe) {
+ oe.tempCanvasCtx.clearRect(0,0,oe.canvasWidth, oe.canvasHeight);
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ // oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ // this.drawCursor(oe);
+ oe.prevLine = null;
+};
+
+Neo.DrawToolBase.prototype.freeHandMoveHandler = function(oe) {
+ var ctx = oe.canvasCtx[oe.current];
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ var x1 = Math.floor(oe.prevMouseX);
+ var y1 = Math.floor(oe.prevMouseY);
+ oe.drawLine(ctx, x0, y0, x1, y1, this.lineType);
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+
+ var r = Math.ceil(oe.lineWidth / 2);
+ var rect = oe.getBound(oe.mouseX, oe.mouseY, oe.prevMouseX, oe.prevMouseY, r);
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+};
+
+Neo.DrawToolBase.prototype.freeHandUpMoveHandler = function(oe) {
+ this.isUpMove = true;
+
+ if (oe.cursorRect) {
+ var rect = oe.cursorRect;
+ oe.updateDestCanvas(rect[0], rect[1], rect[2], rect[3], true);
+ oe.cursorRect = null;
+ }
+ this.drawCursor(oe);
+};
+
+Neo.DrawToolBase.prototype.drawCursor = function(oe) {
+ if (oe.lineWidth <= 8) return;
+ var mx = oe.mouseX;
+ var my = oe.mouseY;
+ var d = oe.lineWidth;
+
+ var x = (mx - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y = (my - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ var r = d * 0.5 * oe.zoom;
+
+ if (!(x > -r &&
+ y > -r &&
+ x < oe.destCanvas.width + r &&
+ y < oe.destCanvas.height + r)) return;
+
+ var ctx = oe.destCanvasCtx;
+ ctx.save();
+ this.transformForZoom(oe)
+
+ var c = (this.type == Neo.Painter.TOOLTYPE_ERASER) ? 0x0000ff : 0xffff7f;
+ oe.drawXOREllipse(ctx, x-r, y-r, r*2, r*2, false, c);
+
+ ctx.restore();
+ oe.cursorRect = oe.getBound(mx, my, mx, my, Math.ceil(d / 2));
+}
+
+
+/* Line (ç›´ç·š) */
+
+Neo.DrawToolBase.prototype.lineDownHandler = function(oe) {
+ this.isUpMove = false;
+ this.startX = Math.floor(oe.mouseX);
+ this.startY = Math.floor(oe.mouseY);
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+Neo.DrawToolBase.prototype.lineUpHandler = function(oe) {
+ if (this.isUpMove == false) {
+ this.isUpMove = true;
+
+ oe._pushUndo();
+ oe.prepareDrawing();
+ var ctx = oe.canvasCtx[oe.current];
+ var x0 = Math.floor(oe.mouseX);
+ var y0 = Math.floor(oe.mouseY);
+ oe.drawLine(ctx, x0, y0, this.startX, this.startY, this.lineType);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.DrawToolBase.prototype.lineMoveHandler = function(oe) {
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ this.drawLineCursor(oe);
+};
+
+Neo.DrawToolBase.prototype.lineUpMoveHandler = function(oe) {
+};
+
+Neo.DrawToolBase.prototype.drawLineCursor = function(oe, mx, my) {
+ if (!mx) mx = Math.floor(oe.mouseX);
+ if (!my) my = Math.floor(oe.mouseY);
+ var nx = this.startX;
+ var ny = this.startY;
+ var ctx = oe.destCanvasCtx;
+ ctx.save();
+ this.transformForZoom(oe)
+
+ var x0 = (mx +.499 - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y0 = (my +.499 - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ var x1 = (nx +.499 - oe.zoomX + oe.destCanvas.width * 0.5 / oe.zoom) * oe.zoom;
+ var y1 = (ny +.499 - oe.zoomY + oe.destCanvas.height * 0.5 / oe.zoom) * oe.zoom;
+ oe.drawXORLine(ctx, x0, y0, x1, y1);
+
+ ctx.restore();
+};
+
+
+/* Bezier (BZ曲線) */
+
+Neo.DrawToolBase.prototype.bezierDownHandler = function(oe) {
+ this.isUpMove = false;
+
+ if (this.step == 0) {
+ this.startX = this.x0 = Math.floor(oe.mouseX);
+ this.startY = this.y0 = Math.floor(oe.mouseY);
+ }
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+};
+
+Neo.DrawToolBase.prototype.bezierUpHandler = function(oe) {
+ if (this.isUpMove == false) {
+ this.isUpMove = true;
+ }
+
+ this.step++;
+ switch (this.step) {
+ case 1:
+ oe.prepareDrawing();
+ this.x3 = Math.floor(oe.mouseX);
+ this.y3 = Math.floor(oe.mouseY);
+ break;
+
+ case 2:
+ this.x1 = Math.floor(oe.mouseX);
+ this.y1 = Math.floor(oe.mouseY);
+ break;
+
+ case 3:
+ this.x2 = Math.floor(oe.mouseX);
+ this.y2 = Math.floor(oe.mouseY);
+
+ oe._pushUndo();
+ oe.drawBezier(oe.canvasCtx[oe.current],
+ this.x0, this.y0, this.x1, this.y1,
+ this.x2, this.y2, this.x3, this.y3, this.lineType);
+
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ this.step = 0;
+ break;
+
+ default:
+ this.step = 0;
+ break;
+ }
+};
+
+Neo.DrawToolBase.prototype.bezierMoveHandler = function(oe) {
+ switch (this.step) {
+ case 0:
+ if (!this.isUpMove) {
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawLineCursor(oe);
+ }
+ break;
+ case 1:
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawBezierCursor1(oe);
+ break;
+
+ case 2:
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, false);
+ this.drawBezierCursor2(oe);
+ break;
+ }
+};
+
+Neo.DrawToolBase.prototype.bezierUpMoveHandler = function(oe) {
+ this.bezierMoveHandler(oe);
+};
+
+Neo.DrawToolBase.prototype.bezierKeyDownHandler = function(e) {
+ if (e.keyCode == 27) { //Escã§ã‚­ãƒ£ãƒ³ã‚»ãƒ«
+ this.step = 0;
+
+ var oe = Neo.painter;
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+
+Neo.DrawToolBase.prototype.drawBezierCursor1 = function(oe) {
+ var ctx = oe.destCanvasCtx;
+ // var x = oe.mouseX; //Math.floor(oe.mouseX);
+ // var y = oe.mouseY; //Math.floor(oe.mouseY);
+ var stab = oe.getStabilized();
+ var x = Math.floor(stab[0]);
+ var y = Math.floor(stab[1]);
+ var p = oe.getDestCanvasPosition(x, y, false, true);
+ var p0 = oe.getDestCanvasPosition(this.x0, this.y0, false, true);
+ var p3 = oe.getDestCanvasPosition(this.x3, this.y3, false, true);
+
+ // handle
+ oe.drawXORLine(ctx, p0.x, p0.y, p.x, p.y);
+ oe.drawXOREllipse(ctx, p.x - 4, p.y - 4, 8, 8);
+ oe.drawXOREllipse(ctx, p0.x - 4, p0.y - 4, 8, 8);
+
+ // preview
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.drawBezier(oe.tempCanvasCtx,
+ this.x0, this.y0,
+ x, y,
+ x, y,
+ this.x3, this.y3, this.lineType);
+
+ ctx.save();
+ ctx.translate(oe.destCanvas.width*.5, oe.destCanvas.height*.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+ ctx.drawImage(oe.tempCanvas,
+ 0, 0, oe.canvasWidth, oe.canvasHeight,
+ 0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ ctx.restore();
+};
+
+Neo.DrawToolBase.prototype.drawBezierCursor2 = function(oe) {
+ var ctx = oe.destCanvasCtx;
+ // var x = oe.mouseX; //Math.floor(oe.mouseX);
+ // var y = oe.mouseY; //Math.floor(oe.mouseY);
+ var stab = oe.getStabilized();
+ var x = Math.floor(stab[0]);
+ var y = Math.floor(stab[1]);
+ var p = oe.getDestCanvasPosition(oe.mouseX, oe.mouseY, false, true);
+ var p0 = oe.getDestCanvasPosition(this.x0, this.y0, false, true);
+ var p1 = oe.getDestCanvasPosition(this.x1, this.y1, false, true);
+ var p3 = oe.getDestCanvasPosition(this.x3, this.y3, false, true);
+
+ // handle
+ oe.drawXORLine(ctx, p3.x, p3.y, p.x, p.y);
+ oe.drawXOREllipse(ctx, p.x - 4, p.y - 4, 8, 8);
+ oe.drawXORLine(ctx, p0.x, p0.y, p1.x, p1.y);
+ oe.drawXOREllipse(ctx, p1.x - 4, p1.y - 4, 8, 8);
+ oe.drawXOREllipse(ctx, p0.x - 4, p0.y - 4, 8, 8);
+
+ // preview
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.drawBezier(oe.tempCanvasCtx,
+ this.x0, this.y0,
+ this.x1, this.y1,
+ x, y,
+ this.x3, this.y3, this.lineType);
+
+ ctx.save();
+ ctx.translate(oe.destCanvas.width*.5, oe.destCanvas.height*.5);
+ ctx.scale(oe.zoom, oe.zoom);
+ ctx.translate(-oe.zoomX, -oe.zoomY);
+ ctx.drawImage(oe.tempCanvas,
+ 0, 0, oe.canvasWidth, oe.canvasHeight,
+ 0, 0, oe.canvasWidth, oe.canvasHeight);
+ ctx.restore();
+};
+
+/*
+ -------------------------------------------------------------------------
+ Pen(鉛筆)
+ -------------------------------------------------------------------------
+*/
+
+Neo.PenTool = function() {};
+Neo.PenTool.prototype = new Neo.DrawToolBase();
+Neo.PenTool.prototype.type = Neo.Painter.TOOLTYPE_PEN;
+Neo.PenTool.prototype.lineType = Neo.Painter.LINETYPE_PEN;
+
+Neo.PenTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+}
+
+/*
+ -------------------------------------------------------------------------
+ Brush(水彩)
+ -------------------------------------------------------------------------
+*/
+
+Neo.BrushTool = function() {};
+Neo.BrushTool.prototype = new Neo.DrawToolBase();
+Neo.BrushTool.prototype.type = Neo.Painter.TOOLTYPE_BRUSH;
+Neo.BrushTool.prototype.lineType = Neo.Painter.LINETYPE_BRUSH;
+
+Neo.BrushTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = this.getAlpha();
+ Neo.updateUI();
+ }
+};
+
+Neo.BrushTool.prototype.getAlpha = function() {
+ var alpha = 241 - Math.floor(Neo.painter.lineWidth / 2) * 6;
+ return alpha / 255.0;
+};
+
+/*
+ -------------------------------------------------------------------------
+ Tone(トーン)
+ -------------------------------------------------------------------------
+*/
+
+Neo.ToneTool = function() {};
+Neo.ToneTool.prototype = new Neo.DrawToolBase();
+Neo.ToneTool.prototype.type = Neo.Painter.TOOLTYPE_TONE;
+Neo.ToneTool.prototype.lineType = Neo.Painter.LINETYPE_TONE;
+
+Neo.ToneTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 23 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Eraser(消ã—ペン)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EraserTool = function() {};
+Neo.EraserTool.prototype = new Neo.DrawToolBase();
+Neo.EraserTool.prototype.type = Neo.Painter.TOOLTYPE_ERASER;
+Neo.EraserTool.prototype.lineType = Neo.Painter.LINETYPE_ERASER;
+
+
+/*
+ -------------------------------------------------------------------------
+ Blur(ã¼ã‹ã—)
+ -------------------------------------------------------------------------
+*/
+
+Neo.BlurTool = function() {};
+Neo.BlurTool.prototype = new Neo.DrawToolBase();
+Neo.BlurTool.prototype.type = Neo.Painter.TOOLTYPE_BLUR;
+Neo.BlurTool.prototype.lineType = Neo.Painter.LINETYPE_BLUR;
+
+Neo.BlurTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Dodge(覆ã„焼ã)
+ -------------------------------------------------------------------------
+*/
+
+Neo.DodgeTool = function() {};
+Neo.DodgeTool.prototype = new Neo.DrawToolBase();
+Neo.DodgeTool.prototype.type = Neo.Painter.TOOLTYPE_DODGE;
+Neo.DodgeTool.prototype.lineType = Neo.Painter.LINETYPE_DODGE;
+
+Neo.DodgeTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Burn(焼ãè¾¼ã¿ï¼‰
+ -------------------------------------------------------------------------
+*/
+
+Neo.BurnTool = function() {};
+Neo.BurnTool.prototype = new Neo.DrawToolBase();
+Neo.BurnTool.prototype.type = Neo.Painter.TOOLTYPE_BURN;
+Neo.BurnTool.prototype.lineType = Neo.Painter.LINETYPE_BURN;
+
+Neo.BurnTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 128 / 255.0;
+ Neo.updateUI();
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Hand(スクロール)
+ -------------------------------------------------------------------------
+*/
+
+Neo.HandTool = function() {};
+Neo.HandTool.prototype = new Neo.ToolBase();
+Neo.HandTool.prototype.type = Neo.Painter.TOOLTYPE_HAND;
+Neo.HandTool.prototype.isUpMove = false;
+Neo.HandTool.prototype.reverse = false;
+
+Neo.HandTool.prototype.downHandler = function(oe) {
+ oe.tempCanvasCtx.clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+
+ this.isDrag = true;
+ this.startX = oe.rawMouseX;
+ this.startY = oe.rawMouseY;
+};
+
+Neo.HandTool.prototype.upHandler = function(oe) {
+ this.isDrag = false;
+ oe.popTool();
+};
+
+Neo.HandTool.prototype.moveHandler = function(oe) {
+ if (this.isDrag) {
+ var dx = this.startX - oe.rawMouseX;
+ var dy = this.startY - oe.rawMouseY;
+
+ var ax = oe.destCanvas.width / (oe.canvasWidth * oe.zoom);
+ var ay = oe.destCanvas.height / (oe.canvasHeight * oe.zoom);
+ var barWidth = oe.destCanvas.width * ax;
+ var barHeight = oe.destCanvas.height * ay;
+ var scrollWidthInScreen = oe.destCanvas.width - barWidth - 2;
+ var scrollHeightInScreen = oe.destCanvas.height - barHeight - 2;
+
+ dx *= oe.scrollWidth / scrollWidthInScreen;
+ dy *= oe.scrollHeight / scrollHeightInScreen;
+
+ if (this.reverse) {
+ dx *= -1;
+ dy *= -1;
+ }
+
+ oe.setZoomPosition(oe.zoomX - dx, oe.zoomY - dy);
+
+ this.startX = oe.rawMouseX;
+ this.startY = oe.rawMouseY;
+ }
+};
+
+Neo.HandTool.prototype.upMoveHandler = function(oe) {}
+Neo.HandTool.prototype.rollOverHandler= function(oe) {}
+Neo.HandTool.prototype.rollOutHandler= function(oe) {};
+
+/*
+ -------------------------------------------------------------------------
+ Slider(色やサイズã®ã‚¹ãƒ©ã‚¤ãƒ€ã‚’æ“作ã—ã¦ã„る時)
+ -------------------------------------------------------------------------
+*/
+
+Neo.SliderTool = function() {};
+Neo.SliderTool.prototype = new Neo.ToolBase();
+Neo.SliderTool.prototype.type = Neo.Painter.TOOLTYPE_SLIDER;
+Neo.SliderTool.prototype.isUpMove = false;
+Neo.SliderTool.prototype.alt = false;
+
+Neo.SliderTool.prototype.downHandler = function(oe) {
+ if (!oe.isShiftDown) this.isDrag = true;
+
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].downHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+};
+
+Neo.SliderTool.prototype.upHandler = function(oe) {
+ this.isDrag = false;
+ oe.popTool();
+
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].upHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+};
+
+Neo.SliderTool.prototype.moveHandler = function(oe) {
+ if (this.isDrag) {
+ var rect = this.target.getBoundingClientRect();
+ var sliderType = (this.alt) ? Neo.SLIDERTYPE_SIZE : this.target['data-slider'];
+ Neo.sliders[sliderType].moveHandler(oe.rawMouseX - rect.left,
+ oe.rawMouseY - rect.top);
+ }
+};
+
+Neo.SliderTool.prototype.upMoveHandler = function(oe) {}
+Neo.SliderTool.prototype.rollOverHandler= function(oe) {}
+Neo.SliderTool.prototype.rollOutHandler= function(oe) {}
+
+/*
+ -------------------------------------------------------------------------
+ Fill(塗り潰ã—)
+ -------------------------------------------------------------------------
+*/
+
+Neo.FillTool = function() {};
+Neo.FillTool.prototype = new Neo.ToolBase();
+Neo.FillTool.prototype.type = Neo.Painter.TOOLTYPE_FILL;
+Neo.FillTool.prototype.isUpMove = false;
+
+Neo.FillTool.prototype.downHandler = function(oe) {
+ var x = Math.floor(oe.mouseX);
+ var y = Math.floor(oe.mouseY);
+ oe._pushUndo();
+ oe.fill(x, y, oe.canvasCtx[oe.current]);
+};
+
+Neo.FillTool.prototype.upHandler = function(oe) {
+};
+
+Neo.FillTool.prototype.moveHandler = function(oe) {
+};
+
+Neo.FillTool.prototype.rollOutHandler= function(oe) {};
+Neo.FillTool.prototype.upMoveHandler = function(oe) {}
+Neo.FillTool.prototype.rollOverHandler= function(oe) {}
+
+
+/*
+ -------------------------------------------------------------------------
+ EraseAll(全消ã—)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EraseAllTool = function() {};
+Neo.EraseAllTool.prototype = new Neo.ToolBase();
+Neo.EraseAllTool.prototype.type = Neo.Painter.TOOLTYPE_ERASEALL;
+Neo.EraseAllTool.prototype.isUpMove = false;
+
+Neo.EraseAllTool.prototype.downHandler = function(oe) {
+ oe._pushUndo();
+
+ oe.prepareDrawing();
+ oe.canvasCtx[oe.current].clearRect(0, 0, oe.canvasWidth, oe.canvasHeight);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+Neo.EraseAllTool.prototype.upHandler = function(oe) {
+};
+
+Neo.EraseAllTool.prototype.moveHandler = function(oe) {
+};
+
+Neo.EraseAllTool.prototype.rollOutHandler= function(oe) {};
+Neo.EraseAllTool.prototype.upMoveHandler = function(oe) {};
+Neo.EraseAllTool.prototype.rollOverHandler= function(oe) {};
+
+
+/*
+ -------------------------------------------------------------------------
+ EffectToolBase(エフェックトツールã®ãƒ™ãƒ¼ã‚¹ã‚¯ãƒ©ã‚¹ï¼‰
+ -------------------------------------------------------------------------
+*/
+
+Neo.EffectToolBase = function() {};
+Neo.EffectToolBase.prototype = new Neo.ToolBase();
+Neo.EffectToolBase.prototype.isUpMove = false;
+
+Neo.EffectToolBase.prototype.downHandler = function(oe) {
+ this.isUpMove = false;
+
+ this.startX = this.endX = oe.clipMouseX;
+ this.startY = this.endY = oe.clipMouseY;
+};
+
+Neo.EffectToolBase.prototype.upHandler = function(oe) {
+ if (this.isUpMove) return;
+ this.isUpMove = true;
+
+ this.startX = Math.floor(this.startX);
+ this.startY = Math.floor(this.startY);
+ this.endX = Math.floor(this.endX);
+ this.endY = Math.floor(this.endY);
+
+ var x = (this.startX < this.endX) ? this.startX : this.endX;
+ var y = (this.startY < this.endY) ? this.startY : this.endY;
+ var width = Math.abs(this.startX - this.endX) + 1;
+ var height = Math.abs(this.startY - this.endY) + 1;
+ var ctx = oe.canvasCtx[oe.current];
+
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (x + width > oe.canvasWidth) width = oe.canvasWidth - x;
+ if (y + height > oe.canvasHeight) height = oe.canvasHeight - y;
+
+ if (width > 0 && height > 0) {
+ oe._pushUndo();
+ oe.prepareDrawing();
+ this.doEffect(oe, x, y, width, height);
+ }
+
+ if (oe.tool.type != Neo.Painter.TOOLTYPE_PASTE) {
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+Neo.EffectToolBase.prototype.moveHandler = function(oe) {
+ this.endX = oe.clipMouseX;
+ this.endY = oe.clipMouseY;
+
+ oe.updateDestCanvas(0,0,oe.canvasWidth, oe.canvasHeight, true);
+ this.drawCursor(oe);
+};
+
+Neo.EffectToolBase.prototype.rollOutHandler= function(oe) {};
+Neo.EffectToolBase.prototype.upMoveHandler = function(oe) {};
+Neo.EffectToolBase.prototype.rollOverHandler= function(oe) {};
+
+Neo.EffectToolBase.prototype.drawCursor = function(oe) {
+ var ctx = oe.destCanvasCtx;
+
+ ctx.save();
+ this.transformForZoom(oe);
+
+ var start = oe.getDestCanvasPosition(this.startX, this.startY, true);
+ var end = oe.getDestCanvasPosition(this.endX, this.endY, true);
+
+ var x = (start.x < end.x) ? start.x : end.x;
+ var y = (start.y < end.y) ? start.y : end.y;
+ var width = Math.abs(start.x - end.x) + oe.zoom;
+ var height = Math.abs(start.y - end.y) + oe.zoom;
+
+ if (this.isEllipse) {
+ oe.drawXOREllipse(ctx, x, y, width, height, this.isFill);
+
+ } else {
+ oe.drawXORRect(ctx, x, y, width, height, this.isFill);
+ }
+ ctx.restore();
+};
+
+Neo.EffectToolBase.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = this.defaultAlpha || 1.0;
+ Neo.updateUI();
+ };
+};
+
+/*
+ -------------------------------------------------------------------------
+ EraseRect(消ã—四角)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EraseRectTool = function() {};
+Neo.EraseRectTool.prototype = new Neo.EffectToolBase();
+Neo.EraseRectTool.prototype.type = Neo.Painter.TOOLTYPE_ERASERECT;
+
+Neo.EraseRectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.eraseRect(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ FlipH(左å³å転)
+ -------------------------------------------------------------------------
+*/
+
+Neo.FlipHTool = function() {};
+Neo.FlipHTool.prototype = new Neo.EffectToolBase();
+Neo.FlipHTool.prototype.type = Neo.Painter.TOOLTYPE_FLIP_H;
+
+Neo.FlipHTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.flipH(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ FlipV(上下å転)
+ -------------------------------------------------------------------------
+*/
+
+Neo.FlipVTool = function() {};
+Neo.FlipVTool.prototype = new Neo.EffectToolBase();
+Neo.FlipVTool.prototype.type = Neo.Painter.TOOLTYPE_FLIP_V;
+
+Neo.FlipVTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.flipV(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ DodgeRect(角å–り)
+ -------------------------------------------------------------------------
+*/
+
+Neo.BlurRectTool = function() {};
+Neo.BlurRectTool.prototype = new Neo.EffectToolBase();
+Neo.BlurRectTool.prototype.type = Neo.Painter.TOOLTYPE_BLURRECT;
+
+Neo.BlurRectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.blurRect(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+Neo.BlurRectTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 0.5;
+ Neo.updateUI();
+ };
+}
+
+/*
+ -------------------------------------------------------------------------
+ Turn(傾ã‘)
+ -------------------------------------------------------------------------
+*/
+
+Neo.TurnTool = function() {};
+Neo.TurnTool.prototype = new Neo.EffectToolBase();
+Neo.TurnTool.prototype.type = Neo.Painter.TOOLTYPE_TURN;
+
+Neo.TurnTool.prototype.upHandler = function(oe) {
+ this.isUpMove = true;
+
+ this.startX = Math.floor(this.startX);
+ this.startY = Math.floor(this.startY);
+ this.endX = Math.floor(this.endX);
+ this.endY = Math.floor(this.endY);
+
+ var x = (this.startX < this.endX) ? this.startX : this.endX;
+ var y = (this.startY < this.endY) ? this.startY : this.endY;
+ var width = Math.abs(this.startX - this.endX) + 1;
+ var height = Math.abs(this.startY - this.endY) + 1;
+
+ if (width > 0 && height > 0) {
+ oe._pushUndo();
+ oe.turn(x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Merge(レイヤーçµåˆï¼‰
+ -------------------------------------------------------------------------
+*/
+
+Neo.MergeTool = function() {};
+Neo.MergeTool.prototype = new Neo.EffectToolBase();
+Neo.MergeTool.prototype.type = Neo.Painter.TOOLTYPE_MERGE;
+
+Neo.MergeTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.merge(ctx, x, y, width, height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Copy(コピー)
+ -------------------------------------------------------------------------
+*/
+
+Neo.CopyTool = function() {};
+Neo.CopyTool.prototype = new Neo.EffectToolBase();
+Neo.CopyTool.prototype.type = Neo.Painter.TOOLTYPE_COPY;
+
+Neo.CopyTool.prototype.doEffect = function(oe, x, y, width, height) {
+ oe.copy(x, y, width, height);
+ oe.setToolByType(Neo.Painter.TOOLTYPE_PASTE);
+ oe.tool.x = x;
+ oe.tool.y = y;
+ oe.tool.width = width;
+ oe.tool.height = height;
+};
+
+/*
+ -------------------------------------------------------------------------
+ Paste(ペースト)
+ -------------------------------------------------------------------------
+*/
+
+Neo.PasteTool = function() {};
+Neo.PasteTool.prototype = new Neo.ToolBase();
+Neo.PasteTool.prototype.type = Neo.Painter.TOOLTYPE_PASTE;
+
+Neo.PasteTool.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+ this.drawCursor(oe);
+};
+
+Neo.PasteTool.prototype.upHandler = function(oe) {
+ oe._pushUndo();
+
+ oe.paste(this.x, this.y, this.width, this.height);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ oe.setToolByType(Neo.Painter.TOOLTYPE_COPY);
+};
+
+Neo.PasteTool.prototype.moveHandler = function(oe) {
+ var dx = Math.floor(oe.mouseX - this.startX);
+ var dy = Math.floor(oe.mouseY - this.startY);
+ oe.tempX = dx;
+ oe.tempY = dy;
+
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ // this.drawCursor(oe);
+};
+
+Neo.PasteTool.prototype.keyDownHandler = function(e) {
+ if (e.keyCode == 27) { //Escã§ã‚­ãƒ£ãƒ³ã‚»ãƒ«
+ var oe = Neo.painter;
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+ oe.setToolByType(Neo.Painter.TOOLTYPE_COPY);
+ }
+};
+
+Neo.PasteTool.prototype.drawCursor = function(oe) {
+ var ctx = oe.destCanvasCtx;
+
+ ctx.save();
+ this.transformForZoom(oe);
+
+ var start = oe.getDestCanvasPosition(this.x, this.y, true);
+ var end = oe.getDestCanvasPosition(this.x + this.width, this.y + this.height, true);
+
+ var x = start.x + oe.tempX * oe.zoom;
+ var y = start.y + oe.tempY * oe.zoom;
+ var width = Math.abs(start.x - end.x);
+ var height = Math.abs(start.y - end.y);
+ oe.drawXORRect(ctx, x, y, width, height);
+ ctx.restore();
+};
+
+/*
+ -------------------------------------------------------------------------
+ Rect(線四角)
+ -------------------------------------------------------------------------
+*/
+
+Neo.RectTool = function() {};
+Neo.RectTool.prototype = new Neo.EffectToolBase();
+Neo.RectTool.prototype.type = Neo.Painter.TOOLTYPE_RECT;
+
+Neo.RectTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.rectMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ RectFill(四角)
+ -------------------------------------------------------------------------
+*/
+
+Neo.RectFillTool = function() {};
+Neo.RectFillTool.prototype = new Neo.EffectToolBase();
+Neo.RectFillTool.prototype.type = Neo.Painter.TOOLTYPE_RECTFILL;
+
+Neo.RectFillTool.prototype.isFill = true;
+Neo.RectFillTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.rectFillMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Ellipse(線楕円)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EllipseTool = function() {};
+Neo.EllipseTool.prototype = new Neo.EffectToolBase();
+Neo.EllipseTool.prototype.type = Neo.Painter.TOOLTYPE_ELLIPSE;
+Neo.EllipseTool.prototype.isEllipse = true;
+Neo.EllipseTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.ellipseMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ EllipseFill(楕円)
+ -------------------------------------------------------------------------
+*/
+
+Neo.EllipseFillTool = function() {};
+Neo.EllipseFillTool.prototype = new Neo.EffectToolBase();
+Neo.EllipseFillTool.prototype.type = Neo.Painter.TOOLTYPE_ELLIPSEFILL;
+Neo.EllipseFillTool.prototype.isEllipse = true;
+Neo.EllipseFillTool.prototype.isFill = true;
+Neo.EllipseFillTool.prototype.doEffect = function(oe, x, y, width, height) {
+ var ctx = oe.canvasCtx[oe.current];
+ oe.doFill(ctx, x, y, width, height, oe.ellipseFillMask);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Text(テキスト)
+ -------------------------------------------------------------------------
+*/
+
+Neo.TextTool = function() {};
+Neo.TextTool.prototype = new Neo.ToolBase();
+Neo.TextTool.prototype.type = Neo.Painter.TOOLTYPE_TEXT;
+Neo.TextTool.prototype.isUpMove = false;
+
+Neo.TextTool.prototype.downHandler = function(oe) {
+ this.startX = oe.mouseX;
+ this.startY = oe.mouseY;
+
+ if (Neo.painter.inputText) {
+ Neo.painter.updateInputText();
+
+ var rect = oe.container.getBoundingClientRect();
+ var text = Neo.painter.inputText;
+ var x = oe.rawMouseX - rect.left - 5;
+ var y = oe.rawMouseY - rect.top - 5;
+
+ text.style.left = x + "px";
+ text.style.top = y + "px";
+ text.style.display = "block";
+ text.focus();
+ }
+};
+
+Neo.TextTool.prototype.upHandler = function(oe) {
+};
+
+Neo.TextTool.prototype.moveHandler = function(oe) {};
+Neo.TextTool.prototype.upMoveHandler = function(oe) {};
+Neo.TextTool.prototype.rollOverHandler= function(oe) {};
+Neo.TextTool.prototype.rollOutHandler= function(oe) {};
+
+Neo.TextTool.prototype.keyDownHandler = function(e) {
+ if (e.keyCode == 13) { // Returnã§ç¢ºå®š
+ e.preventDefault();
+
+ var oe = Neo.painter;
+ var text = oe.inputText;
+ if (text) {
+ oe._pushUndo();
+ this.drawText(oe);
+ oe.updateDestCanvas(0, 0, oe.canvasWidth, oe.canvasHeight, true);
+
+ text.style.display = "none";
+ text.blur();
+ }
+ }
+};
+
+Neo.TextTool.prototype.kill = function(oe) {
+ Neo.painter.hideInputText();
+};
+
+Neo.TextTool.prototype.drawText = function(oe) {
+ var text = oe.inputText;
+
+ // unescape entities
+ //var tmp = document.createElement("textarea");
+ //tmp.innerHTML = text.innerHTML;
+ //var string = tmp.value;
+
+ var string = text.textContent || text.innerText;
+
+ if (string.length <= 0) return;
+ oe.doText(this.startX, this.startY, string, text.style.fontSize);
+};
+
+Neo.TextTool.prototype.loadStates = function() {
+ var reserve = this.getReserve();
+ if (reserve) {
+ Neo.painter.lineWidth = reserve.size;
+ Neo.painter.alpha = 1.0;
+ Neo.updateUI();
+ };
+};
+
+/*
+ -------------------------------------------------------------------------
+ Dummy(何もã—ãªã„時)
+ -------------------------------------------------------------------------
+*/
+
+Neo.DummyTool = function() {};
+Neo.DummyTool.prototype = new Neo.ToolBase();
+Neo.DummyTool.prototype.type = Neo.Painter.TOOLTYPE_NONE;
+Neo.DummyTool.prototype.isUpMove = false;
+
+Neo.DummyTool.prototype.downHandler = function(oe) {
+};
+
+Neo.DummyTool.prototype.upHandler = function(oe) {
+ oe.popTool();
+};
+
+Neo.DummyTool.prototype.moveHandler = function(oe) {};
+Neo.DummyTool.prototype.upMoveHandler = function(oe) {}
+Neo.DummyTool.prototype.rollOverHandler= function(oe) {}
+Neo.DummyTool.prototype.rollOutHandler= function(oe) {}
+
+'use strict';
+
+Neo.CommandBase = function() {
+};
+Neo.CommandBase.prototype.data;
+Neo.CommandBase.prototype.execute = function() {}
+
+
+/*
+ ---------------------------------------------------
+ ZOOM
+ ---------------------------------------------------
+*/
+Neo.ZoomPlusCommand = function(data) {this.data = data};
+Neo.ZoomPlusCommand.prototype = new Neo.CommandBase();
+Neo.ZoomPlusCommand.prototype.execute = function() {
+ if (this.data.zoom < 12) {
+ this.data.setZoom(this.data.zoom + 1);
+ }
+ Neo.resizeCanvas();
+ Neo.painter.updateDestCanvas();
+};
+
+Neo.ZoomMinusCommand = function(data) {this.data = data};
+Neo.ZoomMinusCommand.prototype = new Neo.CommandBase();
+Neo.ZoomMinusCommand.prototype.execute = function() {
+ if (this.data.zoom >= 2) {
+ this.data.setZoom(this.data.zoom - 1);
+ }
+ Neo.resizeCanvas();
+ Neo.painter.updateDestCanvas();
+};
+
+/*
+ ---------------------------------------------------
+ UNDO
+ ---------------------------------------------------
+*/
+Neo.UndoCommand = function(data) {this.data = data};
+Neo.UndoCommand.prototype = new Neo.CommandBase();
+Neo.UndoCommand.prototype.execute = function() {
+ this.data.undo();
+};
+
+Neo.RedoCommand = function(data) {this.data = data};
+Neo.RedoCommand.prototype = new Neo.CommandBase();
+Neo.RedoCommand.prototype.execute = function() {
+ this.data.redo();
+};
+
+
+Neo.WindowCommand = function(data) {this.data = data};
+Neo.WindowCommand.prototype = new Neo.CommandBase();
+Neo.WindowCommand.prototype.execute = function() {
+ if (Neo.fullScreen) {
+ if (confirm(Neo.translate("ページビュー?"))) {
+ Neo.fullScreen = false;
+ Neo.updateWindow();
+ }
+ } else {
+ if (confirm(Neo.translate("ウィンドウビュー?"))) {
+ Neo.fullScreen = true;
+ Neo.updateWindow();
+ }
+ }
+};
+
+Neo.SubmitCommand = function(data) {this.data = data};
+Neo.SubmitCommand.prototype = new Neo.CommandBase();
+Neo.SubmitCommand.prototype.execute = function() {
+ var board = location.href.replace(/[^/]*$/, '');
+ console.log("submit: " + board);
+ this.data.submit(board);
+};
+
+Neo.CopyrightCommand = function(data) {this.data = data};
+Neo.CopyrightCommand.prototype = new Neo.CommandBase();
+Neo.CopyrightCommand.prototype.execute = function() {
+ var url = "http://github.com/funige/neo/";
+ if (confirm(Neo.translate("PaintBBS NEOã¯ã€ãŠçµµæãã—ãƒæŽ²ç¤ºæ¿ PaintBBS (©2000-2004 ã—ãƒã¡ã‚ƒã‚“) ã‚’html5化ã™ã‚‹ãƒ—ロジェクトã§ã™ã€‚\n\nPaintBBS NEOã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ã‚’表示ã—ã¾ã™ã‹ï¼Ÿ") + "\n")) {
+ Neo.openURL(url);
+ }
+};
+
+'use strict';
+
+Neo.getModifier = function(e) {
+ if (e.shiftKey) {
+ return 'shift';
+
+ } else if (e.button == 2 || e.ctrlKey || e.altKey || Neo.painter.virtualRight) {
+ return 'right';
+ }
+ return null;
+}
+
+/*
+ -------------------------------------------------------------------------
+ Button
+ -------------------------------------------------------------------------
+*/
+
+Neo.Button = function() {};
+Neo.Button.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.selected = false;
+ this.isMouseDown = false;
+
+ var ref = this;
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+ this.element.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, true);
+
+
+ this.element.className = (!this.params.type == "fill") ? "button" : "buttonOff";
+
+ return this;
+};
+
+Neo.Button.prototype._mouseDownHandler = function(e) {
+ if (Neo.painter.isUIPaused()) return;
+ this.isMouseDown = true;
+
+ if ((this.params.type == "fill") && (this.selected == false)) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.setSelected((this.selected) ? false : true);
+ }
+ Neo.painter.setToolByType(Neo.Painter.TOOLTYPE_FILL);
+ }
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+Neo.Button.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+Neo.Button.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.Button.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.Button.prototype.setSelected = function(selected) {
+ if (selected) {
+ this.element.className = "buttonOn";
+ } else {
+ this.element.className = "buttonOff";
+ }
+ this.selected = selected;
+};
+
+Neo.Button.prototype.update = function() {
+};
+
+/*
+ -------------------------------------------------------------------------
+ Right Button
+ -------------------------------------------------------------------------
+*/
+
+Neo.RightButton;
+
+Neo.RightButton = function() {};
+Neo.RightButton.prototype = new Neo.Button();
+
+Neo.RightButton.prototype.init = function(name, params) {
+ Neo.Button.prototype.init.call(this, name, params);
+ this.params.type = "right";
+ return this;
+}
+
+Neo.RightButton.prototype._mouseDownHandler = function(e) {
+};
+
+Neo.RightButton.prototype._mouseUpHandler = function(e) {
+ this.setSelected(!this.selected)
+};
+
+Neo.RightButton.prototype._mouseOutHandler = function(e) {
+};
+
+Neo.RightButton.prototype.setSelected = function (selected) {
+ if (selected) {
+ this.element.className = "buttonOn";
+ Neo.painter.virtualRight = true;
+ } else {
+ this.element.className = "buttonOff";
+ Neo.painter.virtualRight = false;
+ }
+ this.selected = selected;
+};
+
+Neo.RightButton.clear = function () {
+ var right = Neo.rightButton;
+ right.setSelected(false);
+};
+
+/*
+ -------------------------------------------------------------------------
+ Fill Button
+ -------------------------------------------------------------------------
+*/
+
+Neo.FillButton;
+
+Neo.FillButton = function() {};
+Neo.FillButton.prototype = new Neo.Button();
+
+Neo.FillButton.prototype.init = function(name, params) {
+ Neo.Button.prototype.init.call(this, name, params);
+ this.params.type = "fill";
+ return this;
+}
+
+/*
+ -------------------------------------------------------------------------
+ ColorTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.colorTips = [];
+
+Neo.ColorTip = function() {};
+Neo.ColorTip.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ this.selected = (this.name == "color1") ? true : false;
+ this.isMouseDown = false;
+
+ var ref = this;
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+ this.element.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, true);
+
+ this.element.className = "colorTipOff";
+
+ var index = parseInt(this.name.slice(5)) - 1;
+ this.element.style.left = (index % 2) ? "0px" : "26px";
+ this.element.style.top = Math.floor(index / 2) * 21 + "px";
+
+ // base64 ColorTip.png
+ this.element.innerHTML = "<img style='max-width:44px;' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAASCAYAAAAg9DzcAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAANklEQVRIx+3OAQkAMADDsO3+Pe8qCj+0Akq6bQFqS2wTCpwE+R4IiyVYsGDBggULfirBgn8HX7BzCRwDx1QeAAAAAElFTkSuQmCC' />"
+
+ this.setColor(Neo.config.colors[params.index - 1]);
+
+ this.setSelected(this.selected);
+ Neo.colorTips.push(this);
+};
+
+Neo.ColorTip.prototype._mouseDownHandler = function(e) {
+ if (Neo.painter.isUIPaused()) return;
+ this.isMouseDown = true;
+
+ for (var i = 0; i < Neo.colorTips.length; i++) {
+ var colorTip = Neo.colorTips[i];
+ if (this == colorTip) {
+ switch (Neo.getModifier(e)) {
+ case 'shift':
+ this.setColor(Neo.config.colors[this.params.index - 1]);
+ break;
+ case 'right':
+ this.setColor(Neo.painter.foregroundColor);
+ break;
+ }
+
+// if (e.shiftKey) {
+// this.setColor(Neo.config.colors[this.params.index - 1]);
+// } else if (e.button == 2 || e.ctrlKey || e.altKey ||
+// Neo.painter.virtualRight) {
+// this.setColor(Neo.painter.foregroundColor);
+// }
+ }
+ colorTip.setSelected(this == colorTip) ? true : false;
+ }
+ Neo.painter.setColor(this.color);
+ Neo.updateUIColor(true, false);
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+Neo.ColorTip.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+Neo.ColorTip.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.ColorTip.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.ColorTip.prototype.setSelected = function(selected) {
+ if (selected) {
+ this.element.className = "colorTipOn";
+ } else {
+ this.element.className = "colorTipOff";
+ }
+ this.selected = selected;
+};
+
+Neo.ColorTip.prototype.setColor = function(color) {
+ this.color = color;
+ this.element.style.backgroundColor = color;
+};
+
+Neo.ColorTip.getCurrent = function() {
+ for (var i = 0; i < Neo.colorTips.length; i++) {
+ var colorTip = Neo.colorTips[i];
+ if (colorTip.selected) return colorTip;
+ }
+ return null;
+};
+
+/*
+ -------------------------------------------------------------------------
+ ToolTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.toolTips = [];
+Neo.toolButtons = [];
+
+Neo.ToolTip = function() {};
+
+Neo.ToolTip.prototype.prevMode = -1;
+
+Neo.ToolTip.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.params.type = this.element.id;
+ this.name = name;
+ this.mode = 0;
+
+ this.isMouseDown = false;
+
+ var ref = this;
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.onmouseup = function(e) { ref._mouseUpHandler(e); }
+ this.element.onmouseover = function(e) { ref._mouseOverHandler(e); }
+ this.element.onmouseout = function(e) { ref._mouseOutHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+ this.element.addEventListener("touchend", function(e) {
+ ref._mouseUpHandler(e);
+ }, true);
+
+ this.selected = (this.params.type == "pen") ? true : false;
+ this.setSelected(this.selected);
+
+ this.element.innerHTML = "<canvas width=46 height=18></canvas><div class='label'></div>";
+ this.canvas = this.element.getElementsByTagName('canvas')[0];
+ this.label = this.element.getElementsByTagName('div')[0];
+
+ this.update();
+ return this;
+};
+
+Neo.ToolTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ if (this.isTool) {
+ if (this.selected == false) {
+ for (var i = 0; i < Neo.toolButtons.length; i++) {
+ var toolTip = Neo.toolButtons[i];
+ toolTip.setSelected((this == toolTip) ? true : false);
+ }
+
+ } else {
+ var length = this.toolStrings.length;
+ if (Neo.getModifier(e) == "right") {
+ this.mode--;
+ if (this.mode < 0) this.mode = length - 1;
+
+ } else {
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ }
+ }
+ Neo.painter.setToolByType(this.tools[this.mode]);
+ this.update();
+ }
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+
+Neo.ToolTip.prototype._mouseUpHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseup) this.onmouseup(this);
+ }
+};
+
+Neo.ToolTip.prototype._mouseOutHandler = function(e) {
+ if (this.isMouseDown) {
+ this.isMouseDown = false;
+ if (this.onmouseout) this.onmouseout(this);
+ }
+};
+Neo.ToolTip.prototype._mouseOverHandler = function(e) {
+ if (this.onmouseover) this.onmouseover(this);
+};
+
+Neo.ToolTip.prototype.setSelected = function(selected) {
+ if (this.fixed) {
+ this.element.className = "toolTipFixed";
+
+ } else {
+ if (selected) {
+ this.element.className = "toolTipOn";
+ } else {
+ this.element.className = "toolTipOff";
+ }
+ }
+ this.selected = selected;
+};
+
+Neo.ToolTip.prototype.update = function() {};
+
+Neo.ToolTip.prototype.draw = function(c) {
+ if (this.hasTintImage) {
+ if (typeof c != "string") c = Neo.painter.getColorString(c);
+ var ctx = this.canvas.getContext("2d");
+
+ if (this.prevMode != this.mode) {
+ this.prevMode = this.mode;
+
+ var img = new Image();
+ img.src = this.toolIcons[this.mode];
+ img.onload = function() {
+ var ref = this;
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ this.drawTintImage(ctx, img, c, 0, 0);
+ }.bind(this);
+
+ } else {
+ this.tintImage(ctx, c);
+ }
+ }
+};
+
+Neo.ToolTip.prototype.drawTintImage = function(ctx, img, c, x, y) {
+ ctx.drawImage(img, x, y);
+ this.tintImage(ctx, c);
+};
+
+Neo.ToolTip.prototype.tintImage = function(ctx, c) {
+ c = (Neo.painter.getColor(c) & 0xffffff);
+
+ var imageData = ctx.getImageData(0, 0, 46, 18);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+
+ for (var i = 0; i < buf32.length; i++) {
+ var a = buf32[i] & 0xff000000;
+ if (a) {
+ buf32[i] = buf32[i] & a | c;
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+};
+
+Neo.ToolTip.bezier = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAT0lEQVRIx+3SQQoAIAhE0en+h7ZVEEKBZrX5b5sjKknAkRYpNslaMLPq44ZI9wwHs0vMQ/v87u0Kk8xfsaI242jbMdjPi5Y0r/zTAAAAD3UOjRf9jcO4sgAAAABJRU5ErkJggg==";
+Neo.ToolTip.blur = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAASUlEQVRIx+3VMQ4AIAgEQeD/f8bWWBnJYUh2SgtgK82G8/MhzVKwxOtTLgIUx6tDout4laiPIICA0Qj4bXxAy0+8LZP9yACAJwsqkggS55eiZgAAAABJRU5ErkJggg==";
+Neo.ToolTip.blurrect = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAX0lEQVRIx+2XQQ4AEAwEt+I7/v+8Org6lJKt6NzLjjYE8DAKtLpYoDeCCCC7tYUd3ru2qQOzDTyndhJzB6KSAmxSgM0fAlGuzBnmlziqxB8jFJkUYJMCbAQYPxt2kF06fvYKgjPBO/IAAAAASUVORK5CYII=";
+Neo.ToolTip.brush = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAQUlEQVRIx2NgGOKAEcb4z8CweRA4xpdUPSxofJ8BdP8WcjQxDaCDqQLQY4CsUBgFo2AUjIJRMApGwSgYBaNgZAIA0CoDwDbZu8oAAAAASUVORK5CYII=";
+Neo.ToolTip.burn = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAPklEQVRIx+3PMRIAMAQAQbzM0/0sKZPeiDG57TQ4keH0Htx9VR+MCM1vOezl8xUsv4IAAkYjoBsB3QgAgL9tYXgF19rh9yoAAAAASUVORK5CYII=";
+Neo.ToolTip.copy = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAW0lEQVRIx+2XMQoAIAwDU/E7/v95Orh2KMUSC7m5Qs6AUqAxG1gzOLirwxhgmXOjOlg1oQY8sjf2mvYNSICNBNhIgE3oH/jlzfdo34AE2EiATXsBA+5mww6S5QASDwSGMt8ouwAAAABJRU5ErkJggg==";
+Neo.ToolTip.copy2 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAN0lEQVRIx+3PwQkAIBADwdPKt3MtQVCOPNz5B7JV0pNxOwRW9zng+G92n+hmQJoBaQakGSBJf9tyBgQUV/fKCAAAAABJRU5ErkJggg==";
+Neo.ToolTip.ellipse = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAATklEQVRIx+2VMQ4AIAgD6/8fjbOJi1LFmt4OPQ0KIE7LNgggCBLbHkuFM9lM+Om+QwDjpksyb4tT86vlvzgEbYxefQPyv5D8HjDGGGOk6b3jJ+lYubd8AAAAAElFTkSuQmCC";
+Neo.ToolTip.ellipsefill = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAVUlEQVRIx+2VURIAEAgFc/9D5waSHpV5+43ZHRMizRnRA1REARLHHq6NCFl01Nail+LeEDMgU34nYhlQQd6K+PsGKkSEZyArBPoK3Y6K/AOEEEJIayZHbhIKjkZrFwAAAABJRU5ErkJggg==";
+Neo.ToolTip.eraser = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAABQElEQVRIx+1WQY7CMAwcI37Cad+yXOgH4Gu8gAt9CtrDirfMHjZJbbcktVSpQnROSeMkY3vsFHhzSG3xfLpz/JVmG0mIqDkIMcc6+7Kejx6fdb0dq7w09rVFkrjejrMOunQ9vg7f/5QEIAd6E1Eo38WF8fF7n8sdALCrLerIzoFI4sI0Vtv1SYZ8CVbeF7tzF7JugIkVkxOauc6CIe8842S+XmMfsq7TN9LRTngZmTmVD4SrnzYaGYhFoxCWgajXuMjYGTuJ3dlwIBIN3U0cUVqLXCs5E7YeVsvAYJul5HWeLUhL3EpstQwooqoOTEHDOebpMn7ngkUsg3RotU8X1MkuVDrYohkIupC0YArX6T+PfX3kcbQLNV/iCKi6EB3xqXdAZ0JKthZ8B0QEl673NIEX/0I/z36Rf6ENGzZ8EP4A8Lp+9e9VWC4AAAAASUVORK5CYII=";
+Neo.ToolTip.flip = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAZklEQVRIx+2XQQoAIAgE1+g7/f95degWHSyTTXDOhTsSiUBgOtCq8mD3DiOA3NxTCVgKaLA0qHiFOsHSnC8ELKQAmxRgE15APQfWv9pzLjwX+CXsjvBPKAXYpACb8AICzM2GHeSWAfVOCIiJuQ9tAAAAAElFTkSuQmCC";
+Neo.ToolTip.freehand = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAdUlEQVRIx+2WUQrAMAhD3dj9r+y+VoSyLhYDynzQv1qiJlCR4hzeAhVRsiC3Jkj0c5hN7Lx7IQ9SphLE1ICdwko420purEWQuywN3pqxgcw2+WwAtU1GzoqiLZNwZBvMAIcO8y3YKUO8mkbmjPzjK9E0TUPjBoeyLAS0usjLAAAAAElFTkSuQmCC";
+Neo.ToolTip.line = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAU0lEQVRIx+2UQQ4AIAjD8P+PxivRGDQC47C+oN1hIgTLQAt4qIga2c23XYAVPkm3CVhlb4ShAa/rQgMi1i0NyFg3LaBq3bAA1LpfAd7/EkIIIR2YXFYSCpWS8w8AAAAASUVORK5CYII=";
+Neo.ToolTip.merge = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAW0lEQVRIx+2XQQrAQAgDx9Lv9JF9+e6h54IINlgyZ4UMOYgwmAXXmRxc3WECorJ3dAfrJtXAC7c6PPygAQuosYAaC6hJ3YHqlfyC8Q1YQI0F1IwXCHg+G3WQKhvwgwUFmFyYbwAAAABJRU5ErkJggg==";
+Neo.ToolTip.pen = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAK0lEQVRIx+3OsQkAMAwDQXn/oe3WfSAEctd9I5TA32pHJ/3AoTpfAQCAGwaa5AICJLKWSQAAAABJRU5ErkJggg==";
+Neo.ToolTip.rect = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAQElEQVRIx+3TMQ4AIAhD0WK8/5VxdcIYY8rw3wok7YAEr6iGKaU74BY0ro+6FKhyDHe4VxRwm6eFLn8AAADwwQIwTQgGo9ZMywAAAABJRU5ErkJggg==";
+Neo.ToolTip.rectfill = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAANElEQVRIx+3PIQ4AIBADwcL//3xYBMEgLiQztmab0GvcxkqqO3ALPbbO7rBXDnRzAADgYwvqDwIMJlGb5QAAAABJRU5ErkJggg==";
+Neo.ToolTip.text = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAcUlEQVRIx+2VwQ7AIAhDy7L//2V2WmIYg+ky2KEv8aCCqYQqQMgrJNpUQMXEKKDmAPHyspgSrBBvLZu3cQqZEdwhfusq0KdkVR5HlFfBvpI0mtIzeusFot7vFPqYuzZYMXUFlzc+qrIn7tf/ACGEkIwDlEQ94YZjzcgAAAAASUVORK5CYII=";
+Neo.ToolTip.tone = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAATCAYAAADWOo4fAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAAsSAAALEgHS3X78AAAAO0lEQVRIx+3PIQ4AMAgEwaP//zNVVZUELiQ7CgWstFy8IaVsPhT1Lb/T+fQEAtwIcCPAjQC39QEAgJIL6DQCFhAqsRkAAAAASUVORK5CYII=";
+
+/*
+ -------------------------------------------------------------------------
+ PenTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.penTip;
+
+Neo.PenTip = function() {};
+Neo.PenTip.prototype = new Neo.ToolTip();
+
+Neo.PenTip.prototype.tools = [Neo.Painter.TOOLTYPE_PEN,
+ Neo.Painter.TOOLTYPE_BRUSH,
+ Neo.Painter.TOOLTYPE_TEXT];
+
+Neo.PenTip.prototype.hasTintImage = true;
+Neo.PenTip.prototype.toolIcons = [Neo.ToolTip.pen,
+ Neo.ToolTip.brush,
+ Neo.ToolTip.text];
+
+Neo.PenTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("鉛筆"),
+ Neo.translate("水彩"),
+ Neo.translate("テキスト")];
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.PenTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ if (this.label) {
+ this.label.innerHTML = this.toolStrings[this.mode];
+ }
+};
+
+/*
+ -------------------------------------------------------------------------
+ Pen2Tip
+ -------------------------------------------------------------------------
+*/
+
+Neo.pen2Tip;
+
+Neo.Pen2Tip = function() {};
+Neo.Pen2Tip.prototype = new Neo.ToolTip();
+
+Neo.Pen2Tip.prototype.tools = [Neo.Painter.TOOLTYPE_TONE,
+ Neo.Painter.TOOLTYPE_BLUR,
+ Neo.Painter.TOOLTYPE_DODGE,
+ Neo.Painter.TOOLTYPE_BURN];
+
+Neo.Pen2Tip.prototype.hasTintImage = true;
+Neo.Pen2Tip.prototype.toolIcons = [Neo.ToolTip.tone,
+ Neo.ToolTip.blur,
+ Neo.ToolTip.burn,
+ Neo.ToolTip.burn];
+
+Neo.Pen2Tip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("トーン"),
+ Neo.translate("ã¼ã‹ã—"),
+ Neo.translate("覆ã„焼ã"),
+ Neo.translate("焼ãè¾¼ã¿")];
+
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.Pen2Tip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ switch (this.tools[this.mode]) {
+ case Neo.Painter.TOOLTYPE_TONE:
+ this.drawTone(Neo.painter.foregroundColor);
+ break;
+
+ case Neo.Painter.TOOLTYPE_DODGE:
+ this.draw(0xffc0c0c0);
+ break;
+
+ case Neo.Painter.TOOLTYPE_BURN:
+ this.draw(0xff404040);
+ break;
+
+ default:
+ this.draw(Neo.painter.foregroundColor);
+ break;
+ }
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.Pen2Tip.prototype.drawTone = function() {
+ var ctx = this.canvas.getContext("2d");
+
+ var imageData = ctx.getImageData(0, 0, 46, 18);
+ var buf32 = new Uint32Array(imageData.data.buffer);
+ var buf8 = new Uint8ClampedArray(imageData.data.buffer);
+ var c = Neo.painter.getColor() | 0xff000000;
+ var a = Math.floor(Neo.painter.alpha * 255);
+ var toneData = Neo.painter.getToneData(a);
+
+ for (var j = 0; j < 18; j++) {
+ for (var i = 0; i < 46; i++) {
+ if (j >= 1 && j < 12 &&
+ i >= 2 && i < 26 &&
+ toneData[(i%4) + (j%4) * 4]) {
+ buf32[j * 46 + i] = c;
+
+ } else {
+ buf32[j * 46 + i] = 0;
+ }
+ }
+ }
+ imageData.data.set(buf8);
+ ctx.putImageData(imageData, 0, 0);
+
+ this.prevMode = this.mode;
+};
+
+
+/*
+ -------------------------------------------------------------------------
+ EraserTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.eraserTip;
+
+Neo.EraserTip = function() {};
+Neo.EraserTip.prototype = new Neo.ToolTip();
+
+Neo.EraserTip.prototype.tools = [Neo.Painter.TOOLTYPE_ERASER,
+ Neo.Painter.TOOLTYPE_ERASERECT,
+ Neo.Painter.TOOLTYPE_ERASEALL];
+
+Neo.EraserTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("消ã—ペン"),
+ Neo.translate("消ã—四角"),
+ Neo.translate("全消ã—")];
+
+ this.drawOnce = false;
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.EraserTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ if (this.drawOnce == false) {
+ this.draw();
+ this.drawOnce = true;
+ }
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.EraserTip.prototype.draw = function() {
+ var ctx = this.canvas.getContext("2d");
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ var img = new Image();
+
+ img.src = Neo.ToolTip.eraser;
+ img.onload = function() {
+ ctx.drawImage(img, 0, 0);
+ };
+};
+
+/*
+ -------------------------------------------------------------------------
+ EffectTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.effectTip;
+
+Neo.EffectTip = function() {};
+Neo.EffectTip.prototype = new Neo.ToolTip();
+
+Neo.EffectTip.prototype.tools = [Neo.Painter.TOOLTYPE_RECTFILL,
+ Neo.Painter.TOOLTYPE_RECT,
+ Neo.Painter.TOOLTYPE_ELLIPSEFILL,
+ Neo.Painter.TOOLTYPE_ELLIPSE];
+
+Neo.EffectTip.prototype.hasTintImage = true;
+Neo.EffectTip.prototype.toolIcons = [Neo.ToolTip.rectfill,
+ Neo.ToolTip.rect,
+ Neo.ToolTip.ellipsefill,
+ Neo.ToolTip.ellipse];
+
+Neo.EffectTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("四角"),
+ Neo.translate("線四角"),
+ Neo.translate("楕円"),
+ Neo.translate("線楕円")];
+
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.EffectTip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+ -------------------------------------------------------------------------
+ Effect2Tip
+ -------------------------------------------------------------------------
+*/
+
+Neo.effect2Tip;
+
+Neo.Effect2Tip = function() {};
+Neo.Effect2Tip.prototype = new Neo.ToolTip();
+
+Neo.Effect2Tip.prototype.tools = [Neo.Painter.TOOLTYPE_COPY,
+ Neo.Painter.TOOLTYPE_MERGE,
+ Neo.Painter.TOOLTYPE_BLURRECT,
+ Neo.Painter.TOOLTYPE_FLIP_H,
+ Neo.Painter.TOOLTYPE_FLIP_V,
+ Neo.Painter.TOOLTYPE_TURN];
+
+Neo.Effect2Tip.prototype.hasTintImage = true;
+Neo.Effect2Tip.prototype.toolIcons = [Neo.ToolTip.copy,
+ Neo.ToolTip.merge,
+ Neo.ToolTip.blurrect,
+ Neo.ToolTip.flip,
+ Neo.ToolTip.flip,
+ Neo.ToolTip.flip];
+
+Neo.Effect2Tip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("コピー"),
+ Neo.translate("レイヤçµåˆ"),
+ Neo.translate("角å–ã‚Š"),
+ Neo.translate("å·¦å³å転"),
+ Neo.translate("上下å転"),
+ Neo.translate("傾ã‘")];
+
+ this.isTool = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+
+ this.img = document.createElement("img");
+ this.img.src = Neo.ToolTip.copy2;
+ this.element.appendChild(this.img);
+ return this;
+};
+
+Neo.Effect2Tip.prototype.update = function() {
+ for (var i = 0; i < this.tools.length; i++) {
+ if (Neo.painter.tool.type == this.tools[i]) this.mode = i;
+ }
+
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+ -------------------------------------------------------------------------
+ MaskTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.maskTip;
+
+Neo.MaskTip = function() {};
+Neo.MaskTip.prototype = new Neo.ToolTip();
+
+Neo.MaskTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("通常"),
+ Neo.translate("マスク"),
+ Neo.translate("逆ï¾ï½½ï½¸"),
+ Neo.translate("加算"),
+ Neo.translate("逆加算")];
+
+ this.fixed = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.MaskTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ if (Neo.getModifier(e) == "right") {
+ Neo.painter.maskColor = Neo.painter.foregroundColor;
+
+ } else {
+ var length = this.toolStrings.length;
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ Neo.painter.maskType = this.mode;
+ }
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+}
+
+Neo.MaskTip.prototype.update = function() {
+ this.draw(Neo.painter.maskColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+Neo.MaskTip.prototype.draw = function(c) {
+ if (typeof c != "string") c = Neo.painter.getColorString(c);
+
+ var ctx = this.canvas.getContext("2d");
+ ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
+ ctx.fillStyle = c;
+ ctx.fillRect(1, 1, 43, 9);
+};
+
+/*
+ -------------------------------------------------------------------------
+ DrawTip
+ -------------------------------------------------------------------------
+*/
+
+Neo.drawTip;
+
+Neo.DrawTip = function() {};
+Neo.DrawTip.prototype = new Neo.ToolTip();
+
+Neo.DrawTip.prototype.hasTintImage = true;
+Neo.DrawTip.prototype.toolIcons = [Neo.ToolTip.freehand,
+ Neo.ToolTip.line,
+ Neo.ToolTip.bezier];
+
+Neo.DrawTip.prototype.init = function(name, params) {
+ this.toolStrings = [Neo.translate("手書ã"),
+ Neo.translate("ç›´ç·š"),
+ Neo.translate("BZ曲線")];
+
+ this.fixed = true;
+ Neo.ToolTip.prototype.init.call(this, name, params);
+ return this;
+};
+
+Neo.DrawTip.prototype._mouseDownHandler = function(e) {
+ this.isMouseDown = true;
+
+ var length = this.toolStrings.length;
+
+ if (Neo.getModifier(e) == "right") {
+ this.mode--;
+ if (this.mode < 0) this.mode = length - 1;
+
+ } else {
+ this.mode++;
+ if (this.mode >= length) this.mode = 0;
+ }
+ Neo.painter.drawType = this.mode;
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+}
+
+Neo.DrawTip.prototype.update = function() {
+ this.mode = Neo.painter.drawType;
+ this.draw(Neo.painter.foregroundColor);
+ this.label.innerHTML = this.toolStrings[this.mode];
+};
+
+/*
+ -------------------------------------------------------------------------
+ ColorSlider
+ -------------------------------------------------------------------------
+*/
+
+Neo.sliders = [];
+
+Neo.ColorSlider = function() {};
+
+Neo.ColorSlider.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+ this.value = 0;
+ this.type = this.params.type;
+
+ this.element.className = "colorSlider";
+ this.element.innerHTML = "<div class='slider'></div><div class='label'></div>";
+ this.element.innerHTML += "<div class='hit'></div>";
+
+ this.slider = this.element.getElementsByClassName('slider')[0];
+ this.label = this.element.getElementsByClassName('label')[0];
+ this.hit = this.element.getElementsByClassName('hit')[0];
+ this.hit['data-slider'] = params.type;
+
+ switch (this.type) {
+ case Neo.SLIDERTYPE_RED:
+ this.prefix = "R";
+ this.slider.style.backgroundColor = "#fa9696";
+ break;
+ case Neo.SLIDERTYPE_GREEN:
+ this.prefix = "G";
+ this.slider.style.backgroundColor = "#82f238";
+ break;
+ case Neo.SLIDERTYPE_BLUE:
+ this.prefix = "B";
+ this.slider.style.backgroundColor = "#8080ff";
+ break;
+ case Neo.SLIDERTYPE_ALPHA:
+ this.prefix = "A";
+ this.slider.style.backgroundColor = "#aaaaaa";
+ this.value = 255;
+ break;
+ }
+
+ this.update();
+ return this;
+};
+
+Neo.ColorSlider.prototype.downHandler = function(x, y) {
+ if (Neo.painter.isShiftDown) {
+ this.shift(x, y);
+
+ } else {
+ this.slide(x, y);
+ }
+};
+
+Neo.ColorSlider.prototype.moveHandler = function(x, y) {
+ this.slide(x, y);
+ //event.preventDefault();
+};
+
+Neo.ColorSlider.prototype.upHandler = function(x, y) {
+};
+
+Neo.ColorSlider.prototype.shift = function(x, y) {
+ var value;
+ if (x >= 0 && x < 60 && y >= 0 && y <= 15) {
+ var v = Math.floor((x - 5) * 5.0);
+ var min = (this.type == Neo.SLIDERTYPE_ALPHA) ? 1 : 0;
+
+ value = Math.max(Math.min(v, 255), min);
+ if (this.value > value || this.value == 255) {
+ this.value--;
+ } else {
+ this.value++;
+ }
+ this.value = Math.max(Math.min(this.value, 255), min);
+ this.value0 = this.value;
+ this.x0 = x;
+ }
+
+ if (this.type == Neo.SLIDERTYPE_ALPHA) {
+ Neo.painter.alpha = this.value / 255.0;
+ this.update();
+ Neo.updateUIColor(false, false);
+
+ } else {
+ var r = Neo.sliders[Neo.SLIDERTYPE_RED].value;
+ var g = Neo.sliders[Neo.SLIDERTYPE_GREEN].value;
+ var b = Neo.sliders[Neo.SLIDERTYPE_BLUE].value;
+
+ Neo.painter.setColor(r<<16 | g<<8 | b);
+ Neo.updateUIColor(true, true);
+ }
+};
+
+Neo.ColorSlider.prototype.slide = function(x, y) {
+ var value;
+ if (x >= 0 && x < 60 && y >= 0 && y <= 15) {
+ var v = Math.floor((x - 5) * 5.0);
+ value = Math.round(v / 5) * 5;
+
+ this.value0 = value;
+ this.x0 = x;
+
+ } else {
+ var d = (x - this.x0) / 3.0;
+ value = this.value0 + d;
+ }
+
+ var min = (this.type == Neo.SLIDERTYPE_ALPHA) ? 1 : 0;
+ this.value = Math.max(Math.min(value, 255), min);
+
+ if (this.type == Neo.SLIDERTYPE_ALPHA) {
+ Neo.painter.alpha = this.value / 255.0;
+ this.update();
+ Neo.updateUIColor(false, false);
+
+ } else {
+ var r = Neo.sliders[Neo.SLIDERTYPE_RED].value;
+ var g = Neo.sliders[Neo.SLIDERTYPE_GREEN].value;
+ var b = Neo.sliders[Neo.SLIDERTYPE_BLUE].value;
+ var color = (r<<16 | g<<8 | b);
+
+ var colorTip = Neo.ColorTip.getCurrent()
+ if (colorTip) {
+ colorTip.setColor(Neo.painter.getColorString(color))
+ }
+
+ Neo.painter.setColor(color);
+ // Neo.updateUIColor(true, true);
+ }
+};
+
+Neo.ColorSlider.prototype.update = function() {
+ var color = Neo.painter.getColor();
+ var alpha = Neo.painter.alpha * 255;
+
+ switch (this.type) {
+ case Neo.SLIDERTYPE_RED: this.value = (color & 0x0000ff); break;
+ case Neo.SLIDERTYPE_GREEN: this.value = (color & 0x00ff00) >> 8; break;
+ case Neo.SLIDERTYPE_BLUE: this.value = (color & 0xff0000) >> 16; break;
+ case Neo.SLIDERTYPE_ALPHA: this.value = alpha; break;
+ }
+
+ var width = this.value * 49.0 / 255.0;
+ width = Math.max(Math.min(48, width), 1);
+
+ this.slider.style.width = width.toFixed(2) + "px";
+ this.label.innerHTML = this.prefix + this.value.toFixed(0);
+};
+
+/*
+ -------------------------------------------------------------------------
+ SizeSlider
+ -------------------------------------------------------------------------
+*/
+
+Neo.SizeSlider = function() {};
+
+Neo.SizeSlider.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+ this.value = this.value0 = 1;
+
+ this.element.className = "sizeSlider";
+ this.element.innerHTML = "<div class='slider'></div><div class='label'></div>";
+ this.element.innerHTML += "<div class='hit'></div>"
+
+ this.slider = this.element.getElementsByClassName('slider')[0];
+ this.label = this.element.getElementsByClassName('label')[0];
+ this.hit = this.element.getElementsByClassName('hit')[0];
+ this.hit['data-slider'] = params.type;
+
+ this.slider.style.backgroundColor = Neo.painter.foregroundColor;
+ this.update();
+ return this;
+};
+
+Neo.SizeSlider.prototype.downHandler = function(x, y) {
+ if (Neo.painter.isShiftDown) {
+ this.shift(x, y);
+
+ } else {
+ this.value0 = this.value;
+ this.y0 = y;
+ this.slide(x, y);
+ }
+};
+
+Neo.SizeSlider.prototype.moveHandler = function(x, y) {
+ this.slide(x, y);
+ //event.preventDefault();
+};
+
+Neo.SizeSlider.prototype.upHandler = function(x, y) {
+};
+
+Neo.SizeSlider.prototype.shift = function(x, y) {
+ var value0 = Neo.painter.lineWidth;
+ var value;
+
+ if (!Neo.painter.tool.alt) {
+ var v = Math.floor((y - 4) * 30.0 / 33.0);
+
+ value = Math.max(Math.min(v, 30), 1);
+ if (value0 > value || value0 == 30) {
+ value0--;
+ } else {
+ value0++;
+ }
+ this.setSize(value0);
+ }
+};
+
+Neo.SizeSlider.prototype.slide = function(x, y) {
+ var value;
+ if (!Neo.painter.tool.alt) {
+ if (x >= 0 && x < 48 && y >= 0 && y < 41) {
+ var v = Math.floor((y - 4) * 30.0 / 33.0);
+ value = v;
+
+ this.value0 = value;
+ this.y0 = y;
+
+ } else {
+ var d = (y - this.y0) / 7.0;
+ value = this.value0 + d;
+ }
+ } else {
+ // Ctrl+Alt+ドラッグã§ã‚µã‚¤ã‚ºå¤‰æ›´ã™ã‚‹ã¨ã
+ var d = y - this.y0;
+ value = this.value0 + d;
+ }
+
+ value = Math.max(Math.min(value, 30), 1);
+ this.setSize(value);
+};
+
+Neo.SizeSlider.prototype.setSize = function(value) {
+ value = Math.round(value);
+ Neo.painter.lineWidth = Math.max(Math.min(30, value), 1);
+
+ var tool = Neo.painter.getCurrentTool();
+ if (tool) {
+ if (tool.type == Neo.Painter.TOOLTYPE_BRUSH) {
+ Neo.painter.alpha = tool.getAlpha();
+ Neo.sliders[Neo.SLIDERTYPE_ALPHA].update();
+
+ } else if (tool.type == Neo.Painter.TOOLTYPE_TEXT) {
+ Neo.painter.updateInputText();
+ }
+ }
+ this.update();
+};
+
+Neo.SizeSlider.prototype.update = function() {
+ this.value = Neo.painter.lineWidth;
+
+ var height = this.value * 33.0 / 30.0;
+ height = Math.max(Math.min(34, height), 1);
+
+ this.slider.style.height = height.toFixed(2) + "px";
+ this.label.innerHTML = this.value + "px";
+ this.slider.style.backgroundColor = Neo.painter.foregroundColor;
+};
+
+/*
+ -------------------------------------------------------------------------
+ LayerControl
+ -------------------------------------------------------------------------
+*/
+
+Neo.LayerControl = function() {};
+Neo.LayerControl.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+ this.isMouseDown = false;
+
+ var ref = this;
+
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+
+ this.element.className = "layerControl";
+
+ var layerStrings = [Neo.translate("Layer0"),
+ Neo.translate("Layer1")];
+
+ this.element.innerHTML =
+ "<div class='bg'></div><div class='label0'>" + layerStrings[0] +
+ "</div><div class='label1'>" + layerStrings[1] +
+ "</div><div class='line1'></div><div class='line0'></div>";
+
+ this.bg = this.element.getElementsByClassName('bg')[0];
+ this.label0 = this.element.getElementsByClassName('label0')[0];
+ this.label1 = this.element.getElementsByClassName('label1')[0];
+ this.line0 = this.element.getElementsByClassName('line0')[0];
+ this.line1 = this.element.getElementsByClassName('line1')[0];
+
+ this.line0.style.display = "none";
+ this.line1.style.display = "none";
+ this.label1.style.display = "none";
+
+ this.update();
+ return this;
+};
+
+Neo.LayerControl.prototype._mouseDownHandler = function(e) {
+ if (Neo.getModifier(e) == "right") {
+ var visible = Neo.painter.visible[Neo.painter.current];
+ Neo.painter.visible[Neo.painter.current] = (visible) ? false : true;
+
+ } else {
+ var current = Neo.painter.current;
+ Neo.painter.current = (current) ? 0 : 1
+ }
+ Neo.painter.updateDestCanvas(0, 0, Neo.painter.canvasWidth, Neo.painter.canvasHeight);
+ if (Neo.painter.tool.type == Neo.Painter.TOOLTYPE_PASTE) {
+ Neo.painter.tool.drawCursor(Neo.painter);
+ }
+ this.update();
+
+ if (this.onmousedown) this.onmousedown(this);
+};
+
+Neo.LayerControl.prototype.update = function() {
+ this.label0.style.display = (Neo.painter.current == 0) ? "block" : "none";
+ this.label1.style.display = (Neo.painter.current == 1) ? "block" : "none";
+ this.line0.style.display = (Neo.painter.visible[0]) ? "none" : "block";
+ this.line1.style.display = (Neo.painter.visible[1]) ? "none" : "block";
+};
+
+/*
+ -------------------------------------------------------------------------
+ ReserveControl
+ -------------------------------------------------------------------------
+*/
+Neo.reserveControls = [];
+
+Neo.ReserveControl = function() {};
+Neo.ReserveControl.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ var ref = this;
+
+ this.element.onmousedown = function(e) { ref._mouseDownHandler(e); }
+ this.element.addEventListener("touchstart", function(e) {
+ ref._mouseDownHandler(e);
+ e.preventDefault();
+ }, true);
+
+ this.element.className = "reserve";
+
+ var index = parseInt(this.name.slice(7)) - 1;
+ this.element.style.top = "1px";
+ this.element.style.left = (index * 15 + 2) + "px";
+
+ this.reserve = Neo.clone(Neo.config.reserves[index]);
+ this.update();
+
+ Neo.reserveControls.push(this);
+ return this;
+};
+
+Neo.ReserveControl.prototype._mouseDownHandler = function(e) {
+ if (Neo.getModifier(e) == 'right') {
+ this.save();
+ } else {
+ this.load();
+ }
+ this.update();
+};
+
+Neo.ReserveControl.prototype.load = function() {
+ Neo.painter.setToolByType(this.reserve.tool)
+ Neo.painter.foregroundColor = this.reserve.color;
+ Neo.painter.lineWidth = this.reserve.size;
+ Neo.painter.alpha = this.reserve.alpha;
+
+ switch (this.reserve.tool) {
+ case Neo.Painter.TOOLTYPE_PEN:
+ case Neo.Painter.TOOLTYPE_BRUSH:
+ case Neo.Painter.TOOLTYPE_TONE:
+ Neo.painter.drawType = this.reserve.drawType;
+ };
+ Neo.updateUI();
+};
+
+Neo.ReserveControl.prototype.save = function() {
+ this.reserve.color = Neo.painter.foregroundColor;
+ this.reserve.size = Neo.painter.lineWidth;
+ this.reserve.drawType = Neo.painter.drawType;
+ this.reserve.alpha = Neo.painter.alpha;
+ this.reserve.tool = Neo.painter.tool.getType();
+ this.element.style.backgroundColor = this.reserve.color;
+ this.update();
+ Neo.updateUI();
+};
+
+Neo.ReserveControl.prototype.update = function() {
+ this.element.style.backgroundColor = this.reserve.color;
+};
+
+/*
+ -------------------------------------------------------------------------
+ ScrollBarButton
+ -------------------------------------------------------------------------
+*/
+
+Neo.scrollH;
+Neo.scrollV;
+
+Neo.ScrollBarButton = function() {};
+Neo.ScrollBarButton.prototype.init = function(name, params) {
+ this.element = document.getElementById(name);
+ this.params = params || {};
+ this.name = name;
+
+ this.element.innerHTML = "<div></div>";
+ this.barButton = this.element.getElementsByTagName("div")[0];
+ this.element['data-bar'] = true;
+ this.barButton['data-bar'] = true;
+
+ if (name == "scrollH") Neo.scrollH = this;
+ if (name == "scrollV") Neo.scrollV = this;
+ return this;
+};
+
+Neo.ScrollBarButton.prototype.update = function(oe) {
+ if (this.name == "scrollH") {
+ var a = oe.destCanvas.width / (oe.canvasWidth * oe.zoom);
+ var barWidth = Math.ceil(oe.destCanvas.width * a);
+ var barX = (oe.scrollBarX) * (oe.destCanvas.width - barWidth);
+ this.barButton.style.width = (Math.ceil(barWidth) - 4) + "px";
+ this.barButton.style.left = Math.floor(barX) + "px";
+
+ } else {
+ var a = oe.destCanvas.height / (oe.canvasHeight * oe.zoom);
+ var barHeight = Math.ceil(oe.destCanvas.height * a);
+ var barY = (oe.scrollBarY) * (oe.destCanvas.height - barHeight);
+ this.barButton.style.height = (Math.ceil(barHeight) - 4) + "px";
+ this.barButton.style.top = Math.floor(barY) + "px";
+ }
+};
+
diff --git a/static/js/palette_selfy.js b/static/js/palette_selfy.js
new file mode 100755
index 0000000..b17134f
--- /dev/null
+++ b/static/js/palette_selfy.js
@@ -0,0 +1,972 @@
+// palette_selfy.js .. for PaintBBS and ShiPainter .. last update : 2004/04/11.
+
+//¨Žg‚¢•û .. ŠO•”JS‚Æ‚µ‚Ä“Ç‚Ýž‚ñ‚Å‚©‚çAD‚«‚ÈŠ‚Å palette_selfy() ‚ðŒÄ‚Ño‚µ‚ĉº‚³‚¢.
+ var selfv=new Array(); var selfytag=new Array(); //©Á‚³‚È‚¢‚Å.
+
+//«Ý’è ------------------------------------------------------------
+// ¦selfv[*] ‚ÍA‚»‚ꂼ‚ê‚ÌÝ’è‚ð‹ó”’‚É‚·‚é‚ÆA‚»‚Ì‹@”\‚̃{ƒ^ƒ“‚ð•\Ž¦‚³‚¹‚È‚­‚Å‚«‚Ü‚·.
+
+// +-‚·‚é’l‚Ì‚Æ‚±
+var pnum = 10; // +- ‚̃fƒtƒHƒ‹ƒg’l
+selfv[0] = 'size=3 style="text-align:right">'; // ”’lƒ^ƒO(type=text)‚Ì’†g
+
+
+// ƒpƒŒƒbƒgƒŠƒXƒg.
+// ..Še—v‘f‚Ì’†‚ÌF‚ÍA1‚‚¾‚¯‚Ȃ瑼‚Ì13F‚Í‚»‚ÌF‚ðŒ³‚É«‚Ì2’Ê‚è‚©‚玩“®Žæ“¾A
+var psx = 0; // 0:Ê“x+–¾“x‚ðŒ³‚É. 1:F‘Š‚ðzŠÂ‚Å.
+
+// Ê“x+–¾“x‚ðŒ³‚É‚·‚é‚Æ‚«‚ÌF. (•¡”Ý’è‚·‚éꇂÍA1‚Â1‚‚ÌF‚ð \n ‚Å‹æØ‚é)
+var pdefs = new Array(
+ '#ffffff',
+ '#ffe6e6','#ffece6','#fff3e6','#fff9e6','#ffffe6',
+ '#f3ffe6','#e6fff3','#e6f3ff','#ffe6ff','#eeddbb',
+''); // ¦‹ó”’‚¾‚Æ‚»‚Ì—v‘f‚̓XƒLƒbƒv.
+
+// F‘Š‚ÅzŠÂ‚³‚¹‚é‚Æ‚«‚ÌF. (•¡”Ý’è‚·‚éꇂÍA1‚Â1‚‚ÌF‚ð \n ‚Å‹æØ‚é)
+var pdefx = new Array(
+ '#ffffff',
+ '#ffe6e6','#ffcccc','#ff9999','#e6cccc','#e69999',
+ '#cc9999','#cc6666','#996666','#993333','#660000',
+''); // ¦‹ó”’‚¾‚Æ‚»‚Ì—v‘f‚̓XƒLƒbƒv.
+
+
+// ƒfƒtƒHƒ‹ƒg‚̃pƒŒƒbƒgƒJƒ‰[ (ˆê”Ôʼn‚ɃAƒvƒŒƒbƒg‚É‚Å‚éF)
+var pbase = '#000000\n#FFFFFF\n#B47575\n#888888\n#FA9696\n#C096C0\n#FFB6FF\n#8080FF\n#25C7C9\n#E7E58D\n#E7962D\n#99CB7B\n#FCECE2\n#F9DDCF';
+
+
+// ƒTƒ“ƒvƒ‹ƒJƒ‰[‚Ì
+ // •\Ž¦‚·‚éƒpƒŒƒbƒg‚̃Jƒ‰[”Ô†(‚±‚Ì’†‚É‚ ‚é”Ô†‚¾‚¯«‚Å‘‚«o‚µ)
+var sams = new Array(0,2,4,6,8,10,12,1,3,5,7,9,11,13); // Ê“x+–¾“x‚ðŒ³‚É‚·‚é‚Æ‚«
+var samx = new Array(0,1,2,3,4,5,6,7,8,9,10,11,12,13); // F‘Š‚ÅzŠÂ‚³‚¹‚é‚Æ‚«
+
+selfv[1] = '&nbsp;'; // ƒtƒHƒ“ƒg
+selfv[2] = 'style="font-size:xx-small; background-color:$FONT;"';
+ // ƒtƒHƒ“ƒgƒ^ƒO‚Ì’†g(u$FONTv:16i–@RGBF‚ª‘ã“üA³Šm‚É“K—p‚³‚ê‚é‘®«‚Í«‚Ì3‚Â)
+ // c color, style="color" style="background", style="background-color")
+
+ // ¦«‚±‚ê‚æ‚艺‚Í ">"(•Â‚¶ƒ^ƒO) ‚à“ü‚ê‚Ä‚­‚¾‚³‚¢ //
+
+// ƒpƒŒƒbƒg‚Ì‘I‘ðƒ{ƒ^ƒ“(type=radio)ƒ^ƒO‚Ì’†g
+selfv[3] = 'style="border-width:0;" title="ƒfƒtƒHƒ‹ƒg‚̃pƒŒƒbƒg">'; // ƒfƒtƒHƒ‹ƒgF
+selfv[4] = 'style="border-width:0;" title="‚±‚±‚̃pƒŒƒbƒg‚ðŽg‚¤B\nƒ`ƒFƒbƒN‚µ‚Ä‚é‚Æ‚«‚É‚³‚ç‚ɉŸ‚·‚ÆAƒ`ƒFƒbƒN‚ªŠO‚êA\nF‘ŠzŠÂ‚©AÊ“x+–¾“xƒpƒŒƒbƒg‚ÉB(1”Ô‚ÌF‚ªŠî–{F)">'; // ‘I‘ð
+
+
+// ƒ{ƒ^ƒ“(type=button)ƒ^ƒO‚Ì’†g
+selfv[5] = 'value="H" title="F‘ŠƒpƒŒƒbƒg (1”Ô‚ÌF‚ªŠî–{F)">'; // F‘Š
+selfv[6] = 'value="S" title="Ê“xƒpƒŒƒbƒg (1”Ô‚ÌF‚ªŠî–{F)">'; // Ê“x
+selfv[7] = 'value="B" title="–¾“xƒpƒŒƒbƒg (1”Ô‚ÌF‚ªŠî–{F)">\n'; // –¾“x
+selfv[8] = 'value="o" title="‚±‚±‚É¡‚̃pƒŒƒbƒg‚ð•Û‘¶">'; // ƒZ[ƒu
+selfv[9] = 'value="x" title="‚±‚±‚̃pƒŒƒbƒg‚ðƒfƒtƒHƒ‹ƒg‚É–ß‚·"><br>\n'; // ƒfƒtƒHƒ‹ƒg
+
+selfv[10] = 'value="H+" title="ƒpƒŒƒbƒg‘S‘Ì‚ÌF‘Š‚ð{">'; // F‘Š+
+selfv[11] = 'value="H-" title="ƒpƒŒƒbƒg‘S‘Ì‚ÌF‘Š‚ð|">'; // F‘Š-
+selfv[12] = 'value="S+" title="ƒpƒŒƒbƒg‘S‘Ì‚ÌÊ“x‚ð{">'; // Ê“x+
+selfv[13] = 'value="S-" title="ƒpƒŒƒbƒg‘S‘Ì‚ÌÊ“x‚ð|">'; // Ê“x-
+selfv[14] = 'value="B+" title="ƒpƒŒƒbƒg‘S‘Ì‚Ì–¾“x‚ð{">\n'; // –¾“x+
+selfv[15] = 'value="B-" title="ƒpƒŒƒbƒg‘S‘Ì‚Ì–¾“x‚ð|">\n'; // –¾“x-
+selfv[16] = 'value="RGB+" title="ƒpƒŒƒbƒg‘S‘Ì‚ÌRGB‚ð{"><br>\n'; // RGB+
+selfv[17] = 'value="RGB-" title="ƒpƒŒƒbƒg‘S‘Ì‚ÌRGB‚ð|"><br>\n'; // RGB-
+
+
+// ƒOƒ‰ƒf[ƒVƒ‡ƒ“‚Ì‚Æ‚±
+selfv[18] = 'style="border-width:0;" title="2“_‚ðŒ³‚ÉƒOƒ‰ƒf[ƒVƒ‡ƒ“ (1”Ô‚ÌF‚Æ14”Ô‚ÌF)" checked>2'; // 2“_
+selfv[19] = 'style="border-width:0;" title="3“_‚ðŒ³‚ÉƒOƒ‰ƒf[ƒVƒ‡ƒ“ (1”ÔA8”ÔA14”Ô‚ÌF)">3'; // 3“_
+selfv[20] = 'style="border-width:0;" title="4“_‚ðŒ³‚ÉƒOƒ‰ƒf[ƒVƒ‡ƒ“ (1A6A10A14”Ô‚ÌF)">4<br>\n'; // 4“_
+selfv[21] = 'value="RGB" title="RGB‚ŃOƒ‰ƒf[ƒVƒ‡ƒ“">\n'; // RGB?
+selfv[22] = 'value="+HSB" title="+HSB‚ŃOƒ‰ƒf[ƒVƒ‡ƒ“ (F‘Š{•ûŒü)">\n'; // +HSB
+selfv[23] = 'value="-HSB" title="-HSB‚ŃOƒ‰ƒf[ƒVƒ‡ƒ“ (F‘Š|•ûŒü)"><br>\n'; // -HSB
+
+
+// ’ljÁEíœ
+selfv[24] = 'value="+" title="ƒpƒŒƒbƒg‚ð’ljÁ‚µ‚Ü‚·">'; // ’ljÁ
+selfv[25] = 'value="-" title="‘I‘𒆂̃pƒŒƒbƒg‚ð휂µ‚Ü‚·">\n'; // íœ
+
+
+// ƒZ[ƒuEƒI[ƒgƒZ[ƒu
+selfv[26] = 'checked title="‚±‚±‚Ƀ`ƒFƒbƒN‚ð‚‚¯‚Ä‚¨‚­‚ÆAF‚ð•ÏX‚·‚é‚Æ‚«A\n@Ž©“®‚Å•Û‘¶ƒpƒŒƒbƒg‚ɃpƒŒƒbƒgî•ñ‚ðƒZ[ƒu‚µ‚Ü‚·B\nŽ©“®•Û‘¶‚ª“K—p‚³‚ê‚é‚Ì‚ÍA\n@ƒ`ƒFƒbƒN‚µ‚Ä‚éƒpƒŒƒbƒg‚©‚瑼‚̃pƒŒƒbƒg‚Ɉړ®‚µ‚½‚Æ‚«A\n@ƒ`ƒFƒbƒN‚µ‚Ä‚éƒpƒŒƒbƒg‚ÌH/S/Bƒ{ƒ^ƒ“‚ð‰Ÿ‚µ‚½‚Æ‚«A\n@‚Ì2‚‚̂Ƃ«‚Å‚·BƒTƒ“ƒvƒ‹‚ÌF‚à•Ï‚í‚è‚Ü‚·B\n‚à‚¿‚ë‚ñA‚±‚±‚Ƀ`ƒFƒbƒN‚µ‚Ä‚È‚­‚Ä‚àA\n@Žè“®‚ŃZ[ƒuƒ{ƒ^ƒ“‚ð‰Ÿ‚¹‚ÎAƒpƒŒƒbƒg‚É•Û‘¶‚³‚ê‚Ü‚·B">'; // Ž©“®ƒZ[ƒu
+selfv[27] = 'value="O" title="¡‚Ì‘S‘̂̃pƒŒƒbƒg‚ðƒNƒbƒL[‚É•Û‘¶"><br>\n'; // ƒZ[ƒu
+
+
+// ƒfƒtƒHƒ‹ƒg‚̃pƒŒƒbƒg‚ð F‘Š360‹‚É‚·‚é‚©AÊ“x++–¾“x-- ‚É‚·‚é‚©
+selfv[28] = 'style="border-width:0;" title="ƒfƒtƒHƒ‹ƒg‚̃pƒŒƒbƒg‚ÍAF‘Š‚ÅzŠÂ‚³‚¹‚é">H<sup>o</sup>'; // H‹
+selfv[29] = 'style="border-width:0;" title="ƒfƒtƒHƒ‹ƒg‚̃pƒŒƒbƒg‚ÍAÊ“x{A–¾“x|‚ŃŠƒXƒg">+S-B'; // +S-B
+selfv[30] = 'value="X" title="‘S‘̂̃pƒŒƒbƒg‚ðƒfƒtƒHƒ‹ƒg‚É–ß‚·"><br>\n'; // ƒfƒtƒHƒ‹ƒg‚É
+
+
+// UPLOAD / DOWNLOAD
+selfv[31] = 'value="" size=8 title="ƒpƒŒƒbƒgƒf[ƒ^B\nEƒAƒbƒvƒ[ƒh‚·‚é‚Æ‚«‚ÍA‚±‚±‚É“\‚è•t‚¯‚Ä‚­‚¾‚³‚¢B\nEƒ_ƒEƒ“ƒ[ƒh‚·‚é‚Æ‚«‚ÍA‚±‚±‚Ƀf[ƒ^‚ªo—Í‚³‚ê‚Ü‚·B\n@ ƒ[ƒJƒ‹‚̃eƒLƒXƒg‚É‚Å‚à•Û‘¶‚µ‚Ä‚­‚¾‚³‚¢B\n¦ƒpƒŒƒbƒgƒf[ƒ^‚ÍA\n pals = new Array(\'#FFFFFF\',\'#B47575\\n#888888\\n...\');\n@‚̂悤‚ÉAJS‚Ì”z—ñŒ`Ž®‚Å‘‚©‚ê‚Ü‚·B">\n'; //
+selfv[32] = 'value="ª" title="©‚©‚çƒpƒŒƒbƒgƒf[ƒ^‚ðƒAƒbƒvƒ[ƒh">'; //
+selfv[33] = 'value="«" title="©©‚ɃpƒŒƒbƒgƒf[ƒ^‚ðƒ_ƒEƒ“ƒ[ƒh"><br>\n'; //
+
+
+// ‚±‚̃pƒŒƒbƒgƒe[ƒuƒ‹‚ðˆÍ‚ñ‚Å‚éAƒ\[ƒX‚Æ‚©ƒ^ƒO‚Æ‚© (formƒ^ƒO‚ÍÁ‚µ‚¿‚áƒ_ƒ)
+// ƒtƒH[ƒ€Žn‚Ü‚è
+selfytag[0] = '<table class="ptable"><tr><form name="palepale"><td class="ptd" nowrap>\n<div align=right class="menu">Palette-Selfy</div>\n<div style="font-size:xx-small;">\n';
+
+// ƒtƒH[ƒ€‚ÌŠÔ_1 (ŒÂ•Ê‚̃pƒŒƒbƒg ` ‘S‘Ì‚Ì HSBARGB +- ‚Æ‚©)
+selfytag[1] = '<div style="text-align:right; padding:5;">\n';
+
+// ƒtƒH[ƒ€‚ÌŠÔ_2 (‘S‘Ì‚Ì HSBARGB +- ‚Æ‚© ` ƒOƒ‰ƒf[ƒVƒ‡ƒ“)
+selfytag[2] = '</div>\n<div style="text-align:right; padding:0 5 5 5;"">\nGradation';
+
+// ƒtƒH[ƒ€‚ÌŠÔ_3 (ƒOƒ‰ƒf[ƒVƒ‡ƒ“ ` ƒpƒŒƒbƒg‚̒ljÁE휃{ƒ^ƒ“)
+selfytag[3] = '</div>\n<div style="text-align:right; padding:0 5 0 5;"">\nPalette';
+
+// ƒtƒH[ƒ€‚ÌŠÔ_4 (ƒpƒŒƒbƒg‚̒ljÁE휃{ƒ^ƒ“ ` ƒZ[ƒuƒ{ƒ^ƒ“)
+selfytag[4] = '\nSave';
+
+// ƒtƒH[ƒ€‚ÌŠÔ_5 (ƒZ[ƒuƒ{ƒ^ƒ“ ` Default‚Í H++/+S-B ‚Ç‚¿‚ç‚©)
+selfytag[5] = '</div>\n<div style="text-align:right; padding:3 5 2 5;"">\nDefault';
+
+// ƒtƒH[ƒ€‚ÌŠÔ_6 (Default‚Í H++/+S-B ‚Ç‚¿‚ç‚© ` ƒpƒŒƒbƒg‚̃Aƒbƒv/ƒ_ƒEƒ“ƒ[ƒh)
+selfytag[6] = '</div>\n<div style="text-align:right; padding:0 5 0 5;">\nUpdata ';
+
+// ƒtƒH[ƒ€I‚í‚è
+selfytag[7] = '</div>\n</div>\n</td></form></tr></table>\n';
+//ªÝ’肨‚í‚è ------------------------------------------------------
+
+
+// ‰Šú’l (‚¢‚½‚é‚Æ‚±‚ë‚ÅŽg‚¤’l)
+var d = document;
+var pon,pno; // radioƒ`ƒFƒbƒN’†H / ƒ`ƒFƒbƒN‚µ‚½ƒpƒŒƒbƒgNO.
+var qon,qno,qmo; // buttonƒvƒbƒVƒ…’†H / ƒvƒbƒVƒ…‚µ‚½ƒpƒŒƒbƒgNO.
+var pals = new Array(); // color-palette
+var inp = '<input type="button" '; // input-button
+var inr = '<input type="radio" '; // input-button
+var cname = 'selfy='; // cookie-name
+var psx_ch = new Array('',''); // h_sb-checked
+var brwz=0;
+if(d.all){ brwz=1; }else if(d.getElementById){ brwz=2; }
+
+
+// -------------------------------------------------------------------------
+// HSB¨RGB ŒvŽZ. ’l‚Í0`255.
+function HSBtoRGB(h,s,v){
+ var r,g,b;
+ if(s==0){
+ r=v; g=v; b=v;
+ }else{
+ var max,min,dif;
+ h*=360/255; //360‹
+ max=v;
+ dif=v*s/255; //s=(dif/max)*255
+ min=v-dif; //min=max-dif
+
+ if(h<60){
+ r=max; b=min; g=h*dif/60+min;
+ }else if(h<120){
+ g=max; b=min; r=-(h-120)*dif/60+min;
+ }else if(h<180){
+ g=max; r=min; b= (h-120)*dif/60+min;
+ }else if(h<240){
+ b=max; r=min; g=-(h-240)*dif/60+min;
+ }else if(h<300){
+ b=max; g=min; r= (h-240)*dif/60+min;
+ }else if(h<=360){
+ r=max; g=min; b=-(h-360)*dif/60+min;
+ }else{r=0;g=0;b=0;}
+ }
+ return(new Array(r,g,b));
+}
+
+
+// RGB¨HSB ŒvŽZ. ’l‚Í0`255.
+function RGBtoHSB(r,g,b){
+ var max,min,dif,h,s,v;
+
+ // max
+ if(r>=g && r>=b){
+ max=r;
+ }else if(g>=b){
+ max=g;
+ }else{
+ max=b;
+ }
+
+ // min
+ if(r<=g && r<=b){
+ min=r;
+ }else if(g<=b){
+ min=g;
+ }else{
+ min=b;
+ }
+
+ // 0,0,0
+ if(max<=0){ return(new Array(0,0,0)); }
+
+ // difference
+ dif=max-min;
+
+ //Hue:
+ if(max>min){
+ if(g==max){
+ h=(b-r)/dif*60+120;
+ }else if(b==max){
+ h=(r-g)/dif*60+240;
+ }else if(b>g){
+ h=(g-b)/dif*60+360;
+ }else{
+ h=(g-b)/dif*60;
+ }
+ if(h<0){
+ h=h+360;
+ }
+ }else{ h=0; }
+ h*=255/360;
+
+ //Saturation:
+ s=(dif/max)*255;
+
+ //Value:
+ v=max;
+
+ return(new Array(h,s,v));
+}
+
+
+// RGB16¨RGB10 •\‹L. ’l‚Í 000000`ffffff
+function to10rgb(str){
+ var ns = new Array();
+ str = str.replace(/[^0-9a-fA-F]/g,'');
+ for(var i=0; i<=2; i++){
+ ns[i] = str.substr(i*2,2);
+ if(!ns[i]){ ns[i]='00'; }
+ ns[i] = Number(parseInt(ns[i],16).toString(10));
+ }
+ return(ns);
+}
+
+
+// 10¨16i–@“ñŒ…
+function format16(n){
+ n = Number(n).toString(16);
+ if(n.length<2){ n='0'+n; }
+ return(n);
+}
+
+
+
+
+// -------------------------------------------------------------------------
+// ƒpƒŒƒbƒg‚É (¦ q=1:ƒAƒvƒŒƒbƒgƒpƒŒƒbƒg‚Éo—Í‚µ‚È‚¢. lst=1:ʼn‚Ì‚Æ‚«
+function rady(p,q,lst){
+ var d = document;
+ var df = d.forms.palepale;
+
+ // ƒfƒtƒHƒ‹ƒgƒpƒŒƒbƒg
+ if(!p&&p!=0){ pon=0; pno=''; d.paintbbs.setColors(pbase); return; }
+
+ var ps = pals[p].split('\n');
+ var n = pnum;
+ if(!q && df.num.value){ n = Number(df.num.value); }
+ if(!q && pon==1 && pno!=p){ poncheck(); }
+
+ // ‘µ‚Á‚Ä‚é‚È‚ç‚·‚®•Ô‚·
+ if((pon!=1 || pno!=p) && ps.length==14){
+ if(!q){ pon=1; pno=p; }
+ if(q!=1 && pals[p]){ d.paintbbs.setColors(pals[p]); } return;
+ }
+
+ // check‚µ‚Ä‚é‚È‚ç
+ if(pon==1 && pno==p){
+ var pget = String(d.paintbbs.getColors());
+// if(pget==pals[p]){ return; }
+ var cs = pget.split('\n');
+ ps[0] = cs[0]; ps[1] = '';
+ }
+ // Œ‡‚¯‚Ä‚¢‚é‚È‚ç
+ var cs = new Array();
+
+ var psy=0; // H‹/ +S-B
+ psy = check_h_sb(lst);
+
+ if(psy==1){ cs = rh_list(p,n); }// H‹ƒŠƒXƒg
+ else{ cs = sb_list(p,n); } // +S-B ƒŠƒXƒg
+
+ if(q){ // ‰Šúݒ莞
+ pals[p] = String(cs.join('\n'));
+ }
+ if(q!=1){ // ˆê”Ê
+ if(pon==1 && pno==p){ checkout(); }
+ else{ pon=1; pno=p; }
+// pals[p] = String(cs.join('\n'));
+ d.paintbbs.setColors(String(cs.join('\n')));
+ }
+}
+
+
+// H‹ƒŠƒXƒg
+function rh_list(p,n){
+ var ps = pals[p].split('\n');
+ var rgb = to10rgb(ps[0]); //¨RGB
+ var hsv = RGBtoHSB(rgb[0],rgb[1],rgb[2]); //¨HSB
+ var cs = new Array(ps[0],ps[1]);
+ if(!cs[0]){ cs[0]='#ffffff'; }
+ if(hsv[1]!=0 && !cs[13]){ cs[13]='#ffffff'; }
+
+ for (var i=1; i<13; i++){
+ if(ps[i] && (pon!=1 || pno!=p)){ cs[i]=ps[i]; continue; } //‚ ‚é
+ var x,y,z;
+ if(hsv[1]==0){ //”’•
+ x = hsv[0];
+ y = 0;
+ if(i%2==0){ z = 255-i*n; }else{ z = 0+(i-1)*n; }
+ }else if(i>=12){
+ x = hsv[0];
+ y = 0;
+ z = 255-hsv[1];
+ }else{
+ x = hsv[0] + i*255/12;
+ y = hsv[1];
+ z = hsv[2];
+ }
+ while(x<0){ x+=255; } if(y<0){ y=0; } if(z<0){ z=0; } //«0
+ while(x>255){ x-=255; } if(y>255){ y=255; } if(z>255){ z=255; } //ª255
+// for (var j=0; j<=2; j++){ hsv[j] = Math.round(hsv[j]); }
+ rgb = HSBtoRGB(x,y,z);
+ for (var j=0; j<=2; j++){ rgb[j] = Math.round(rgb[j]); }
+ cs[i] = '#'+format16(rgb[0])+format16(rgb[1])+format16(rgb[2]);
+ }
+ return(cs);
+}
+
+
+// +S-B ƒŠƒXƒg
+function sb_list(p,n){
+ var ps = pals[p].split('\n');
+ var rgb = to10rgb(ps[0]); //¨RGB
+ var hsv = RGBtoHSB(rgb[0],rgb[1],rgb[2]); //¨HSB
+ var cs = new Array(ps[0],ps[1]);
+ if(!cs[0]){ cs[0]='#ffffff'; }
+ if(hsv[1]==0 && !cs[1]){ cs[1]='#000000'; }
+ else if(!cs[1]){ cs[1]='#ffffff'; }
+
+ for (var i=2; i<14; i++){
+ if(ps[i] && (pon!=1 || pno!=p)){ cs[i]=ps[i]; continue; } //‚ ‚é
+ var y,z;
+ if(hsv[1]==0){ //”’•
+ y = 0;
+ if(i%2==0){ z = 255-i*n; }else{ z = 0+(i-1)*n; }
+ }else{
+ if(i%2==0){ //¶
+ y = hsv[1]+i*n;
+ z = hsv[2];
+ }else{ //‰E
+ y = hsv[1]+(i-1)*n;
+ z = hsv[2]-(i-1)*n;
+ }
+ }
+ while(z<0){ z+=255; } while(y<0){ y+=255; } //«0
+ while(z>255){ z-=255; } while(y>255){ y-=255; } //ª255
+// for (var j=0; j<=2; j++){ hsv[j] = Math.round(hsv[j]); }
+ rgb = HSBtoRGB(hsv[0],y,z);
+ for (var j=0; j<=2; j++){ rgb[j] = Math.round(rgb[j]); }
+ cs[i] = '#'+format16(rgb[0])+format16(rgb[1])+format16(rgb[2]);
+ }
+ return(cs);
+}
+
+
+// ŒÂ•Ê‚ÅH/S/B‚ðƒŠƒXƒgƒAƒbƒv
+function onplus(p,m){
+ var d = document;
+ var df = d.forms.palepale;
+ var n = Number(df.num.value); //+-
+ if(pon==1 && pno==p){ poncheck(); }
+
+ // ˜A‘±‚Ì‚Æ‚«
+ if(m>0 && n*(qon+1)>38){ qon=0; }
+ if(qno==p && qmo==m && qon>=1){ qon++; n*=(qon+1)/2; }
+ else{ qno=p; qmo=m; qon=1; }
+
+ var ps = pals[p].split('\n');
+ var rgb = to10rgb(ps[0]); //¨RGB
+ var hsv = RGBtoHSB(rgb[0],rgb[1],rgb[2]); //¨HSB
+ var cs = new Array();
+ if(m==2){ n*=-1; }
+ for (var i=0; i<14; i++){
+ var z;
+ if(m==0){ z = hsv[m]+((i%2)*2-1)*Math.round(Math.floor(i/2)*(n)); }
+ else{ z = hsv[m]+i*n; }
+ while(z<0){ z+=255; } //«0
+ while(z>255){ z-=255; } //ª255
+// for (var j=0; j<=2; j++){ hsv[j] = Math.round(hsv[j]); }
+ if(m==1){ rgb = HSBtoRGB(hsv[0],z,hsv[2]); } //¨HSB
+ else if(m==2){ rgb = HSBtoRGB(hsv[0],hsv[1],z); }
+ else{ rgb = HSBtoRGB(z,hsv[1],hsv[2]); } //¨HSB
+ for (var j=0; j<=2; j++){ rgb[j] = Math.round(rgb[j]); }
+ cs[i] = '#'+format16(rgb[0])+format16(rgb[1])+format16(rgb[2]);
+ }
+ checkout(1);
+ d.paintbbs.setColors(String(cs.join('\n')));
+}
+
+
+// ‘S‘Ì‚ÌH/S/B‚ðƒvƒ‰ƒXƒ}ƒCƒiƒX
+function alplus(m,n){
+ var d = document;
+ var cs = String(d.paintbbs.getColors()).split('\n');
+ n *= Number(d.forms.palepale.num.value); //+-
+ poncheck();
+
+ for (var i=0; i<cs.length; i++){
+ var rgb = to10rgb(cs[i]); //¨RGB
+ var hsv = RGBtoHSB(rgb[0],rgb[1],rgb[2]); //¨HSB
+ //ª–¾“x255‚Ì‚Æ‚«Ê“xŒ¸
+ if(m==2 && n>0 && hsv[2]>=255){
+ hsv[1] -= n;
+ if(hsv[1]<0){ hsv[1]=0; }else if(hsv[1]>255){ hsv[1]=255; } //«0 or ª255
+ }
+ hsv[m] += n;
+ //«0 ª255
+ if(m==0){
+ if(hsv[0]<0){ hsv[0]+=255; }else if(hsv[0]>255){ hsv[0]-=255; }
+ }else{
+ if(hsv[m]<0){ hsv[m]=0; }else if(hsv[m]>255){ hsv[m]=255; }
+ }
+// for (var j=0; j<=2; j++){ hsv[j] = Math.round(hsv[j]); }
+ rgb = HSBtoRGB(hsv[0],hsv[1],hsv[2]); //¨HSB
+ for (var j=0; j<=2; j++){ rgb[j] = Math.round(rgb[j]); }
+ cs[i] = '#'+format16(rgb[0])+format16(rgb[1])+format16(rgb[2]);
+ }
+ checkout();
+ d.paintbbs.setColors(String(cs.join('\n')));
+}
+
+
+// ‘S‘Ì‚ÌRGB‚ðƒvƒ‰ƒXƒ}ƒCƒiƒX
+function alrgb(n){
+ var d = document;
+ var cs = String(d.paintbbs.getColors()).split('\n');
+ n *= Number(d.forms.palepale.num.value); //+-
+ poncheck();
+
+ for (var i=0; i<cs.length; i++){
+ var rgb = to10rgb(cs[i]); //¨RGB
+ for (var j=0; j<=2; j++){
+ rgb[j] += n;
+ rgb[j] = Math.round(rgb[j]);
+ if(rgb[j]<0){ rgb[j]=0; } //«0
+ if(rgb[j]>255){ rgb[j]=255; } //ª255
+ }
+ cs[i] = '#'+format16(rgb[0])+format16(rgb[1])+format16(rgb[2]);
+ }
+ checkout();
+ d.paintbbs.setColors(String(cs.join('\n')));
+}
+
+
+// ƒOƒ‰ƒf[ƒVƒ‡ƒ“
+function grady(m){
+ var d = document;
+ var df = d.forms.palepale;
+ var n = 2;
+ if(df.gradc){
+ for(var j=0; j<df.gradc.length; j++){
+ if(df.gradc[j].checked == true){ n = Number(df.gradc[j].value); break; }
+ }
+ }
+ var cs = String(d.paintbbs.getColors()).split('\n');
+ var gs = new Array(1,13);
+ if(n==3){ gs = new Array(1,7,13); }
+ else if(n==4){ gs = new Array(1,5,9,13); }
+ poncheck();
+ cs[1] = cs[0];
+
+ // 2`4F
+ for (var i=0; i<gs.length-1; i++){
+ var p=gs[i]; var q=gs[(i+1)];
+ var rgbp = to10rgb(cs[p]); //¨RGB
+ var rgbq = to10rgb(cs[q]); //¨RGB2
+ // HSB
+ var hsvp = new Array();
+ var hsvq = new Array();
+ if(m==1 || m==-1){
+ hsvp = RGBtoHSB(rgbp[0],rgbp[1],rgbp[2]); //¨HSB
+ hsvq = RGBtoHSB(rgbq[0],rgbq[1],rgbq[2]); //¨HSB
+ }
+ // ƒpƒŒƒbƒg‚ÌF
+ for (var k=p+1; k<q; k++){
+ var rgb = new Array();
+ // HSB
+ if(m==1 || m==-1){
+ var hsv = new Array();
+ for (var j=0; j<=2; j++){ // RGB
+ var sa = (hsvp[j]-hsvq[j])/(q-p);
+ if(j==0){ // H
+ if(m*hsvp[j]>m*hsvq[j]){ sa = Math.abs(sa) - 255/(q-p); }
+ hsv[0] = hsvp[0] + m*Math.abs(sa)*(k-p);
+ if(hsv[0]<0){ hsv[0]+=255; }else if(hsv[0]>255){ hsv[0]-=255; }
+ }else{ // S,B
+ hsv[j] = hsvp[j] - sa*(k-p);
+ if(hsv[j]<0){ hsv[j]=0; }else if(hsv[j]>255){ hsv[j]=255; }
+ }
+ }
+ rgb = HSBtoRGB(hsv[0],hsv[1],hsv[2]); //¨HSB
+ for (var j=0; j<=2; j++){ rgb[j] = Math.round(rgb[j]); }
+ // RGB
+ }else{
+ for (var j=0; j<=2; j++){ // RGB
+ var sa = (rgbp[j]-rgbq[j])/(q-p);
+ rgb[j] = Math.round(rgbp[j] - sa*(k-p));
+ if(rgb[j]<0){ rgb[j]=0; }else if(rgb[j]>255){ rgb[j]=255; } //ª«
+ }
+ }
+ cs[k] = '#'+format16(rgb[0])+format16(rgb[1])+format16(rgb[2]);
+ }
+ }
+ cs[0]=cs[1]; cs[1]='#ffffff';
+ checkout();
+ d.paintbbs.setColors(String(cs.join('\n')));
+}
+
+
+// -------------------------------------------------------------------------
+// ƒpƒŒƒbƒg‚̃Tƒ“ƒvƒ‹ƒJƒ‰[
+function csamp(p,pz,lst){
+ var ss='';
+ var ps = pz.split('\n');
+ var slong = sams.length;
+ var psy = check_h_sb(lst); if(psy==1){ slong = samx.length; }
+ // color-sample
+ for (var i=0; i<slong; i++){
+ // color-title
+ var k,cl='',rgb='',hsv='',ctl='';
+ if(psy==1){ k=samx[i]; }else{ k=sams[i]; }
+ if(ps[k]){
+ rgb = to10rgb(ps[k]); //¨RGB
+ hsv = RGBtoHSB(rgb[0],rgb[1],rgb[2]); //¨HSB
+ for (var j=0; j<=2; j++){ hsv[j] = Math.round(hsv[j]); }
+ ctl = 'HSB: '+hsv[0]+','+hsv[1]+','+hsv[2]+'\n';
+ ctl += 'RGB: '+rgb[0]+','+rgb[1]+','+rgb[2]+'\nRGB16: '+ps[k];
+ }
+ if(selfv[2]) cl=selfv[2].replace(/\$FONT/i,ps[k]);
+ if(selfv[1]) ss += '<font id="font_'+p+'_'+k+'" '+cl+' title="'+ctl+'">'+selfv[1]+'</font>';
+ }
+ return ss;
+}
+
+
+// ƒpƒŒƒbƒg‚̃ŠƒXƒg
+function palette_list(lst){
+ var d = document;
+ var ds = '';
+ for (var p=0; p<pals.length; p++){
+ if(!pals[p]){ continue; }
+ var samw = csamp(p,pals[p],lst); //ƒTƒ“ƒvƒ‹
+
+ // element
+ if(selfv[4]) ds+=inr+'name="rad" value="'+p+'" onclick="rady('+p+')" '+selfv[4]+samw+'\n';
+// ds+='<font color="'+ps[0]+'" id="font_'+p+'" title="'+ctl+'">'+samw+'</font>';
+ if(selfv[5]) ds+=inp+'onclick="onplus('+p+',0)" '+selfv[5];
+ if(selfv[6]) ds+=inp+'onclick="onplus('+p+',1)" '+selfv[6];
+ if(selfv[7]) ds+=inp+'onclick="onplus('+p+',2)" '+selfv[7];
+ if(selfv[8]) ds+=inp+'onclick="savy('+p+')" '+selfv[8];
+ if(selfv[9]) ds+=inp+'onclick="defy('+p+')" '+selfv[9];
+ }
+ return ds;
+}
+
+
+// ƒ`ƒFƒbƒN‚ð‚‚¯‚éAƒtƒHƒ“ƒgƒJƒ‰[‚̃Tƒ“ƒvƒ‹‚ð•ÏX
+function checkin(p,not){
+ qno=''; qmo=''; qon=0;
+ if(!pals[p]){ return; }
+ var d = document;
+ // font-color
+ var ps = pals[p].split('\n');
+ var slong = sams.length;
+ var psy = check_h_sb(); if(psy==1){ slong = samx.length; }
+ // color-sample
+ for (var i=0; i<slong; i++){
+ // color-title
+ var k,rgb='',hsv='',ctl='';
+ if(psy==1){ k=samx[i]; }else{ k=sams[i]; }
+ if(ps[k]){
+ rgb = to10rgb(ps[k]); //¨RGB
+ hsv = RGBtoHSB(rgb[0],rgb[1],rgb[2]); //¨HSB
+ for (var j=0; j<=2; j++){ hsv[j] = Math.round(hsv[j]); }
+ ctl = 'HSB: '+hsv[0]+','+hsv[1]+','+hsv[2]+'\n';
+ ctl += 'RGB: '+rgb[0]+','+rgb[1]+','+rgb[2]+'\nRGB16: '+ps[k];
+ }
+ // replace
+ var ds;
+ if(brwz==1){ ds = d.all('font_'+p+'_'+k); }
+ else if(brwz==2){ ds = d.getElementById('font_'+p+'_'+k); }
+ if(ds){
+ if(ds.style.background){ ds.style.background = ps[k]; }
+ if(ds.style.backgroundColor){ ds.style.backgroundColor = ps[k]; }
+ if(ds.style.color){ ds.style.color = ps[k]; }
+ if(ds.color){ ds.color = ps[k]; }
+ }
+ }
+
+ // check
+ if(not!=1){
+ var df = d.forms.palepale;
+ for(var j=0; j<df.rad.length; j++){
+ if(df.rad[j].value == p){
+ df.rad[j].checked = true; break; }
+ }
+ }
+}
+
+
+// check‚ðŠO‚·
+function checkout(q){
+ pon=0; pno='';
+ if(q!=1){ qno=''; qmo=''; qon=0; }
+ var df = document.forms.palepale;
+ for(var j=0; j<df.rad.length; j++){
+ if(df.rad[j].checked == true){
+ df.rad[j].checked = false; break; }
+ }
+}
+
+
+// ˆÈ‘O‚̃pƒŒƒbƒg‚ðŽ©“®•Û‘¶
+function poncheck(not){
+ var d = document;
+ var df = document.forms.palepale;
+ if(df.autosave&&df.autosave.checked==false){ return; }
+ else if(pon==1){
+ var pget = String(d.paintbbs.getColors());
+ if(pals[pno] != pget){
+ pals[pno] = pget;
+ checkin(pno,1);
+ if(not!=1){ pcookset(1); }
+ }
+ }
+}
+
+
+// ƒpƒŒƒbƒg‚ðƒZ[ƒu
+function savy(p){
+ var d = document;
+ pals[p] = String(d.paintbbs.getColors());
+ checkin(p);
+ pcookset(1);
+ pon=1; pno=p;
+}
+
+
+// ƒpƒŒƒbƒg‚ðƒfƒtƒHƒ‹ƒg‚É
+function defy(p){
+ checkout();
+ var q = pdefs[p];
+ var df = document.forms.palepale;
+ if(check_h_sb()==1){ q = pdefx[p]; }
+ if(q){
+ pals[p] = q;
+ rady(p,2);
+ checkin(p);
+ }else{ minsy(p); }
+}
+
+
+// ƒpƒŒƒbƒg’ljÁ
+function plusy(){
+ var d = document;
+ if(brwz==1 || brwz==2){
+ var p=pals.length;
+ var pz = String(d.paintbbs.getColors());
+ if(pz){ pals[p] = pz; }
+ else{
+ pals[p] = '#'+Number(d.paintbbs.getInfo().m.iColor).toString(16);
+ rady(p,1);
+ }
+ }
+ if(brwz==1 && d.all('palelist').innerHTML){
+ d.all('palelist').innerHTML = palette_list();
+ checkin(p);
+ }else if(brwz==2 && d.getElementById('palelist').innerHTML){
+ d.getElementById('palelist').innerHTML = palette_list();
+ checkin(p);
+ }
+}
+
+
+// ƒpƒŒƒbƒgíœ
+function minsy(p){
+ var d = document;
+ var df = d.forms.palepale;
+ if(!p&&p!=0){
+ for(var j=0; j<=df.rad.length; j++){
+ if(df.rad[j] && df.rad[j].checked==true){p=Number(df.rad[j].value); break; }
+ }
+ }
+ if((!p&&p!=0)||p<0){ return; }
+ pals[p] = '';
+ var plong = pdefs.length;
+ if(check_h_sb()==1){ plong = pdefx.length; }
+ if(p>=plong){
+ var k=0;
+ var pds = new Array(); pds = pals;
+ pals = new Array();
+ for(var j=0; j<pds.length; j++){
+ if(p!=j && pds[j]){ pals[k] = pds[j]; k++; }
+ }
+ }
+
+ if(brwz==1 && d.all('palelist').innerHTML){
+ d.all('palelist').innerHTML = palette_list();
+ }else if(brwz==2 && d.getElementById('palelist').innerHTML){
+ d.getElementById('palelist').innerHTML = palette_list();
+ }
+ checkout();
+}
+
+
+// ƒpƒŒƒbƒgƒfƒtƒHƒ‹ƒg
+function def_list(){
+ var okd = confirm("‘S‘̂̃pƒŒƒbƒg‚ðƒfƒtƒHƒ‹ƒg‚É–ß‚µ‚Ü‚·B\n‚æ‚낵‚¢‚Å‚·‚©H");
+ if(!okd){ return; }
+ var d = document;
+ var df = d.forms.palepale;
+ pals = new Array();
+ var psy = 0;
+ var plong = pdefs.length;
+ if(check_h_sb()==1){ psy=1; plong = pdefx.length; }
+ for (var p=0; p<plong; p++){
+ if(psy==1){ pals[p]=pdefx[p]; }else{ pals[p]=pdefs[p]; }
+ }
+ for (var p=0; p<pals.length; p++){ if(pals[p]){ rady(p,1); } }
+
+ if(brwz==1 && d.all('palelist').innerHTML){
+ d.all('palelist').innerHTML = palette_list();
+ }else if(brwz==2 && d.getElementById('palelist').innerHTML){
+ d.getElementById('palelist').innerHTML = palette_list();
+ }else{
+ for (var p=0; p<pals.length; p++){
+ if(pals[p]){ checkin(p,1); }
+ }
+ }
+}
+
+
+// ƒfƒtƒHƒ‹ƒg h_sb ‚̃tƒH[ƒ€‚̃`ƒFƒbƒN. H‹‚Ƀ`ƒFƒbƒN‚ª‚‚¢‚Ä‚é‚È‚ç1
+function check_h_sb(lst){
+ var ch = 0;
+ var df = document.forms.palepale;
+ if(lst!=1 && df && df.h_sb){
+ for (var i=0; i<df.h_sb.length; i++){
+ if(df.h_sb[i].value==1 && df.h_sb[i].checked==true){ ch=1; break; }
+ }
+ }else{ ch=psx; }
+ return ch;
+}
+
+
+// ƒpƒŒƒbƒgƒf[ƒ^ ƒAƒbƒvƒ[ƒh
+function pupload(){
+ var d = document;
+ var df = d.forms.palepale;
+ var qs = new Array();
+ var palx='';
+ if(df.palz){ palx = df.palz.value; }
+ if(!palx){ return; }
+ pals = new Array();
+ if(eval(palx)){}
+ else{
+ var px = palx.split(/\(|\)/);
+ var ps = px[1].split(',');
+ for (var p=0; p<ps.length; p++){
+ var q=ps[p].replace(/[^0-9a-fA-F]/g,''); pals[p] = q;
+ }
+ }
+
+ for (var p=0; p<pals.length; p++){ if(pals[p]){ rady(p,1); } }
+
+ if(brwz==1 && d.all('palelist').innerHTML){
+ d.all('palelist').innerHTML = palette_list();
+ }else if(brwz==2 && d.getElementById('palelist').innerHTML){
+ d.getElementById('palelist').innerHTML = palette_list();
+ }else{
+ for (var p=0; p<pals.length; p++){
+ if(pals[p]){ checkin(p,1); }
+ }
+ }
+}
+
+
+// ƒpƒŒƒbƒgƒf[ƒ^ ƒ_ƒEƒ“ƒ[ƒh
+function pdownload(){
+ var d = document;
+ var df = d.forms.palepale;
+ var qs = new Array();
+ for (var p=0; p<pals.length; p++){
+ qs[p] = "\'"+pals[p].replace(/\n/g,'\\n')+"\'";
+ }
+ var palx = 'pals = new Array(\n' + qs.join('\,\n') + '\n);';
+ if(df.palz){ df.palz.value = palx; }
+}
+
+
+// ‘S‘̂̃pƒŒƒbƒgî•ñ‚ðƒNƒbƒL[‚ɃZ[ƒu
+function pcookset(o){
+ var df = document.forms.palepale;
+ if(o&&df.autosave&&df.autosave.checked==false){ return; }
+ var exp=new Date();
+ exp.setTime(exp.getTime()+1000*86400*60);
+ var cs = new Array();
+ for(var i=0; i<pals.length; i++){
+ cs[i] = escape(pals[i].replace(/\n/g,'_'));
+ }
+ var cooki = '';
+ if(df.num){ cooki += df.num.value; }
+ cooki += '_'+check_h_sb()+'_%00';
+ cooki += cs.join('%00');
+ document.cookie = cname + cooki + "; expires=" + exp.toGMTString();
+}
+
+
+// ‘S‘̂̃pƒŒƒbƒgî•ñ‚ðƒNƒbƒL[‚©‚çƒ[ƒh
+function pcookget(){
+ var cooks = document.cookie.split("; ");
+ var cooki = '';
+ for (var i=0; i<cooks.length; i++){
+ if (cooks[i].substr(0,cname.length) == cname){
+ cooki = cooks[i].substr(cname.length,cooks[i].length);
+ break;
+ }
+ }
+ if(cooki){
+ var cs = cooki.split('%00');
+ pals = new Array();
+ for(var i=0; i<cs.length-1; i++){
+ pals[i] = unescape(cs[(i+1)]).replace(/\_/g,"\n");
+ }
+ if(cs[0]){
+ var ps = cs[0].split('_');
+ if(ps[0]){ pnum = ps[0]; }
+ if(ps[1]){ psx = ps[1]; }else if(!ps[1]&&ps[1]==0){ psx=0; }
+ }
+ }
+}
+
+
+// ‘Œ¸‚·‚锂ð‘‚₵‚½‚茸‚炵‚½‚è
+function num_plus(n){
+ var df = document.forms.palepale;
+ var m = Number(df.num.value); var l=n;
+ n *= Math.abs(Math.round(m/10))+1; if(n==0){ n=l; }
+ df.num.value = m+n;
+}
+
+
+// ƒg[ƒ“ƒZƒŒƒNƒg‚Ì’l‚ð}
+function tone_plus(n){
+ var df = document.forms.palepale;
+ var m = Number(df.tone.value);
+ if(m>0){ n = Math.floor(m/10 + n)*10; }
+ if(n<0){ n=0; }else if(n<5){ n=5; }else if(n>100){ n=100; }
+ df.tone.value = n;
+ tone_sel(n);
+}
+
+
+// ƒg[ƒ“ƒZƒŒƒNƒg
+function tone_sel(t){
+ var dp=document.paintbbs;
+ t = Number(t);
+ if(t==0){ dp.getInfo().m.iTT = 0; }
+ else{ dp.getInfo().m.iTT = Math.floor(t/10)+1; }
+}
+
+
+// -------------------------------------------------------------------------
+// document.write
+function palette_selfy(){
+ var d = document;
+ var df = document.forms.palepale;
+ var pzs=palette_selfy.arguments; //ƒpƒŒƒbƒgŽw’肪‚ ‚Á‚½‚Æ‚«
+
+ // browzer
+ if(brwz!=1 && brwz!=2){ return; }
+
+ // ƒpƒŒƒbƒg‚ƃpƒŒƒbƒgƒNƒbƒL[
+ var plong = pdefs.length;
+ if(psx==1){ plong = pdefx.length; }
+ for (var p=0; p<plong; p++){
+ if(psx==1){ pals[p]=pdefx[p]; }else{ pals[p]=pdefs[p]; }
+ if(pzs && pzs.length>=1){ var ok=0; //H
+ for (var q=0; q<pzs.length; q++){ if(p==pzs[q]){ ok=1; break; } }
+ if(ok!=1){ pals[p]=''; }
+ }
+ }
+ pcookget(); // cookie-get
+ psx_ch[psx] = 'checked ';
+ for (var p=0; p<pals.length; p++){ if(pals[p]){ rady(p,1,1); } }
+
+ // basic
+ d.write(selfytag[0]);
+ if(selfv[3]) d.write(inr+'name="rad" value="-1" onclick="rady()" '+selfv[3]);
+ if(pbase) d.write(csamp(-1,pbase,1));
+
+ // +-‚·‚é”
+ if(selfv[0]){
+ d.write('\n<small>&nbsp;</small>+-');
+ d.write('<input type="text" name="num" value="'+pnum+'" '+selfv[0]);
+ d.write(inp+'value="+" onclick="num_plus(1)">');
+ d.write(inp+'value="-" onclick="num_plus(-1)">\n');
+ }
+ // ƒpƒŒƒbƒgƒŠƒXƒg
+ if(pdefs||pdefx) d.write('<div id="palelist">\n'+palette_list(1)+'</div>\n');
+
+ // ‘S‘Ì‚Ì HSBARGB +-
+ if(selfytag[1]) d.write(selfytag[1]);
+ if(selfv[10]) d.write(inp+'onclick="alplus(0,1)" ' +selfv[10]);
+ if(selfv[12]) d.write(inp+'onclick="alplus(1,1)" ' +selfv[12]);
+ if(selfv[14]) d.write(inp+'onclick="alplus(2,1)" ' +selfv[14]);
+ if(selfv[16]) d.write(inp+'onclick="alrgb(1)" ' +selfv[16]);
+ if(selfv[11]) d.write(inp+'onclick="alplus(0,-1)" '+selfv[11]);
+ if(selfv[13]) d.write(inp+'onclick="alplus(1,-1)" '+selfv[13]);
+ if(selfv[15]) d.write(inp+'onclick="alplus(2,-1)" '+selfv[15]);
+ if(selfv[17]) d.write(inp+'onclick="alrgb(-1)" ' +selfv[17]);
+
+ // ƒg[ƒ“ƒZƒŒƒNƒg
+ if(selfv[0]){
+ d.write('Tone <select name="tone" onchange="tone_sel(this.value)">');
+ for (var i=0; i<=100; i+=5){
+ d.write('<option value="'+i+'">'+i+'%</option>\n'); if(i>=10){i+=5;}
+ }
+ d.write('</select>');
+ d.write(inp+'value="+" onclick="tone_plus(1)">');
+ d.write(inp+'value="-" onclick="tone_plus(-1)">\n');
+ }
+
+ // GRADATION
+ if(selfytag[2]) d.write(selfytag[2]);
+ if(selfv[18]) d.write(inr+'name="gradc" value="2" '+selfv[18]); //18
+ if(selfv[19]) d.write(inr+'name="gradc" value="3" '+selfv[19]); //19
+ if(selfv[20]) d.write(inr+'name="gradc" value="4" '+selfv[20]); //20
+ if(selfv[21]) d.write(inp+'onclick="grady(0)" ' +selfv[21]); //21
+ if(selfv[22]) d.write(inp+'onclick="grady(1)" ' +selfv[22]); //22
+ if(selfv[23]) d.write(inp+'onclick="grady(-1)" ' +selfv[23]); //23
+
+ // ’ljÁEíœ
+ if(selfytag[3]) d.write(selfytag[3]);
+ if(selfv[24]) d.write(inp+'onclick="plusy()" ' +selfv[24]); //24
+ if(selfv[25]) d.write(inp+'onclick="minsy()" ' +selfv[25]); //25
+
+ // ƒZ[ƒuEƒI[ƒgƒZ[ƒu
+ if(selfytag[4]) d.write(selfytag[4]);
+ if(selfv[26]) d.write('<input type="checkbox" name="autosave" value="1" '+selfv[26]); //26
+ if(selfv[27]) d.write(inp+'onclick="pcookset()" ' +selfv[27]); //27
+
+ // ƒfƒtƒHƒ‹ƒg
+ if(selfytag[5]) d.write(selfytag[5]);
+ if(selfv[28]) d.write(inr+'name="h_sb" value="1" ' +psx_ch[1]+selfv[28]); //28
+ if(selfv[29]) d.write(inr+'name="h_sb" value="0" ' +psx_ch[0]+selfv[29]); //29
+ if(selfv[30]) d.write(inp+'onclick="def_list()" ' +selfv[30]); //30
+
+ // UPLOAD / DOWNLOAD
+ if(selfytag[6]) d.write(selfytag[6]);
+ if(selfv[31]) d.write('<input type="text" name="palz" '+selfv[31]); //31
+ if(selfv[32]) d.write(inp+'onclick="pupload()" ' +selfv[32]); //32
+ if(selfv[33]) d.write(inp+'onclick="pdownload()" ' +selfv[33]); //33
+
+ // /FORM
+ if(selfytag[7]) d.write(selfytag[7]);
+}
diff --git a/static/js/shobon.js b/static/js/shobon.js
new file mode 100644
index 0000000..b4e48f6
--- /dev/null
+++ b/static/js/shobon.js
@@ -0,0 +1,408 @@
+var are_filters = false;
+var hide_word = new Set()
+var hide_name = new Set();
+var hide_id = new Set();
+
+var shobon_ver = "v0.4+";
+function shobon() {
+ console.log("Running shobon " + shobon_ver);
+
+ boardName = document.getElementsByName("board")[0].value;
+ var inThread = document.getElementsByTagName("body")[0].className == "threadpage";
+ var newRepliesCounter = 0;
+
+ if(!inThread) {
+ /* Create settings link */
+ var box = document.getElementsByClassName("links")[0];
+ box.appendChild(document.createTextNode(" | "));
+ var slnk = document.createElement("a");
+ slnk.href = "#";
+ slnk.innerHTML = "<b>Configuración</b>";
+ slnk.addEventListener("click", shobonSettings);
+ box.appendChild(slnk);
+ }
+
+ if(localStorage.getItem("shobon_on") == "false") {
+ console.log("Shutting down Shobon");
+ return;
+ }
+
+ if (localStorage.getItem("shobon_usefilters") != "false") {
+ loadFilters();
+ }
+
+ var threadList = document.getElementsByClassName("thread");
+ for (var i = 0; i < threadList.length; i++) {
+ var threadId;
+ var thread = threadList[i];
+ var replyList = thread.getElementsByClassName("reply");
+ if (inThread) {
+ threadId = document.getElementsByName("parent")[0].value;
+ } else {
+ threadId = thread.getElementsByTagName("input").parent.value;
+ }
+
+ var lastReplyN = replyList[replyList.length - 1].attributes["data-n"].value;
+
+ if (localStorage.getItem(boardName + "_" + threadId) == null) {
+ localStorage.setItem(boardName + "_" + threadId, lastReplyN);
+ }
+ var lastSeen = localStorage.getItem(boardName + "_" + threadId);
+ var newRepliesInThread = 0;
+
+ for (var e = 0; e < replyList.length; e++) {
+ var reply = replyList[e];
+ var message = reply.getElementsByClassName("msg")[0];
+
+ if(localStorage.getItem("shobon_newposts") == "true") {
+ var replyId = reply.attributes["data-n"].value;
+ var isNewReply = parseInt(lastSeen) < parseInt(replyId);
+
+ if (isNewReply) {
+ newRepliesCounter++;
+ newRepliesInThread++;
+ reply.children[0].innerHTML += " <span class='shobonNew' style='color: #CC6666; font-weight: bold;'>NUEVO!</span>";
+ }
+ }
+
+ // ocultar mensajes que tienen palabras en la blacklist
+ if(are_filters) {
+ checkBlackList(reply);
+ }
+
+ // reemplaza los codigos iso de los paises por el nombre completo
+ if (localStorage.getItem("shobon_country") == "true" && boardName == "world") {
+ replaceCountryName(reply)
+ }
+ // colorea los id's
+ if(localStorage.getItem("shobon_ids") != "false") {
+ paintIds(reply);
+ }
+ // deja la barra superior fija
+ if(localStorage.getItem("shobon_navbar") == "true") {
+ fixedNav();
+ }
+ }
+ if (newRepliesInThread > 0 && !inThread) {
+ thread.getElementsByClassName("threadlinks")[0].innerHTML += "<span onClick='localStorage.setItem(\"" + boardName + "_" + threadId + "\" , " + lastReplyN + "); this.hidden = true;' style='font-weight: bold; background: #81a2be; padding: 5px; border-radius: 5px; float: right; margin-bottom: 10px;'>Marcar como leido</span>";
+ }
+
+ }
+ if (newRepliesCounter > 0 && !inThread) {
+ var banner = document.createElement("span");
+ banner.onclick = function() { this.hidden = true; };
+ banner.setAttribute("style", "font-weight: bold; background: #8c9440; padding: 8px; border-radius: 30px; float: right; position: fixed; bottom: 10px; right: 10px");
+ banner.textContent = "Nuevas respuestas: " + newRepliesCounter;
+ document.body.appendChild(banner);
+ }
+
+ if (inThread) {
+ localStorage.setItem(boardName + "_" + threadId, lastReplyN);
+ }
+
+}
+
+function on_checked(e) {
+ localStorage.setItem(e.target.id, e.target.checked);
+}
+function createCheckbox(name, label, def) {
+ var lbl = document.createElement("label");
+ var chk = document.createElement("input");
+ chk.type = "checkbox";
+ chk.id = name;
+ chk.onchange = on_checked;
+ lbl.appendChild(chk);
+ lbl.insertAdjacentHTML("beforeend", " "+label+" ");
+
+ var checked = localStorage.getItem(name);
+ if(checked !== null) {
+ chk.checked = (checked == "true");
+ } else {
+ chk.checked = def;
+ }
+
+ return lbl;
+}
+function createOption(name, label) {
+ var opt = document.createElement("option");
+ opt.value = name;
+ opt.text = label;
+ return opt;
+}
+function createButton(label, func) {
+ var btn = document.createElement("button");
+ btn.type = "button";
+ btn.textContent = label;
+ btn.onclick = func;
+ return btn;
+}
+function createTh(label, w) {
+ var th = document.createElement("th");
+ th.textContent = label;
+ th.width = w;
+ return th;
+}
+function loadFilters() {
+ var filters = JSON.parse(localStorage.getItem("shobon_filters"));
+
+ if(filters) {
+ are_filters = true;
+ hide_word = new Set(filters.word);
+ hide_name = new Set(filters.name);
+ hide_id = new Set(filters.id);
+ }
+}
+function saveFilters() {
+ var filters = {
+ "word": Array.from(hide_word),
+ "name": Array.from(hide_name),
+ "id": Array.from(hide_id)
+ };
+ localStorage.setItem("shobon_filters", JSON.stringify(filters));
+}
+function deleteFilter(e) {
+ var tr = this.parentElement.parentElement;
+ var name = tr.dataset.name;
+ var type = tr.dataset.type;
+ switch(type) {
+ case "word":
+ hide_word.delete(name);
+ break;
+ case "name":
+ hide_name.delete(name);
+ break;
+ case "id":
+ hide_id.delete(name);
+ break;
+ }
+ saveFilters();
+ tr.remove();
+}
+function addFilter(e) {
+ var name = document.getElementById("txt_filter").value;
+ var type = document.getElementById("lst_type").value;
+ if(!name) {
+ return;
+ }
+
+ switch(type) {
+ case "word":
+ hide_word.add(name);
+ break;
+ case "name":
+ hide_name.add(name);
+ break;
+ case "id":
+ hide_id.add(name);
+ break;
+ }
+ addToFilterTable(name, type);
+ saveFilters();
+ document.getElementById("txt_filter").value = "";
+}
+
+function addToFilterTable(name, type) {
+ var dict = {"word": "Palabra", "name": "Nombre/Tripcode", "id": "ID"};
+ var table = document.getElementById("tbl_filters");
+
+ var td_type = document.createElement("td");
+ td_type.textContent = dict[type];
+ var td_name = document.createElement("td");
+ td_name.textContent = name;
+ var td_btn = document.createElement("td");
+ td_btn.appendChild(createButton("X", deleteFilter));
+
+ var tr = document.createElement("tr");
+ tr.dataset.type = type;
+ tr.dataset.name = name;
+ tr.appendChild(td_type);
+ tr.appendChild(td_name);
+ tr.appendChild(td_btn);
+
+ table.appendChild(tr);
+}
+function shobonSettings(e) {
+ e.preventDefault();
+
+ var titlebox = document.getElementById("titlebox");
+
+ var box = document.getElementById("settings");
+ if(box) {
+ box.hidden = !box.hidden;
+ } else {
+ box = document.createElement("div");
+ box.id = "settings";
+ box.className = "innerbox";
+ box.style.textAlign = "center";
+
+ var p = document.createElement("div");
+ p.appendChild(createCheckbox("shobon_on", "<b>Activar extensión</b>", true));
+ p.appendChild(createCheckbox("shobon_navbar", "Fijar barra superior", false));
+ p.appendChild(createCheckbox("shobon_ids", "Colorear IDs", true));
+ p.appendChild(createCheckbox("shobon_newposts", "Destacar mensajes nuevos", false));
+ p.appendChild(createCheckbox("shobon_country", "Reemplazar códigos de país por nombres", false));
+ p.appendChild(createCheckbox("shobon_time", "Convertir fechas a hora local", true));
+ p.appendChild(createCheckbox("shobon_backlink", "Mostrar quién ha citado un post", true));
+ p.appendChild(createCheckbox("shobon_preview", "Previsualizar citas", true));
+ p.appendChild(createCheckbox("shobon_usefilters", "Activar filtros", false));
+ /*var a = document.createElement("a");
+ a.href = "#";
+ a.innerText = "[Editar filtros]";
+ a.addEventListener("click", function() {
+ var x = document.getElementById("filters");
+ x.hidden = !x.hidden;
+ });
+ p.appendChild(a);*/
+ box.appendChild(p);
+
+ var title2 = document.createElement("h6");
+ title2.textContent = "Filtros";
+ title2.style.fontSize = "18px";
+ title2.style.margin = "0.5em 0";
+ box.appendChild(title2);
+
+ box.appendChild(document.createTextNode("Filtrar mensajes por: "));
+
+ var lst_type = document.createElement("select");
+ lst_type.id = "lst_type";
+ lst_type.appendChild(createOption("word", "Palabra"));
+ lst_type.appendChild(createOption("name", "Nombre/Tripcode"));
+ lst_type.appendChild(createOption("id", "ID"));
+ box.appendChild(lst_type);
+
+ var txt_filter = document.createElement("input");
+ txt_filter.id = "txt_filter";
+ txt_filter.type = "text";
+ box.appendChild(txt_filter);
+
+ box.appendChild(createButton("Agregar", addFilter));
+
+ var tbl_filters = document.createElement("table");
+ tbl_filters.id = "tbl_filters";
+ tbl_filters.border = "1";
+ tbl_filters.style.margin = "0 auto";
+ var row = document.createElement("tr");
+ row.appendChild(createTh("Tipo", 150));
+ row.appendChild(createTh("Filtro", 300));
+ row.appendChild(createTh("", 75));
+ tbl_filters.appendChild(row);
+ box.appendChild(tbl_filters);
+
+ var msg = document.createElement("a");
+ msg.style.display = "block";
+ msg.href = "#";
+ msg.textContent = "Actualizar página para ver cambios";
+ msg.style.marginTop = "1em";
+ msg.addEventListener("click", function() { location.reload(); });
+ box.appendChild(msg);
+
+ titlebox.appendChild(box);
+
+ var i;
+ hide_word.forEach(v => {
+ addToFilterTable(v, "word")
+ });
+ hide_name.forEach(v => {
+ addToFilterTable(v, "name")
+ });
+ hide_id.forEach(v => {
+ addToFilterTable(v, "id")
+ });
+ }
+}
+
+function replaceCountryName(reply) {
+ var country = JSON.parse('{"AF":"Afghanistan","AX":"A£land Islands","AL":"Albania","DZ":"Algeria","AS":"American Samoa","AD":"Andorra","AO":"Angola","AI":"Anguilla","AQ":"Antarctica","AG":"Antigua and Barbuda","AR":"Argentina","AM":"Armenia","AW":"Aruba","AU":"Australia","AT":"Austria","AZ":"Azerbaijan","BS":"Bahamas","BH":"Bahrain","BD":"Bangladesh","BB":"Barbados","BY":"Belarus","BE":"Belgium","BZ":"Belize","BJ":"Benin","BM":"Bermuda","BT":"Bhutan","BO":"Bolivia (Plurinational State of)","BQ":"Bonaire, Sint Eustatius and Saba","BA":"Bosnia and Herzegovina","BW":"Botswana","BV":"Bouvet Island","BR":"Brazil","IO":"British Indian Ocean Territory","BN":"Brunei Darussalam","BG":"Bulgaria","BF":"Burkina Faso","BI":"Burundi","KH":"Cambodia","CM":"Cameroon","CA":"Canada","CV":"Cabo Verde","KY":"Cayman Islands","CF":"Central African Republic","TD":"Chad","CL":"Chile","CN":"China","CX":"Christmas Island","CC":"Cocos (Keeling) Islands","CO":"Colombia","KM":"Comoros","CG":"Congo","CD":"Congo (Democratic Republic of the)","CK":"Cook Islands","CR":"Costa Rica","CI":"CAŒte d\'Ivoire","HR":"Croatia","CU":"Cuba","CW":"CuraAXao","CY":"Cyprus","CZ":"Czech Republic","DK":"Denmark","DJ":"Djibouti","DM":"Dominica","DO":"Dominican Republic","EC":"Ecuador","EG":"Egypt","SV":"El Salvador","GQ":"Equatorial Guinea","ER":"Eritrea","EE":"Estonia","ET":"Ethiopia","FK":"Falkland Islands (Malvinas)","FO":"Faroe Islands","FJ":"Fiji","FI":"Finland","FR":"France","GF":"French Guiana","PF":"French Polynesia","TF":"French Southern Territories","GA":"Gabon","GM":"Gambia","GE":"Georgia","DE":"Germany","GH":"Ghana","GI":"Gibraltar","GR":"Greece","GL":"Greenland","GD":"Grenada","GP":"Guadeloupe","GU":"Guam","GT":"Guatemala","GG":"Guernsey","GN":"Guinea","GW":"Guinea-Bissau","GY":"Guyana","HT":"Haiti","HM":"Heard Island and McDonald Islands","VA":"Holy See","HN":"Honduras","HK":"Hong Kong","HU":"Hungary","IS":"Iceland","IN":"India","ID":"Indonesia","IR":"Iran (Islamic Republic of)","IQ":"Iraq","IE":"Ireland","IM":"Isle of Man","IL":"Israel","IT":"Italy","JM":"Jamaica","JP":"Japan","JE":"Jersey","JO":"Jordan","KZ":"Kazakhstan","KE":"Kenya","KI":"Kiribati","KP":"Korea (Democratic People\'s Republic of)","KR":"Korea (Republic of)","KW":"Kuwait","KG":"Kyrgyzstan","LA":"Lao People\'s Democratic Republic","LV":"Latvia","LB":"Lebanon","LS":"Lesotho","LR":"Liberia","LY":"Libya","LI":"Liechtenstein","LT":"Lithuania","LU":"Luxembourg","MO":"Macao","MK":"Macedonia (the former Yugoslav Republic of)","MG":"Madagascar","MW":"Malawi","MY":"Malaysia","MV":"Maldives","ML":"Mali","MT":"Malta","MH":"Marshall Islands","MQ":"Martinique","MR":"Mauritania","MU":"Mauritius","YT":"Mayotte","MX":"Mexico","FM":"Micronesia (Federated States of)","MD":"Moldova (Republic of)","MC":"Monaco","MN":"Mongolia","ME":"Montenegro","MS":"Montserrat","MA":"Morocco","MZ":"Mozambique","MM":"Myanmar","NA":"Namibia","NR":"Nauru","NP":"Nepal","NL":"Netherlands","NC":"New Caledonia","NZ":"New Zealand","NI":"Nicaragua","NE":"Niger","NG":"Nigeria","NU":"Niue","NF":"Norfolk Island","MP":"Northern Mariana Islands","NO":"Norway","OM":"Oman","PK":"Pakistan","PW":"Palau","PS":"Palestine, State of","PA":"Panama","PG":"Papua New Guinea","PY":"Paraguay","PE":"Peru","PH":"Philippines","PN":"Pitcairn","PL":"Poland","PT":"Portugal","PR":"Puerto Rico","QA":"Qatar","RE":"RAcunion","RO":"Romania","RU":"Russian Federation","RW":"Rwanda","BL":"Saint BarthAclemy","SH":"Saint Helena, Ascension and Tristan da Cunha","KN":"Saint Kitts and Nevis","LC":"Saint Lucia","MF":"Saint Martin (French part)","PM":"Saint Pierre and Miquelon","VC":"Saint Vincent and the Grenadines","WS":"Samoa","SM":"San Marino","ST":"Sao Tome and Principe","SA":"Saudi Arabia","SN":"Senegal","RS":"Serbia","SC":"Seychelles","SL":"Sierra Leone","SG":"Singapore","SX":"Sint Maarten (Dutch part)","SK":"Slovakia","SI":"Slovenia","SB":"Solomon Islands","SO":"Somalia","ZA":"South Africa","GS":"South Georgia and the South Sandwich Islands","SS":"South Sudan","ES":"Spain","LK":"Sri Lanka","SD":"Sudan","SR":"Suriname","SJ":"Svalbard and Jan Mayen","SZ":"Swaziland","SE":"Sweden","CH":"Switzerland","SY":"Syrian Arab Republic","TW":"Taiwan, Province of China","TJ":"Tajikistan","TZ":"Tanzania, United Republic of","TH":"Thailand","TL":"Timor-Leste","TG":"Togo","TK":"Tokelau","TO":"Tonga","TT":"Trinidad and Tobago","TN":"Tunisia","TR":"Turkey","TM":"Turkmenistan","TC":"Turks and Caicos Islands","TV":"Tuvalu","UG":"Uganda","UA":"Ukraine","AE":"United Arab Emirates","GB":"United Kingdom of Great Britain and Northern Ireland","US":"United States of America","UM":"United States Minor Outlying Islands","UY":"Uruguay","UZ":"Uzbekistan","VU":"Vanuatu","VE":"Venezuela (Bolivarian Republic of)","VN":"Viet Nam","VG":"Virgin Islands (British)","VI":"Virgin Islands (U.S.)","WF":"Wallis and Futuna","EH":"Western Sahara","YE":"Yemen","ZM":"Zambia","ZW":"Zimbabwe"}');
+ var countryEM = reply.getElementsByTagName("em")[0];
+ var newCountryStr = country[countryEM.innerText.substr(1, 2)];
+ countryEM.innerText = "(" + newCountryStr + ")";
+}
+
+function checkBlackList(reply) {
+ var i;
+
+ // Check words
+ var low = reply.children[1].innerText.toLowerCase();
+ hide_word.forEach(v => {
+ console.log(v);
+ if (low.includes(v.toLowerCase())) {
+ hidepost(reply);
+ }
+ });
+
+ // Check name/trip
+ var msg_name = reply.firstElementChild.getElementsByClassName("name")[0].textContent.toLowerCase();
+ hide_name.forEach(v => {
+ if (msg_name.includes(hide_name[i])) {
+ hidepost(reply);
+ }
+ });
+
+ // Check ID
+ var date_div = reply.firstElementChild.getElementsByClassName("date")[0].textContent;
+ var id_index = date_div.indexOf("ID:");
+ if(id_index != -1) {
+ var id = date_div.substr(id_index+3);
+
+ hide_id.forEach(v => {
+ if(id.includes(v)) {
+ hidepost(reply);
+ }
+ });
+ }
+}
+
+function paintIds(reply) {
+ var dateId = reply.getElementsByClassName("date")[0];
+ if (dateId.innerText.includes("ID:")) {
+ var postDate = dateId.innerText.split("ID:")[0];
+ var userId = dateId.innerText.split("ID:")[1];
+ var idColor = toHex(userId).substring(0, 6);
+ var reverseColor = invertColor(idColor);
+ var lastChar = userId.substring(userId.length-1, userId.length);
+ dateId.innerHTML = postDate + "<span style='background-color:#" + idColor + "; color:#" + reverseColor + "; padding:0 3px; border-radius:5px; font-size:0.9em; vertical-align:top;'>ID:" + userId + "</span>";
+ }
+}
+
+function toHex(str) {
+ var hex = '';
+ for (var i = 0; i < str.length; i++) {
+ hex += '' + (str.charCodeAt(i) + 125).toString(16);
+ }
+ return hex;
+}
+
+function invertColor(hex) {
+ if (hex.indexOf('#') === 0) {
+ hex = hex.slice(1);
+ }
+ // convert 3-digit hex to 6-digits.
+ if (hex.length === 3) {
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
+ }
+ if (hex.length !== 6) {
+ throw new Error('Invalid HEX color.');
+ }
+ // invert color components
+ var r = (255 - parseInt(hex.slice(0, 2), 16)).toString(16),
+ g = (255 - parseInt(hex.slice(2, 4), 16)).toString(16),
+ b = (255 - parseInt(hex.slice(4, 6), 16)).toString(16);
+ // pad each with zeros and return
+ return padZero(r) + padZero(g) + padZero(b);
+}
+
+function padZero(str, len) {
+ len = len || 2;
+ var zeros = new Array(len).join('0');
+ return (zeros + str).slice(-len);
+}
+
+function fixedNav() {
+ if (document.body.className === "mainpage" || document.body.className === "threads") {
+ document.getElementById("main_nav").style.position = "fixed";
+ document.getElementById("main_nav").style.top = "0";
+ document.body.style.marginTop = "2em";
+ }
+}
+
+document.addEventListener('DOMContentLoaded', shobon, false); \ No newline at end of file
diff --git a/static/js/tegaki/tegaki.css b/static/js/tegaki/tegaki.css
new file mode 100644
index 0000000..d2e3591
--- /dev/null
+++ b/static/js/tegaki/tegaki.css
@@ -0,0 +1,187 @@
+@font-face {
+ font-family: 'tegaki';
+ src: url('data:application/octet-stream;base64,d09GRgABAAAAAAyIAA4AAAAAFVAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABRAAAAEQAAABWPeFIsGNtYXAAAAGIAAAAOgAAAUrQFxm3Y3Z0IAAAAcQAAAAKAAAACgAAAABmcGdtAAAB0AAABZQAAAtwiJCQWWdhc3AAAAdkAAAACAAAAAgAAAAQZ2x5ZgAAB2wAAAI+AAAC7u/G5z9oZWFkAAAJrAAAADYAAAA2BIBHAWhoZWEAAAnkAAAAHgAAACQHlwNRaG10eAAACgQAAAAWAAAAIBsOAABsb2NhAAAKHAAAABIAAAASA2cCrm1heHAAAAowAAAAIAAAACAAmwu2bmFtZQAAClAAAAF+AAACte3MYkJwb3N0AAAL0AAAAFAAAABnZ1gGo3ByZXAAAAwgAAAAZQAAAHvdawOFeJxjYGROYpzAwMrAwVTFtIeBgaEHQjM+YDBkZGJgYGJgZWbACgLSXFMYHF4wvGBjDvqfxRDFzM3gDxRmBMkBANw6Cw94nGNgYGBmgGAZBkYGEHAB8hjBfBYGDSDNBqQZGZgYGF6w/f8PUvCCAURLMELVAwEjG8OIBwBqdQa0AAAAAAAAAAAAAAAAAAB4nK1WaXMTRxCd1WHLNj6CDxI2gVnGcox2VpjLCBDG7EoW4BzylexCjl1Ldu6LT/wG/ZpekVSRb/y0vB4d2GAnVVQoSv2m9+1M9+ueXpPQksReWI+k3HwpprY2aWTnSUg3bFqO4kPZ2QspU0z+LoiCaLXUvu04JCISgap1hSWC2PfI0iTjQ48yWrYlvWpSbulJd9kaD+qt+vbT0FGO3QklNZuhQ+uRLanCqBJFMu2RkjYtw9VfSVrh5yvMfNUMJYLoJJLGm2EMj+Rn44xWGa3GdhxFkU2WG0WKRDM8iCKPslpin1wxQUD5oBlSXvk0onyEH5EVe5TTCnHJdprf9yU/6R3OvyTieouyJQf+QHZkB3unK/ki0toK46adbEehivB0fSfEI5uT6p/sUV7TaOB2RaYnzQiWyleQWPkJZfYPyWrhfMqXPBrVkoOcCFovc2Jf8g60HkdMiWsmyILujk6IoO6XnKHYY/q4+OO9XSwXIQTIOJb1jkq4EEYpYbOaJG0EOYiSskWV1HpHTJzyOi3iLWG/Tu3oS2e0Sag7MZ6th46tnKjkeDSp00ymTu2k5tGUBlFKOhM85tcBlB/RJK+2sZrEyqNpbDNjJJFQoIVzaSqIZSeWNAXRPJrRm7thmmvXokWaPFDPPXpPb26Fmzs9p+3AP2v8Z3UqpoO9MJ2eDshKfJp2uUnRun56hn8m8UPWAiqRLTbDlMVDtn4H5eVjS47CawNs957zK+h99kTIpIH4G/AeL9UpBUyFmFVQC9201rUsy9RqVotUZOq7IU0rX9ZpAk05Dn1jX8Y4/q+ZGUtMCd/vxOnZEZeeufYlyDSH3GZdj+Z1arFdgM5sz+k0y/Z9nebYfqDTPNvzOh1ha+t0lO2HOi2w/UinY2wvaEGT7jsEchGBXMAGEoGwdRAI20sIhK1CIGwXEQjbIgJhu4RA2H6MQNguIxC2l7Wsmn4qaRw7E8sARYgDoznuyGVuKldTyaUSrotGpzbkKXKrpKJ4Vv0rA/3ikTesgbVAukTW/IpJrnxUleOPrmh508S5Ao5Vf3tzXJ8TD2W/WPhT8L/amqqkV6x5ZHIVeSPQk+NE1yYVj67p8rmqR9f/i4oOa4F+A6UQC0VZlg2+mZDwUafTUA1c5RAzGzMP1/W6Zc3P4fybGCEL6H78NxQaC9yDTllJWe1gr9XXj2W5twflsCdYkmK+zOtb4YuMzEr7RWYpez7yecAVMCqVYasNXK3gzXsS85DpTfJMELcVZYOkjceZILGBYx4wb76TICRMXbWB2imcsIG8YMwp2O+EQ1RvlOVwe6F9Ho2Uf2tX7MgZFU0Q+G32Rtjrs1DyW6yBhCe/1NdAVSFNxbipgEsj5YZq8GFcrdtGMk6gr6jYDcuyig8fR9x3So5lIPlIEatHRz+tvUKd1Ln9yihu3zv9CIJBaWL+9r6Z4qCUd7WSZVZtA1O3GpVT15rDxasO3c2j7nvH2Sdy1jTddE/c9L6mVbeDg7lZEO3bHJSlTC6o68MOG6jLzaXQ6mVckt52DzAsMKDfoRUb/1f3cfg8V6oKo+NIvZ2oH6PPYgzyDzh/R/UF6OcxTLmGlOd7lxOfbtzD2TJdxV2sn+LfwKy15mbpGnBD0w2Yh6xaHbrKDXynBjo90tyO9BDwse4K8QBgE8Bi8InuWsbzKYDxfMYcH+Bz5jBoMofBFnMYbDNnDWCHOQx2mcNgjzkMvmDOOsCXzGEQModBxBwGT5gTADxlDoOvmMPga+Yw+IY59wG+ZQ6DmDkMEuYw2Nd0ayhzixd0F6htUBXowPQTFvewONRUGbK/44Vhf28Qs38wiKk/aro9pP7EC0P92SCm/mIQU3/VdGdI/Y0Xhvq7QUz9wyCmPtMvxnKZwV9GvkuFA8ouNp/z98T7B8IaQLYAAQAB//8AD3icZZI/bNNAFMbvnYOd3KW1kzhnqUQmdVo7FQWi/LGlMKDSUglRZesAylSKVCkMiB2UShUqE1LGSERCSlmYIFIr5q4MDFUpTN1IB8Rahjq8c9oy4OHzu3dPv+/u3iNAyOg3PaCvyAxRByIGN67Pmjqozi3QpLjVO+BJ8cvXIJAicNsS9EBfMeaNfh9lxZB/499a1/t9/ZmQwc6O/n+hflMWEOn9R0krnBTQeyqB3pA1Va+AohUcN6iheLWqH1RQbkNZWNlKWSjpvBjmRUvkYWjZgAvbamEwxMSezJ4IzGZPLrOynOAHUpQ0/CI6+iWVC7/pc5fpMfvsUUSl7y94Y1CeKNF5h/QFSRGHVAjbK3lXTZ0qyHE9gSjHrVUDVcNiH6qu5qhZ0wYf2ZWyf8XU1Fh+Bh8z8OchZgnl3Wrb6XztOO3VB8cQOw4/G3x53RDGUokb8J03wtPwR3ja4LwBcXAh3uBQ31qoL250OhuL9YWt59vbcB9L1+8lJ2malZaML5nMZre7mXHNdpf2XprRnUc/lV06R0y8M6N45wR214NxT60EjHuqfAjXmM3CNc6b3GZQhCLPJZsc3oSPOYe3mGtyHh5hGgty52+5S5cjri65szgwXgLGUxNIeMSVuPAoPIpwHHo8J6XVZAzmwm+MRXY9Jq1zeN7R2egjvUv3yRRyOUFuBvtipbDx47F0AxyFVEFGfhpeawxaOJKfuMMGkwlmtQZx9aHG6D6Lh3YxczgxcZgSJjxRn2riL3t/mWkAAAABAAAAAQAAO8vwqV8PPPUACwPoAAAAANC+FsgAAAAA0L3smP/9/7ED6AMLAAAACAACAAAAAAAAeJxjYGRgYA76n8UQxfyCgeH/NyAJFEEBHACQkgXuAAB4nGN+wcDALIiEXyAwkzUDAwBBEgQmAAAAAAAAAD4AdgCWAPABHAFIAXcAAAABAAAACAA0AAMAAAAAAAIAAAAQAHMAAAAcC3AAAAAAeJx1kM1Kw0AUhc/U/mArLiy4HjeiiOkPurBuxELrSsFFQVzI2E6T1DRTJlOhr+A7+BC+kM/iSTJIEcwwk++ee+7NnQA4wDcEyueSu2SBOqOSK2jg2vMO9VvPVfKd5xpauPdc53ry3MQZXjy30MYHO4jqLqMFPj0L7ImG5wr2RdvzDvUjz1XyuecaDsWV5zr1B89NTMSz5xaOxdfQrDY2DiMnT4anst/tXcjXjTSU4lQlUq1dZGwmb+TcpE4niQmmZul0qN7iRx2uE2XLoDwn2maxSWUv6JbCWKfaKqdnedfsPew7N5dza5Zy5PvJlTULPXVB5Nxq0OlsfwdDGKywgUWMEBEcJE6onvLdRxc9XJBe6ZB0lq4YKRQSKgprVkRFJmN8wz1nlFLVdCTkAFOey0IJWfHG+seC18wrVm5ntnlCzvvGRUfJWQJOtO0Yk9PCpQp99jtrhne6+lQdJ8qnssUUEqM/80neP88tqEypB8VfcFQH6HD9c58fnU58DwAAeJxjYGKAAC4G7ICDgYGRiZGZkYWRlZGNkZ2Rgy05MS85NYelIKe0mDU3M6+0mDm1MpUzJb88Tze/IDWPvbQATHPlpJal5uiCxBkYAP+wElx4nGPw3sFwIihiIyNjX+QGxp0cDBwMyQUbGVidNjIwaEFoDhR6JwMDAycyi5nBZaMKY0dgxAaHjoiNzCkuG9VAvF0cDQyMLA4dySERICWRQLCRgUdrB+P/1g0svRuZGFwAB9MiuAAAAA==') format('woff');
+ font-weight: normal;
+ font-style: normal;
+}
+
+.tegaki-icon:before {
+ font-size: 10px;
+ width: 10px;
+ font-family: 'tegaki';
+ font-style: normal;
+ font-weight: normal;
+ speak: none;
+ display: inline-block;
+ text-align: center;
+ font-variant: normal;
+ text-transform: none;
+ line-height: 1em;
+}
+
+.tegaki-cancel:before { content: '\e800'; } /* 'î €' */
+.tegaki-plus:before { content: '\e801'; } /* 'î ' */
+.tegaki-minus:before { content: '\e802'; } /* 'î ‚' */
+.tegaki-eye:before { content: '\e803'; } /* 'î ƒ' */
+.tegaki-down-open:before { content: '\e804'; } /* 'î „' */
+.tegaki-up-open:before { content: '\e805'; } /* 'î …' */
+.tegaki-level-down:before { content: '\e806'; } /* 'î †' */
+
+#tegaki {
+ position: fixed;
+ width: 100%;
+ height: 100%;
+ top: 0;
+ left: 0;
+ background-color: #a3b1bf;
+ color: #000;
+ font-family: arial, sans-serif;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ overflow: auto;
+ z-index: 9999;
+ image-rendering: optimizeSpeed;
+ image-rendering: -webkit-optimize-contrast;
+ image-rendering: pixelated;
+ image-rendering: -moz-crisp-edges;
+}
+
+#tegaki-debug {
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+
+#tegaki-debug canvas {
+ width: 75px;
+ height: 75px;
+ display: block;
+ border: 1px solid black;
+}
+
+.tegaki-backdrop {
+ overflow: hidden;
+}
+
+.tegaki-hidden {
+ display: none !important;
+}
+
+.tegaki-strike {
+ text-decoration: line-through;
+}
+
+#tegaki-cnt {
+ left: 50%;
+ top: 50%;
+ position: absolute;
+}
+
+#tegaki-cnt.tegaki-overflow-x {
+ left: 10px;
+ margin-left: 0 !important;
+}
+
+#tegaki-cnt.tegaki-overflow-y {
+ top: 10px;
+ margin-top: 0 !important;
+}
+
+.tegaki-tb-btn {
+ margin-left: 10px;
+ cursor: pointer;
+ text-decoration: none;
+}
+
+.tegaki-tb-btn:hover {
+ color: #007FFF;
+}
+
+.tegaki-tb-btn:focus {
+ color: #007FFF;
+ outline: none;
+}
+
+#tegaki-menu-bar {
+ font-size: 12px;
+ white-space: nowrap;
+ position: absolute;
+ right: 0;
+}
+
+#tegaki-canvas {
+ -moz-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.2);
+ background: #FFFAFA;
+}
+
+#tegaki-layers {
+ display: inline-block;
+ font-size: 0;
+}
+
+#tegaki-finish-btn {
+ font-weight: bold;
+}
+
+.tegaki-ctrlgrp {
+ margin-bottom: 5px;
+}
+
+.tegaki-label {
+ font-size: 10px;
+}
+
+.tegaki-label:after {
+ content: ' ' attr(data-value);
+}
+
+#tegaki-ghost-layer,
+.tegaki-layer {
+ position: absolute;
+ left: 0;
+}
+
+#tegaki-ctrl {
+ position: absolute;
+ display: inline-block;
+ width: 80px;
+ padding-left: 5px;
+ font-size: 14px;
+}
+
+#tegaki-color {
+ padding: 0;
+ border: 0;
+ display: block;
+ width: 25px;
+ height: 25px;
+ cursor: pointer;
+}
+
+#tegaki-layer-grp span {
+ font-size: 12px;
+ margin-right: 3px;
+ cursor: pointer;
+}
+
+#tegaki-layer-grp span:hover {
+ color: #007FFF;
+}
+
+#tegaki-color::-moz-focus-inner {
+ border: none;
+ padding: 0;
+}
+
+#tegaki-alpha,
+#tegaki-size {
+ width: 90%;
+ margin: auto;
+}
+
+#tegaki-ctrl select {
+ font-size: 11px;
+ width: 100%;
+}
diff --git a/static/js/tegaki/tegaki.js b/static/js/tegaki/tegaki.js
new file mode 100644
index 0000000..3d38d00
--- /dev/null
+++ b/static/js/tegaki/tegaki.js
@@ -0,0 +1,1947 @@
+var TegakiBrush = {
+ brushFn: function(x, y) {
+ var i, ctx, dest, data, len, kernel;
+
+ x = 0 | x;
+ y = 0 | y;
+
+ ctx = Tegaki.ghostCtx;
+ dest = ctx.getImageData(x, y, this.brushSize, this.brushSize);
+ data = dest.data;
+ kernel = this.kernel;
+ len = kernel.length;
+
+ i = 0;
+ while (i < len) {
+ data[i] = this.rgb[0]; ++i;
+ data[i] = this.rgb[1]; ++i;
+ data[i] = this.rgb[2]; ++i;
+ data[i] += kernel[i] * (1.0 - data[i] / 255); ++i;
+ }
+
+ ctx.putImageData(dest, x, y);
+ },
+
+ commit: function() {
+ Tegaki.activeCtx.drawImage(Tegaki.ghostCanvas, 0, 0);
+ Tegaki.ghostCtx.clearRect(0, 0,
+ Tegaki.ghostCanvas.width, Tegaki.ghostCanvas.height
+ );
+ },
+
+ draw: function(posX, posY, pt) {
+ var offset, mx, my, fromX, fromY, dx, dy, err, derr, step, stepAcc;
+
+ offset = this.center;
+ step = this.stepSize;
+ stepAcc = this.stepAcc;
+
+ if (pt === true) {
+ this.stepAcc = 0;
+ this.posX = posX;
+ this.posY = posY;
+ this.brushFn(posX - offset, posY - offset);
+ return;
+ }
+
+ fromX = this.posX;
+ fromY = this.posY;
+
+ if (fromX < posX) { dx = posX - fromX; mx = 1; }
+ else { dx = fromX - posX; mx = -1; }
+ if (fromY < posY) { dy = posY - fromY; my = 1; }
+ else { dy = fromY - posY; my = -1; }
+
+ err = (dx > dy ? dx : -dy) / 2;
+
+ dx = -dx;
+
+ while (true) {
+ ++stepAcc;
+ if (stepAcc > step) {
+ this.brushFn(fromX - offset, fromY - offset);
+ stepAcc = 0;
+ }
+ if (fromX === posX && fromY === posY) {
+ break;
+ }
+ derr = err;
+ if (derr > dx) { err -= dy; fromX += mx; }
+ if (derr < dy) { err -= dx; fromY += my; }
+ }
+
+ this.stepAcc = stepAcc;
+ this.posX = posX;
+ this.posY = posY;
+ },
+
+ generateBrush: function() {
+ var i, size, r, brush, ctx, dest, data, len, sqd, sqlen, hs, col, row,
+ ecol, erow, a;
+
+ size = this.size * 2;
+ r = size / 2;
+
+ brush = T$.el('canvas');
+ brush.width = brush.height = size;
+ ctx = brush.getContext('2d');
+ dest = ctx.getImageData(0, 0, size, size);
+ data = dest.data;
+ len = size * size * 4;
+ sqlen = Math.sqrt(r * r);
+ hs = Math.round(r);
+ col = row = -hs;
+
+ i = 0;
+ while (i < len) {
+ if (col >= hs) {
+ col = -hs;
+ ++row;
+ continue;
+ }
+
+ ecol = col;
+ erow = row;
+
+ if (ecol < 0) { ecol = -ecol; }
+ if (erow < 0) { erow = -erow; }
+
+ sqd = Math.sqrt(ecol * ecol + erow * erow);
+
+ if (sqd > sqlen) {
+ a = 0;
+ }
+ else {
+ a = sqd / sqlen;
+ a = (Math.exp(1 - 1 / a) / a);
+ a = 255 - ((0 | (a * 100 + 0.5)) / 100) * 255;
+ }
+
+ if (this.alphaDamp) {
+ a *= this.alpha * this.alphaDamp;
+ }
+ else {
+ a *= this.alpha;
+ }
+
+ data[i + 3] = a;
+
+ i += 4;
+
+ ++col;
+ }
+
+ ctx.putImageData(dest, 0, 0);
+
+ this.center = r;
+ this.brushSize = size;
+ this.brush = brush;
+ this.kernel = data;
+ },
+
+ setSize: function(size, noBrush) {
+ this.size = size;
+ if (!noBrush) this.generateBrush();
+ this.stepSize = Math.floor(this.size * this.step);
+ },
+
+ setAlpha: function(alpha, noBrush) {
+ this.alpha = alpha;
+ if (!noBrush) this.generateBrush();
+ },
+
+ setColor: function(color, noBrush) {
+ this.rgb = Tegaki.hexToRgb(color);
+ if (!noBrush) this.generateBrush();
+ },
+
+ set: function() {
+ this.setAlpha(this.alpha, true);
+ this.setSize(this.size, true);
+ this.setColor(Tegaki.toolColor, true);
+ this.generateBrush();
+ }
+};
+
+var TegakiPen = {
+ init: function() {
+ this.size = 4;
+ this.alpha = 0.5;
+ this.step = 0.1;
+ this.stepAcc = 0;
+ },
+
+ draw: TegakiBrush.draw,
+
+ commit: TegakiBrush.commit,
+
+ brushFn: TegakiBrush.brushFn,
+
+ generateBrush: function() {
+ var size, r, brush, ctx;
+
+ size = this.size;
+ r = size / 2;
+
+ brush = T$.el('canvas');
+ brush.width = brush.height = size;
+ ctx = brush.getContext('2d');
+ ctx.globalAlpha = this.alpha;
+ ctx.beginPath();
+ ctx.arc(r, r, r, 0, Tegaki.TWOPI, false);
+ ctx.fillStyle = '#000000';
+ ctx.fill();
+ ctx.closePath();
+
+ this.center = r;
+ this.brushSize = size;
+ this.brush = brush;
+ this.kernel = ctx.getImageData(0, 0, this.brushSize, this.brushSize).data;
+ },
+
+ setSize: TegakiBrush.setSize,
+
+ setAlpha: TegakiBrush.setAlpha,
+
+ setColor: TegakiBrush.setColor,
+
+ set: TegakiBrush.set
+};
+
+var TegakiPipette = {
+ size: 1,
+ alpha: 1,
+ noCursor: true,
+
+ draw: function(posX, posY) {
+ var c, ctx;
+
+ if (true) {
+ ctx = Tegaki.flatten().getContext('2d');
+ }
+ else {
+ ctx = Tegaki.activeCtx;
+ }
+
+ c = Tegaki.getColorAt(ctx, posX, posY);
+
+ Tegaki.setToolColor(c);
+ Tegaki.updateUI('color');
+ }
+};
+
+var TegakiAirbrush = {
+ init: function() {
+ this.size = 32;
+ this.alpha = 0.5;
+ this.alphaDamp = 0.2;
+ this.step = 0.25;
+ this.stepAcc = 0;
+ },
+
+ draw: TegakiBrush.draw,
+
+ commit: TegakiBrush.commit,
+
+ brushFn: TegakiBrush.brushFn,
+
+ generateBrush: TegakiBrush.generateBrush,
+
+ setSize: TegakiBrush.setSize,
+
+ setAlpha: TegakiBrush.setAlpha,
+
+ setColor: TegakiBrush.setColor,
+
+ set: TegakiBrush.set
+};
+
+var TegakiPencil = {
+ init: function() {
+ this.size = 1;
+ this.alpha = 1.0;
+ this.step = 0.25;
+ this.stepAcc = 0;
+ },
+
+ draw: TegakiBrush.draw,
+
+ commit: TegakiBrush.commit,
+
+ brushFn: function(x, y) {
+ var i, ctx, dest, data, len, kernel, a;
+
+ x = 0 | x;
+ y = 0 | y;
+
+ ctx = Tegaki.ghostCtx;
+ dest = ctx.getImageData(x, y, this.brushSize, this.brushSize);
+ data = dest.data;
+ kernel = this.kernel;
+ len = kernel.length;
+
+ a = this.alpha * 255;
+
+ i = 0;
+ while (i < len) {
+ data[i] = this.rgb[0]; ++i;
+ data[i] = this.rgb[1]; ++i;
+ data[i] = this.rgb[2]; ++i;
+ if (kernel[i] > 0) {
+ data[i] = a;
+ }
+ ++i;
+ }
+
+ ctx.putImageData(dest, x, y);
+ },
+
+ generateBrush: TegakiPen.generateBrush,
+
+ setSize: TegakiBrush.setSize,
+
+ setAlpha: TegakiBrush.setAlpha,
+
+ setColor: TegakiBrush.setColor,
+
+ set: TegakiBrush.set
+};
+
+var TegakiEraser = {
+ init: function() {
+ this.size = 8;
+ this.alpha = 1.0;
+ this.step = 0.25;
+ this.stepAcc = 0;
+ },
+
+ draw: TegakiBrush.draw,
+
+ brushFn: function(x, y) {
+ var i, ctx, dest, data, len, kernel;
+
+ x = 0 | x;
+ y = 0 | y;
+
+ ctx = Tegaki.activeCtx;
+ dest = ctx.getImageData(x, y, this.brushSize, this.brushSize);
+ data = dest.data;
+ kernel = this.kernel;
+ len = kernel.length;
+
+ for (i = 3; i < len; i += 4) {
+ if (kernel[i] > 0) {
+ data[i] = 0;
+ }
+ }
+
+ ctx.putImageData(dest, x, y);
+ },
+
+ generateBrush: TegakiPen.generateBrush,
+
+ setSize: TegakiBrush.setSize,
+
+ setAlpha: TegakiBrush.setAlpha,
+
+ setColor: TegakiBrush.setColor,
+
+ set: TegakiBrush.set
+};
+
+var TegakiDodge = {
+ init: function() {
+ this.size = 24;
+ this.alpha = 0.25;
+ this.alphaDamp = 0.05;
+ this.step = 0.25;
+ this.stepAcc = 0;
+ },
+
+ brushFn: function(x, y) {
+ var i, a, aa, ctx, dest, data, len, kernel;
+
+ x = 0 | x;
+ y = 0 | y;
+
+ ctx = Tegaki.activeCtx;
+ dest = ctx.getImageData(x, y, this.brushSize, this.brushSize);
+ data = dest.data;
+ kernel = this.kernel;
+ len = kernel.length;
+
+ i = 0;
+ while (i < len) {
+ aa = kernel[i + 3] * 0.3;
+ a = 1 + kernel[i + 3] / 255;
+ data[i] = data[i] * a + aa; ++i;
+ data[i] = data[i] * a + aa; ++i;
+ data[i] = data[i] * a + aa; ++i;
+ ++i;
+ }
+
+ ctx.putImageData(dest, x, y);
+ },
+
+ draw: TegakiBrush.draw,
+
+ generateBrush: TegakiBrush.generateBrush,
+
+ setSize: TegakiBrush.setSize,
+
+ setAlpha: TegakiBrush.setAlpha,
+
+ setColor: TegakiBrush.setColor,
+
+ set: TegakiBrush.set
+};
+
+var TegakiBurn = {
+ init: TegakiDodge.init,
+
+ brushFn: function(x, y) {
+ var i, a, ctx, dest, data, len, kernel;
+
+ x = 0 | x;
+ y = 0 | y;
+
+ ctx = Tegaki.activeCtx;
+ dest = ctx.getImageData(x, y, this.brushSize, this.brushSize);
+ data = dest.data;
+ kernel = this.kernel;
+ len = kernel.length;
+
+ i = 0;
+ while (i < len) {
+ a = 1 - kernel[i + 3] / 255;
+ data[i] = data[i] * a; ++i;
+ data[i] = data[i] * a; ++i;
+ data[i] = data[i] * a; ++i;
+ ++i;
+ }
+
+ ctx.putImageData(dest, x, y);
+ },
+
+ draw: TegakiBrush.draw,
+
+ generateBrush: TegakiDodge.generateBrush,
+
+ setSize: TegakiBrush.setSize,
+
+ setAlpha: TegakiBrush.setAlpha,
+
+ setColor: TegakiBrush.setColor,
+
+ set: TegakiBrush.set
+};
+
+var TegakiBlur = {
+ init: TegakiDodge.init,
+
+ brushFn: function(x, y) {
+ var i, j, ctx, src, size, srcData, dest, destData, lim, kernel,
+ sx, sy, r, g, b, a, aa, acc, kx, ky;
+
+ x = 0 | x;
+ y = 0 | y;
+
+ size = this.brushSize;
+ ctx = Tegaki.activeCtx;
+ src = ctx.getImageData(x, y, size, size);
+ srcData = src.data;
+ dest = ctx.createImageData(size, size);
+ destData = dest.data;
+ kernel = this.kernel;
+ lim = size - 1;
+
+ for (sx = 0; sx < size; ++sx) {
+ for (sy = 0; sy < size; ++sy) {
+ r = g = b = a = acc = 0;
+ i = (sy * size + sx) * 4;
+ if (kernel[(sy * size + sx) * 4 + 3] === 0
+ || sx === 0 || sy === 0 || sx === lim || sy === lim) {
+ destData[i] = srcData[i]; ++i;
+ destData[i] = srcData[i]; ++i;
+ destData[i] = srcData[i]; ++i;
+ destData[i] = srcData[i];
+ continue;
+ }
+ for (kx = -1; kx < 2; ++kx) {
+ for (ky = -1; ky < 2; ++ky) {
+ j = ((sy - ky) * size + (sx - kx)) * 4;
+ aa = srcData[j + 3];
+ acc += aa;
+ r += srcData[j] * aa; ++j;
+ g += srcData[j] * aa; ++j;
+ b += srcData[j] * aa; ++j;
+ a += srcData[j];
+ }
+ }
+ destData[i] = r / acc; ++i;
+ destData[i] = g / acc; ++i;
+ destData[i] = b / acc; ++i;
+ destData[i] = a / 9;
+ }
+ }
+
+ ctx.putImageData(dest, x, y);
+ },
+
+ draw: TegakiBrush.draw,
+
+ generateBrush: TegakiDodge.generateBrush,
+
+ setSize: TegakiBrush.setSize,
+
+ setAlpha: TegakiBrush.setAlpha,
+
+ setColor: TegakiBrush.setColor,
+
+ set: TegakiBrush.set
+};
+
+var TegakiHistory = {
+ maxSize: 10,
+
+ undoStack: [],
+ redoStack: [],
+
+ pendingAction: null,
+
+ clear: function() {
+ this.undoStack = [];
+ this.redoStack = [];
+ this.pendingAction = null;
+ },
+
+ push: function(action) {
+ this.undoStack.push(action);
+
+ if (this.undoStack.length > this.maxSize) {
+ this.undoStack.shift();
+ }
+
+ if (this.redoStack.length > 0) {
+ this.redoStack = [];
+ }
+ },
+
+ undo: function() {
+ var action;
+
+ if (!this.undoStack.length) {
+ return;
+ }
+
+ action = this.undoStack.pop();
+ action.undo();
+
+ this.redoStack.push(action);
+ },
+
+ redo: function() {
+ var action;
+
+ if (!this.redoStack.length) {
+ return;
+ }
+
+ action = this.redoStack.pop();
+ action.redo();
+
+ this.undoStack.push(action);
+ }
+};
+
+var TegakiHistoryActions = {
+ Draw: function(layerId) {
+ this.canvasBefore = null;
+ this.canvasAfter = null;
+ this.layerId = layerId;
+ },
+
+ DestroyLayers: function(indices, layers) {
+ this.indices = indices;
+ this.layers = layers;
+ this.canvasBefore = null;
+ this.canvasAfter = null;
+ this.layerId = null;
+ },
+
+ AddLayer: function(layerId) {
+ this.layerId = layerId;
+ },
+
+ MoveLayer: function(layerId, up) {
+ this.layerId = layerId;
+ this.up = up;
+ }
+};
+
+TegakiHistoryActions.Draw.prototype.addCanvasState = function(canvas, type) {
+ if (type) {
+ this.canvasAfter = T$.copyCanvas(canvas);
+ }
+ else {
+ this.canvasBefore = T$.copyCanvas(canvas);
+ }
+};
+
+TegakiHistoryActions.Draw.prototype.exec = function(type) {
+ var i, layer;
+
+ for (i in Tegaki.layers) {
+ layer = Tegaki.layers[i];
+
+ if (layer.id === this.layerId) {
+ layer.ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height);
+ layer.ctx.drawImage(type ? this.canvasAfter: this.canvasBefore, 0, 0);
+ }
+ }
+};
+
+TegakiHistoryActions.Draw.prototype.undo = function() {
+ this.exec(0);
+};
+
+TegakiHistoryActions.Draw.prototype.redo = function() {
+ this.exec(1);
+};
+
+TegakiHistoryActions.DestroyLayers.prototype.undo = function() {
+ var i, ii, len, layers, idx, layer, frag;
+
+ layers = new Array(len);
+
+ for (i = 0; (idx = this.indices[i]) !== undefined; ++i) {
+ layers[idx] = this.layers[i];
+ }
+
+ i = ii = 0;
+ len = Tegaki.layers.length + this.layers.length;
+ frag = T$.frag();
+
+ while (i < len) {
+ if (!layers[i]) {
+ layer = layers[i] = Tegaki.layers[ii];
+ Tegaki.layersCnt.removeChild(layer.canvas);
+ ++ii;
+ }
+
+ if (this.layerId && layer.id === this.layerId) {
+ layer.ctx.clearRect(0, 0, layer.canvas.width, layer.canvas.height);
+ layer.ctx.drawImage(this.canvasBefore, 0, 0);
+ }
+
+ frag.appendChild(layers[i].canvas);
+
+ ++i;
+ }
+
+ Tegaki.layersCnt.insertBefore(frag, Tegaki.canvas.nextElementSibling);
+
+ Tegaki.layers = layers;
+
+ Tegaki.setActiveLayer();
+
+ Tegaki.rebuildLayerCtrl();
+};
+
+TegakiHistoryActions.DestroyLayers.prototype.redo = function() {
+ var i, layer, ids = [];
+
+ for (i = 0; layer = this.layers[i]; ++i) {
+ ids.push(layer.id);
+ }
+
+ if (this.layerId) {
+ ids.push(this.layerId);
+ Tegaki.mergeLayers(ids);
+ }
+ else {
+ Tegaki.deleteLayers(ids);
+ }
+};
+
+TegakiHistoryActions.MoveLayer.prototype.undo = function() {
+ Tegaki.setActiveLayer(this.layerId);
+ Tegaki.moveLayer(this.layerId, !this.up);
+};
+
+TegakiHistoryActions.MoveLayer.prototype.redo = function() {
+ Tegaki.setActiveLayer(this.layerId);
+ Tegaki.moveLayer(this.layerId, this.up);
+};
+
+TegakiHistoryActions.AddLayer.prototype.undo = function() {
+ Tegaki.deleteLayers([this.layerId]);
+ Tegaki.layerIndex--;
+};
+
+TegakiHistoryActions.AddLayer.prototype.redo = function() {
+ Tegaki.addLayer();
+ Tegaki.setActiveLayer();
+};
+
+var T$ = {
+ docEl: document.documentElement,
+
+ id: function(id) {
+ return document.getElementById(id);
+ },
+
+ cls: function(klass, root) {
+ return (root || document).getElementsByClassName(klass);
+ },
+
+ on: function(o, e, h) {
+ o.addEventListener(e, h, false);
+ },
+
+ off: function(o, e, h) {
+ o.removeEventListener(e, h, false);
+ },
+
+ el: function(name) {
+ return document.createElement(name);
+ },
+
+ frag: function() {
+ return document.createDocumentFragment();
+ },
+
+ extend: function(destination, source) {
+ for (var key in source) {
+ destination[key] = source[key];
+ }
+ },
+
+ selectedOptions: function(el) {
+ var i, opt, sel;
+
+ if (el.selectedOptions) {
+ return el.selectedOptions;
+ }
+
+ sel = [];
+
+ for (i = 0; opt = el.options[i]; ++i) {
+ if (opt.selected) {
+ sel.push(opt);
+ }
+ }
+
+ return sel;
+ },
+
+ copyCanvas: function(source) {
+ var canvas = T$.el('canvas');
+ canvas.width = source.width;
+ canvas.height = source.height;
+ canvas.getContext('2d').drawImage(source, 0, 0);
+
+ return canvas;
+ }
+};
+
+var TegakiStrings = {
+ // Messages
+ badDimensions: 'Invalid dimensions.',
+ promptWidth: 'Canvas width in pixels',
+ promptHeight: 'Canvas height in pixels',
+ confirmDelLayers: 'Delete selected layers?',
+ errorMergeOneLayer: 'You need to select at least 2 layers.',
+ confirmMergeLayers: 'Merge selected layers?',
+ errorLoadImage: 'Could not load the image.',
+ noActiveLayer: 'No active layer.',
+ hiddenActiveLayer: 'The active layer is not visible.',
+ confirmCancel: 'Are you sure? Your work will be lost.',
+ confirmChangeCanvas: 'Changing the canvas will clear all layers and history.',
+
+ // UI
+ color: 'Color',
+ size: 'Size',
+ alpha: 'Opacity',
+ layers: 'Layers',
+ addLayer: 'Add layer',
+ delLayers: 'Delete layers',
+ mergeLayers: 'Merge layers',
+ showHideLayer: 'Toggle visibility',
+ moveLayerUp: 'Move up',
+ moveLayerDown: 'Move down',
+ tool: 'Tool',
+ changeCanvas: 'Change canvas',
+ blank: 'Blank',
+ newCanvas: 'New',
+ undo: 'Undo',
+ redo: 'Redo',
+ close: 'Close',
+ finish: 'Finish',
+
+ // Tools
+ pen: 'Pen',
+ pencil: 'Pencil',
+ airbrush: 'Airbrush',
+ pipette: 'Pipette',
+ dodge: 'Dodge',
+ burn: 'Burn',
+ blur: 'Blur',
+ eraser: 'Eraser'
+};
+
+var Tegaki = {
+ VERSION: '0.0.1',
+
+ bg: null,
+ cnt: null,
+ canvas: null,
+ ctx: null,
+ layers: [],
+ layersCnt: null,
+ ghostCanvas: null,
+ ghostCtx: null,
+ activeCtx: null,
+ activeLayer: null,
+ layerIndex: null,
+
+ isPainting: false,
+ isErasing: false,
+ isColorPicking: false,
+
+ offsetX: 0,
+ offsetY: 0,
+
+ TWOPI: 2 * Math.PI,
+
+ tools: {
+ pencil: TegakiPencil,
+ pen: TegakiPen,
+ airbrush: TegakiAirbrush,
+ pipette: TegakiPipette,
+ dodge: TegakiDodge,
+ burn: TegakiBurn,
+ blur: TegakiBlur,
+ eraser: TegakiEraser
+ },
+
+ tool: null,
+ toolColor: '#000000',
+
+ bgColor: '#ffffff',
+ maxSize: 32,
+ maxLayers: 25,
+ baseWidth: null,
+ baseHeight: null,
+
+ onDoneCb: null,
+ onCancelCb: null,
+
+ open: function(opts) {
+ var bg, cnt, el, el2, tool, lbl, btn, ctrl, canvas, grp, self = Tegaki;
+
+ if (self.bg) {
+ self.resume();
+ return;
+ }
+
+ if (opts.bgColor) {
+ self.bgColor = opts.bgColor;
+ }
+
+ self.onDoneCb = opts.onDone;
+ self.onCancelCb = opts.onCancel;
+
+ cnt = T$.el('div');
+ cnt.id = 'tegaki-cnt';
+
+ canvas = T$.el('canvas');
+ canvas.id = 'tegaki-canvas';
+ canvas.width = self.baseWidth = opts.width;
+ canvas.height = self.baseHeight = opts.height;
+
+ el = T$.el('div');
+ el.id = 'tegaki-layers';
+ el.appendChild(canvas);
+ self.layersCnt = el;
+
+ cnt.appendChild(el);
+
+ ctrl = T$.el('div');
+ ctrl.id = 'tegaki-ctrl';
+
+ // Colorpicker
+ grp = T$.el('div');
+ grp.className = 'tegaki-ctrlgrp';
+ el = T$.el('input');
+ el.id = 'tegaki-color';
+ el.value = self.toolColor;
+ try {
+ el.type = 'color';
+ } catch(e) {
+ el.type = 'text';
+ }
+ lbl = T$.el('div');
+ lbl.className = 'tegaki-label';
+ lbl.textContent = TegakiStrings.color;
+ grp.appendChild(lbl);
+ T$.on(el, 'change', self.onColorChange);
+ grp.appendChild(el);
+ ctrl.appendChild(grp);
+
+ // Size control
+ grp = T$.el('div');
+ grp.className = 'tegaki-ctrlgrp';
+ el = T$.el('input');
+ el.id = 'tegaki-size';
+ el.min = 1;
+ el.max = self.maxSize;
+ el.type = 'range';
+ lbl = T$.el('div');
+ lbl.className = 'tegaki-label';
+ lbl.textContent = TegakiStrings.size;
+ grp.appendChild(lbl);
+ T$.on(el, 'change', self.onSizeChange);
+ grp.appendChild(el);
+ ctrl.appendChild(grp);
+
+ // Alpha control
+ grp = T$.el('div');
+ grp.className = 'tegaki-ctrlgrp';
+ el = T$.el('input');
+ el.id = 'tegaki-alpha';
+ el.min = 0;
+ el.max = 1;
+ el.step = 0.01;
+ el.type = 'range';
+ lbl = T$.el('div');
+ lbl.className = 'tegaki-label';
+ lbl.textContent = TegakiStrings.alpha;
+ grp.appendChild(lbl);
+ T$.on(el, 'change', self.onAlphaChange);
+ grp.appendChild(el);
+ ctrl.appendChild(grp);
+
+ // Layer control
+ grp = T$.el('div');
+ grp.className = 'tegaki-ctrlgrp';
+ grp.id = 'tegaki-layer-grp';
+ el = T$.el('select');
+ el.id = 'tegaki-layer';
+ el.multiple = true;
+ el.size = 3;
+ lbl = T$.el('div');
+ lbl.className = 'tegaki-label';
+ lbl.textContent = TegakiStrings.layers;
+ grp.appendChild(lbl);
+ T$.on(el, 'change', self.onLayerChange);
+ grp.appendChild(el);
+ el = T$.el('span');
+ el.title = TegakiStrings.addLayer;
+ el.className = 'tegaki-icon tegaki-plus';
+ T$.on(el, 'click', self.onLayerAdd);
+ grp.appendChild(el);
+ el = T$.el('span');
+ el.title = TegakiStrings.delLayers;
+ el.className = 'tegaki-icon tegaki-minus';
+ T$.on(el, 'click', self.onLayerDelete);
+ grp.appendChild(el);
+ el = T$.el('span');
+ el.id = 'tegaki-layer-visibility';
+ el.title = TegakiStrings.showHideLayer;
+ el.className = 'tegaki-icon tegaki-eye';
+ T$.on(el, 'click', self.onLayerVisibilityChange);
+ grp.appendChild(el);
+ el = T$.el('span');
+ el.id = 'tegaki-layer-merge';
+ el.title = TegakiStrings.mergeLayers;
+ el.className = 'tegaki-icon tegaki-level-down';
+ T$.on(el, 'click', self.onMergeLayers);
+ grp.appendChild(el);
+ el = T$.el('span');
+ el.id = 'tegaki-layer-up';
+ el.title = TegakiStrings.moveLayerUp;
+ el.setAttribute('data-up', '1');
+ el.className = 'tegaki-icon tegaki-up-open';
+ T$.on(el, 'click', self.onMoveLayer);
+ grp.appendChild(el);
+ el = T$.el('span');
+ el.id = 'tegaki-layer-down';
+ el.title = TegakiStrings.moveLayerDown;
+ el.className = 'tegaki-icon tegaki-down-open';
+ T$.on(el, 'click', self.onMoveLayer);
+ grp.appendChild(el);
+ ctrl.appendChild(grp);
+
+ // Tool selector
+ grp = T$.el('div');
+ grp.className = 'tegaki-ctrlgrp';
+ el = T$.el('select');
+ el.id = 'tegaki-tool';
+ for (tool in Tegaki.tools) {
+ el2 = T$.el('option');
+ el2.value = tool;
+ el2.textContent = TegakiStrings[tool];
+ el.appendChild(el2);
+ }
+ lbl = T$.el('div');
+ lbl.className = 'tegaki-label';
+ lbl.textContent = TegakiStrings.tool;
+ grp.appendChild(lbl);
+ T$.on(el, 'change', self.onToolChange);
+ grp.appendChild(el);
+ ctrl.appendChild(grp);
+
+ cnt.appendChild(ctrl);
+
+ el = T$.el('div');
+ el.id = 'tegaki-menu-bar';
+
+ if (opts.canvasOptions) {
+ btn = T$.el('select');
+ btn.id = 'tegaki-canvas-select';
+ btn.title = TegakiStrings.changeCanvas;
+ btn.innerHTML = '<option value="0">' + TegakiStrings.blank + '</option>';
+ opts.canvasOptions(btn);
+ T$.on(btn, 'change', Tegaki.onCanvasSelected);
+ T$.on(btn, 'focus', Tegaki.onCanvasSelectFocused);
+ el.appendChild(btn);
+ }
+
+ btn = T$.el('span');
+ btn.className = 'tegaki-tb-btn';
+ btn.textContent = TegakiStrings.newCanvas;
+ T$.on(btn, 'click', Tegaki.onNewClick);
+ el.appendChild(btn);
+
+ btn = T$.el('span');
+ btn.className = 'tegaki-tb-btn';
+ btn.textContent = TegakiStrings.undo;
+ T$.on(btn, 'click', Tegaki.onUndoClick);
+ el.appendChild(btn);
+
+ btn = T$.el('span');
+ btn.className = 'tegaki-tb-btn';
+ btn.textContent = TegakiStrings.redo;
+ T$.on(btn, 'click', Tegaki.onRedoClick);
+ el.appendChild(btn);
+
+ btn = T$.el('span');
+ btn.className = 'tegaki-tb-btn';
+ btn.textContent = TegakiStrings.close;
+ T$.on(btn, 'click', Tegaki.onCancelClick);
+ el.appendChild(btn);
+
+ btn = T$.el('span');
+ btn.id = 'tegaki-finish-btn';
+ btn.className = 'tegaki-tb-btn';
+ btn.textContent = TegakiStrings.finish;
+ T$.on(btn, 'click', Tegaki.onDoneClick);
+ el.appendChild(btn);
+
+ cnt.appendChild(el);
+
+ bg = T$.el('div');
+ bg.id = 'tegaki';
+ self.bg = bg;
+ bg.appendChild(cnt);
+ document.body.appendChild(bg);
+ document.body.classList.add('tegaki-backdrop');
+
+ el = T$.el('canvas');
+ el.id = 'tegaki-ghost-layer';
+ el.width = canvas.width;
+ el.height = canvas.height;
+ self.ghostCanvas = el;
+ self.ghostCtx = el.getContext('2d');
+
+ self.cnt = cnt;
+ self.centerCnt();
+
+ self.canvas = canvas;
+
+ self.ctx = canvas.getContext('2d');
+ self.ctx.fillStyle = self.bgColor;
+ self.ctx.fillRect(0, 0, opts.width, opts.height);
+
+ self.addLayer();
+
+ self.setActiveLayer();
+
+ self.initTools();
+
+ self.setTool('pencil');
+
+ self.updateUI();
+
+ self.updateCursor();
+ self.updatePosOffset();
+
+ T$.on(self.bg, 'mousemove', self.onMouseMove);
+ T$.on(self.bg, 'mousedown', self.onMouseDown);
+ T$.on(self.layersCnt, 'contextmenu', self.onDummy);
+
+ T$.on(document, 'mouseup', self.onMouseUp);
+ T$.on(window, 'resize', self.updatePosOffset);
+ T$.on(window, 'scroll', self.updatePosOffset);
+ },
+
+ initTools: function() {
+ var tool;
+
+ for (tool in Tegaki.tools) {
+ (tool = Tegaki.tools[tool]) && tool.init && tool.init();
+ }
+ },
+
+ hexToRgb: function(hex) {
+ var c = hex.match(/^#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/i);
+
+ if (c) {
+ return [
+ parseInt(c[1], 16),
+ parseInt(c[2], 16),
+ parseInt(c[3], 16)
+ ];
+ }
+
+ return null;
+ },
+
+ centerCnt: function() {
+ var aabb, cnt;
+
+ cnt = Tegaki.cnt;
+ aabb = cnt.getBoundingClientRect();
+
+ if (aabb.width > T$.docEl.clientWidth || aabb.height > T$.docEl.clientHeight) {
+ if (aabb.width > T$.docEl.clientWidth) {
+ cnt.classList.add('tegaki-overflow-x');
+ }
+ if (aabb.height > T$.docEl.clientHeight) {
+ cnt.classList.add('tegaki-overflow-y');
+ }
+ }
+ else {
+ cnt.classList.remove('tegaki-overflow-x');
+ cnt.classList.remove('tegaki-overflow-y');
+ }
+
+ cnt.style.marginTop = -Math.round(aabb.height / 2) + 'px';
+ cnt.style.marginLeft = -Math.round(aabb.width / 2) + 'px';
+ },
+
+ getCursorPos: function(e, axis) {
+ if (axis === 0) {
+ return e.clientX + window.pageXOffset + Tegaki.bg.scrollLeft - Tegaki.offsetX;
+ }
+ else {
+ return e.clientY + window.pageYOffset + Tegaki.bg.scrollTop - Tegaki.offsetY;
+ }
+ },
+
+ resume: function() {
+ Tegaki.bg.classList.remove('tegaki-hidden');
+ document.body.classList.add('tegaki-backdrop');
+
+ Tegaki.centerCnt();
+ Tegaki.updatePosOffset();
+
+ T$.on(document, 'mouseup', Tegaki.onMouseUp);
+ T$.on(window, 'resize', Tegaki.updatePosOffset);
+ T$.on(window, 'scroll', Tegaki.updatePosOffset);
+ },
+
+ hide: function() {
+ Tegaki.bg.classList.add('tegaki-hidden');
+ document.body.classList.remove('tegaki-backdrop');
+
+ T$.off(document, 'mouseup', Tegaki.onMouseUp);
+ T$.off(window, 'resize', Tegaki.updatePosOffset);
+ T$.off(window, 'scroll', Tegaki.updatePosOffset);
+ },
+
+ destroy: function() {
+ T$.off(Tegaki.bg, 'mousemove', Tegaki.onMouseMove);
+ T$.off(Tegaki.bg, 'mousedown', Tegaki.onMouseDown);
+ T$.off(Tegaki.layersCnt, 'contextmenu', Tegaki.onDummy);
+
+ T$.off(document, 'mouseup', Tegaki.onMouseUp);
+ T$.off(window, 'resize', Tegaki.updatePosOffset);
+ T$.off(window, 'scroll', Tegaki.updatePosOffset);
+
+ Tegaki.bg.parentNode.removeChild(Tegaki.bg);
+
+ TegakiHistory.clear();
+
+ document.body.classList.remove('tegaki-backdrop');
+
+ Tegaki.bg = null;
+ Tegaki.cnt = null;
+ Tegaki.canvas = null;
+ Tegaki.ctx = null;
+ Tegaki.layers = [];
+ Tegaki.layerIndex = 0;
+ Tegaki.activeCtx = null;
+ },
+
+ flatten: function() {
+ var i, layer, canvas, ctx;
+
+ canvas = T$.el('canvas');
+ canvas.width = Tegaki.canvas.width;
+ canvas.height = Tegaki.canvas.height;
+
+ ctx = canvas.getContext('2d');
+
+ ctx.drawImage(Tegaki.canvas, 0, 0);
+
+ for (i = 0; layer = Tegaki.layers[i]; ++i) {
+ if (layer.canvas.classList.contains('tegaki-hidden')) {
+ continue;
+ }
+ ctx.drawImage(layer.canvas, 0, 0);
+ }
+
+ return canvas;
+ },
+
+ updateUI: function(type) {
+ var i, ary, el, tool = Tegaki.tool;
+
+ ary = type ? [type] : ['size', 'alpha', 'color'];
+
+ for (i = 0; type = ary[i]; ++i) {
+ el = T$.id('tegaki-' + type);
+ el.value = type === 'color' ? Tegaki.toolColor : tool[type];
+
+ if (el.type === 'range') {
+ el.previousElementSibling.setAttribute('data-value', tool[type]);
+ }
+ }
+ },
+
+ rebuildLayerCtrl: function() {
+ var i, layer, sel, opt;
+
+ sel = T$.id('tegaki-layer');
+
+ sel.textContent = '';
+
+ for (i = Tegaki.layers.length - 1; layer = Tegaki.layers[i]; i--) {
+ opt = T$.el('option');
+ opt.value = layer.id;
+ opt.textContent = layer.name;
+ sel.appendChild(opt);
+ }
+ },
+
+ getColorAt: function(ctx, posX, posY) {
+ var rgba = ctx.getImageData(posX, posY, 1, 1).data;
+
+ return '#'
+ + ('0' + rgba[0].toString(16)).slice(-2)
+ + ('0' + rgba[1].toString(16)).slice(-2)
+ + ('0' + rgba[2].toString(16)).slice(-2);
+ },
+
+ renderCircle: function(r) {
+ var i, canvas, ctx, d, e, x, y, dx, dy, idata, data, c, color;
+
+ e = 1 - r;
+ dx = 0;
+ dy = -2 * r;
+ x = 0;
+ y = r;
+ d = 33;
+ c = 16;
+
+ canvas = T$.el('canvas');
+ canvas.width = canvas.height = d;
+ ctx = canvas.getContext('2d');
+ idata = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
+ data = idata.data;
+
+ color = 255;
+
+ data[(c + (c + r) * d) * 4 + 3] = color;
+ data[(c + (c - r) * d) * 4 + 3] = color;
+ data[(c + r + c * d) * 4 + 3] = color;
+ data[(c - r + c * d) * 4 + 3] = color;
+
+ while (x < y) {
+ if (e >= 0) {
+ y--;
+ dy += 2;
+ e += dy;
+ }
+
+ ++x;
+ dx += 2;
+ e += dx;
+
+ data[(c + x + (c + y) * d) * 4 + 3] = color;
+ data[(c - x + (c + y) * d) * 4 + 3] = color;
+ data[(c + x + (c - y) * d) * 4 + 3] = color;
+ data[(c - x + (c - y) * d) * 4 + 3] = color;
+ data[(c + y + (c + x) * d) * 4 + 3] = color;
+ data[(c - y + (c + x) * d) * 4 + 3] = color;
+ data[(c + y + (c - x) * d) * 4 + 3] = color;
+ data[(c - y + (c - x) * d) * 4 + 3] = color;
+ }
+
+ if (r > 0) {
+ for (i = 0; i < 3; ++i) {
+ data[(c + c * d) * 4 + i] = 127;
+ }
+ data[(c + c * d) * 4 + i] = color;
+ }
+
+ ctx.putImageData(idata, 0, 0);
+
+ return canvas;
+ },
+
+ setToolSize: function(size) {
+ Tegaki.tool.setSize && Tegaki.tool.setSize(size);
+ Tegaki.updateCursor();
+ },
+
+ setToolAlpha: function(alpha) {
+ Tegaki.tool.setAlpha && Tegaki.tool.setAlpha(alpha);
+ },
+
+ setToolColor: function(color) {
+ Tegaki.toolColor = color;
+ Tegaki.tool.setColor && Tegaki.tool.setColor(color);
+ Tegaki.updateCursor();
+ },
+
+ setTool: function(tool) {
+ tool = Tegaki.tools[tool];
+ Tegaki.tool = tool;
+ tool.set && tool.set();
+ },
+
+ debugDumpPixelData: function(canvas) {
+ var i, idata, data, len, out, el;
+
+ idata = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);
+ data = idata.data;
+ len = data.length;
+
+ out = '';
+
+ for (i = 0; i < len; i += 4) {
+ out += data[i] + ' ' + data[i+1] + ' ' + data[i+2] + ' ' + data[i+3] + '%0a';
+ }
+
+ el = document.createElement('a');
+ el.href = 'data:,' + out;
+ el.download = 'dump.txt';
+ document.body.appendChild(el);
+ el.click();
+ document.body.removeChild(el);
+ },
+
+ debugDrawColors: function(sat) {
+ var i, ctx, grad, a;
+
+ Tegaki.resizeCanvas(360, 360);
+
+ ctx = Tegaki.activeCtx;
+ a = ctx.globalAlpha;
+ ctx.globalAlpha = 1;
+
+ ctx.fillStyle = '#000000';
+ ctx.fillRect(0, 0, 360, 360);
+
+ for (i = 0; i < 360; ++i) {
+ if (sat) {
+ grad = ctx.createLinearGradient(0, 0, 10, 360);
+ grad.addColorStop(0, 'hsl(' + i + ', 0%, ' + '50%)');
+ grad.addColorStop(1, 'hsl(' + i + ', 100%, ' + '50%)');
+ ctx.strokeStyle = grad;
+ }
+ else {
+ ctx.strokeStyle = 'hsl(' + i + ', 100%, ' + '50%)';
+ }
+ ctx.beginPath();
+ ctx.moveTo(i, 0);
+ ctx.lineTo(i, 360);
+ ctx.stroke();
+ ctx.closePath();
+ }
+
+ if (!sat) {
+ grad = ctx.createLinearGradient(0, 0, 10, 360);
+ grad.addColorStop(0, '#000000');
+ grad.addColorStop(1, 'rgba(0,0,0,0)');
+ ctx.fillStyle = grad;
+ ctx.fillRect(0, 0, 360, 360);
+ }
+
+ ctx.globalAlpha = a;
+ },
+
+ onNewClick: function() {
+ var width, height, tmp;
+
+ width = prompt(TegakiStrings.promptWidth, Tegaki.canvas.width);
+ if (!width) { return; }
+
+ height = prompt(TegakiStrings.promptHeight, Tegaki.canvas.height);
+ if (!height) { return; }
+
+ width = +width;
+ height = +height;
+
+ if (width < 1 || height < 1) {
+ alert(TegakiStrings.badDimensions);
+ return;
+ }
+
+ tmp = {};
+ Tegaki.copyContextState(Tegaki.activeCtx, tmp);
+ Tegaki.resizeCanvas(width, height);
+ Tegaki.copyContextState(tmp, Tegaki.activeCtx);
+
+ TegakiHistory.clear();
+ Tegaki.centerCnt();
+ Tegaki.updatePosOffset();
+ },
+
+ onUndoClick: function() {
+ TegakiHistory.undo();
+ },
+
+ onRedoClick: function() {
+ TegakiHistory.redo();
+ },
+
+ onDoneClick: function() {
+ Tegaki.hide();
+ Tegaki.onDoneCb();
+ },
+
+ onCancelClick: function() {
+ if (!confirm(TegakiStrings.confirmCancel)) {
+ return;
+ }
+
+ Tegaki.destroy();
+ Tegaki.onCancelCb();
+ },
+
+ onColorChange: function() {
+ Tegaki.setToolColor(this.value);
+ },
+
+ onSizeChange: function() {
+ this.previousElementSibling.setAttribute('data-value', this.value);
+ Tegaki.setToolSize(+this.value);
+ },
+
+ onAlphaChange: function() {
+ this.previousElementSibling.setAttribute('data-value', this.value);
+ Tegaki.setToolAlpha(+this.value);
+ },
+
+ onLayerChange: function() {
+ var selectedOptions = T$.selectedOptions(this);
+
+ if (selectedOptions.length > 1) {
+ Tegaki.activeLayer = null;
+ }
+ else {
+ Tegaki.setActiveLayer(+this.value);
+ }
+ },
+
+ onLayerAdd: function() {
+ TegakiHistory.push(Tegaki.addLayer());
+ Tegaki.setActiveLayer();
+ },
+
+ onLayerDelete: function() {
+ var i, ary, sel, opt, selectedOptions, action;
+
+ sel = T$.id('tegaki-layer');
+
+ selectedOptions = T$.selectedOptions(sel);
+
+ if (Tegaki.layers.length === selectedOptions.length) {
+ return;
+ }
+
+ if (!confirm(TegakiStrings.confirmDelLayers)) {
+ return;
+ }
+
+ if (selectedOptions.length > 1) {
+ ary = [];
+
+ for (i = 0; opt = selectedOptions[i]; ++i) {
+ ary.push(+opt.value);
+ }
+ }
+ else {
+ ary = [+sel.value];
+ }
+
+ action = Tegaki.deleteLayers(ary);
+
+ TegakiHistory.push(action);
+ },
+
+ onLayerVisibilityChange: function() {
+ var i, ary, sel, opt, flag, selectedOptions;
+
+ sel = T$.id('tegaki-layer');
+
+ selectedOptions = T$.selectedOptions(sel);
+
+ if (selectedOptions.length > 1) {
+ ary = [];
+
+ for (i = 0; opt = selectedOptions[i]; ++i) {
+ ary.push(+opt.value);
+ }
+ }
+ else {
+ ary = [+sel.value];
+ }
+
+ flag = !Tegaki.getLayerById(ary[0]).visible;
+
+ Tegaki.setLayerVisibility(ary, flag);
+ },
+
+ onMergeLayers: function() {
+ var i, ary, sel, opt, selectedOptions, action;
+
+ sel = T$.id('tegaki-layer');
+
+ selectedOptions = T$.selectedOptions(sel);
+
+ if (selectedOptions.length > 1) {
+ ary = [];
+
+ for (i = 0; opt = selectedOptions[i]; ++i) {
+ ary.push(+opt.value);
+ }
+ }
+ else {
+ ary = [+sel.value];
+ }
+
+ if (ary.length < 2) {
+ alert(TegakiStrings.errorMergeOneLayer);
+ return;
+ }
+
+ if (!confirm(TegakiStrings.confirmMergeLayers)) {
+ return;
+ }
+
+ action = Tegaki.mergeLayers(ary);
+
+ TegakiHistory.push(action);
+ },
+
+ onMoveLayer: function(e) {
+ var id, action, sel;
+
+ sel = T$.id('tegaki-layer');
+
+ id = +sel.options[sel.selectedIndex].value;
+
+ if (action = Tegaki.moveLayer(id, e.target.hasAttribute('data-up'))) {
+ TegakiHistory.push(action);
+ }
+ },
+
+ onToolChange: function() {
+ Tegaki.setTool(this.value);
+ Tegaki.updateUI();
+ Tegaki.updateCursor();
+ },
+
+ onCanvasSelected: function() {
+ var img;
+
+ if (!confirm(TegakiStrings.confirmChangeCanvas)) {
+ this.selectedIndex = +this.getAttribute('data-current');
+ return;
+ }
+
+ if (this.value === '0') {
+ Tegaki.ctx.fillStyle = Tegaki.bgColor;
+ Tegaki.ctx.fillRect(0, 0, Tegaki.baseWidth, Tegaki.baseHeight);
+ }
+ else {
+ img = T$.el('img');
+ img.onload = Tegaki.onImageLoaded;
+ img.onerror = Tegaki.onImageError;
+ this.disabled = true;
+ img.src = this.value;
+ }
+ },
+
+ onImageLoaded: function() {
+ var el, tmp = {};
+
+ el = T$.id('tegaki-canvas-select');
+ el.setAttribute('data-current', el.selectedIndex);
+ el.disabled = false;
+
+ Tegaki.copyContextState(Tegaki.activeCtx, tmp);
+ Tegaki.resizeCanvas(this.naturalWidth, this.naturalHeight);
+ Tegaki.activeCtx.drawImage(this, 0, 0);
+ Tegaki.copyContextState(tmp, Tegaki.activeCtx);
+
+ TegakiHistory.clear();
+ Tegaki.centerCnt();
+ Tegaki.updatePosOffset();
+ },
+
+ onImageError: function() {
+ var el;
+
+ el = T$.id('tegaki-canvas-select');
+ el.selectedIndex = +el.getAttribute('data-current');
+ el.disabled = false;
+
+ alert(TegakiStrings.errorLoadImage);
+ },
+
+ resizeCanvas: function(width, height) {
+ var i, layer;
+
+ Tegaki.canvas.width = width;
+ Tegaki.canvas.height = height;
+ Tegaki.ghostCanvas.width = width;
+ Tegaki.ghostCanvas.height = height;
+
+ Tegaki.ctx.fillStyle = Tegaki.bgColor;
+ Tegaki.ctx.fillRect(0, 0, width, height);
+
+ for (i = 0; layer = Tegaki.layers[i]; ++i) {
+ Tegaki.layersCnt.removeChild(layer.canvas);
+ }
+
+ Tegaki.activeCtx = null;
+ Tegaki.layers = [];
+ Tegaki.layerIndex = 0;
+ T$.id('tegaki-layer').textContent = '';
+
+ Tegaki.addLayer();
+ Tegaki.setActiveLayer();
+ },
+
+ getLayerIndex: function(id) {
+ var i, layer, layers = Tegaki.layers;
+
+ for (i = 0; layer = layers[i]; ++i) {
+ if (layer.id === id) {
+ return i;
+ }
+ }
+
+ return -1;
+ },
+
+ getLayerById: function(id) {
+ return Tegaki.layers[Tegaki.getLayerIndex(id)];
+ },
+
+ addLayer: function() {
+ var id, cnt, opt, canvas, layer, nodes, last;
+
+ canvas = T$.el('canvas');
+ canvas.className = 'tegaki-layer';
+ canvas.width = Tegaki.canvas.width;
+ canvas.height = Tegaki.canvas.height;
+
+ id = ++Tegaki.layerIndex;
+
+ layer = {
+ id: id,
+ name: 'Layer ' + id,
+ canvas: canvas,
+ ctx: canvas.getContext('2d'),
+ visible: true,
+ empty: true,
+ opacity: 1.0
+ };
+
+ Tegaki.layers.push(layer);
+
+ cnt = T$.id('tegaki-layer');
+ opt = T$.el('option');
+ opt.value = layer.id;
+ opt.textContent = layer.name;
+ cnt.insertBefore(opt, cnt.firstElementChild);
+
+ nodes = T$.cls('tegaki-layer', Tegaki.layersCnt);
+
+ if (nodes.length) {
+ last = nodes[nodes.length - 1];
+ }
+ else {
+ last = Tegaki.canvas;
+ }
+
+ Tegaki.layersCnt.insertBefore(canvas, last.nextElementSibling);
+
+ return new TegakiHistoryActions.AddLayer(id);
+ },
+
+ deleteLayers: function(ids) {
+ var i, id, len, sel, idx, indices, layers;
+
+ sel = T$.id('tegaki-layer');
+
+ indices = [];
+ layers = [];
+
+ for (i = 0, len = ids.length; i < len; ++i) {
+ id = ids[i];
+ idx = Tegaki.getLayerIndex(id);
+ sel.removeChild(sel.options[Tegaki.layers.length - 1 - idx]);
+ Tegaki.layersCnt.removeChild(Tegaki.layers[idx].canvas);
+
+ indices.push(idx);
+ layers.push(Tegaki.layers[idx]);
+
+ Tegaki.layers.splice(idx, 1);
+ }
+
+ Tegaki.setActiveLayer();
+
+ return new TegakiHistoryActions.DestroyLayers(indices, layers);
+ },
+
+ mergeLayers: function(ids) {
+ var i, id, sel, idx, canvasBefore, destId, dest, action;
+
+ sel = T$.id('tegaki-layer');
+
+ destId = ids.pop();
+ idx = Tegaki.getLayerIndex(destId);
+ dest = Tegaki.layers[idx].ctx;
+
+ canvasBefore = T$.copyCanvas(Tegaki.layers[idx].canvas);
+
+ for (i = ids.length - 1; i >= 0; i--) {
+ id = ids[i];
+ idx = Tegaki.getLayerIndex(id);
+ dest.drawImage(Tegaki.layers[idx].canvas, 0, 0);
+ }
+
+ action = Tegaki.deleteLayers(ids);
+ action.layerId = destId;
+ action.canvasBefore = canvasBefore;
+ action.canvasAfter = T$.copyCanvas(dest.canvas);
+
+ Tegaki.setActiveLayer(destId);
+
+ return action;
+ },
+
+ moveLayer: function(id, up) {
+ var idx, sel, opt, canvas, tmp, tmpId;
+
+ sel = T$.id('tegaki-layer');
+ idx = Tegaki.getLayerIndex(id);
+
+ canvas = Tegaki.layers[idx].canvas;
+ opt = sel.options[Tegaki.layers.length - 1 - idx];
+
+ if (up) {
+ if (!Tegaki.ghostCanvas.nextElementSibling) { return false; }
+ canvas.parentNode.insertBefore(canvas,
+ Tegaki.ghostCanvas.nextElementSibling.nextElementSibling
+ );
+ opt.parentNode.insertBefore(opt, opt.previousElementSibling);
+ tmpId = idx + 1;
+ }
+ else {
+ if (canvas.previousElementSibling.id === 'tegaki-canvas') { return false; }
+ canvas.parentNode.insertBefore(canvas, canvas.previousElementSibling);
+ opt.parentNode.insertBefore(opt, opt.nextElementSibling.nextElementSibling);
+ tmpId = idx - 1;
+ }
+
+ Tegaki.updateGhostLayerPos();
+
+ tmp = Tegaki.layers[tmpId];
+ Tegaki.layers[tmpId] = Tegaki.layers[idx];
+ Tegaki.layers[idx] = tmp;
+
+ Tegaki.activeLayer = tmpId;
+
+ return new TegakiHistoryActions.MoveLayer(id, up);
+ },
+
+ setLayerVisibility: function(ids, flag) {
+ var i, len, sel, idx, layer, optIdx;
+
+ sel = T$.id('tegaki-layer');
+ optIdx = Tegaki.layers.length - 1;
+
+ for (i = 0, len = ids.length; i < len; ++i) {
+ idx = Tegaki.getLayerIndex(ids[i]);
+ layer = Tegaki.layers[idx];
+ layer.visible = flag;
+
+ if (flag) {
+ sel.options[optIdx - idx].classList.remove('tegaki-strike');
+ layer.canvas.classList.remove('tegaki-hidden');
+ }
+ else {
+ sel.options[optIdx - idx].classList.add('tegaki-strike');
+ layer.canvas.classList.add('tegaki-hidden');
+ }
+ }
+ },
+
+ setActiveLayer: function(id) {
+ var ctx, idx;
+
+ idx = id ? Tegaki.getLayerIndex(id) : Tegaki.layers.length - 1;
+
+ if (idx < 0 || idx > Tegaki.maxLayers) {
+ return;
+ }
+
+ ctx = Tegaki.layers[idx].ctx;
+
+ if (Tegaki.activeCtx) {
+ Tegaki.copyContextState(Tegaki.activeCtx, ctx);
+ }
+
+ Tegaki.activeCtx = ctx;
+ Tegaki.activeLayer = idx;
+ T$.id('tegaki-layer').selectedIndex = Tegaki.layers.length - idx - 1;
+
+ Tegaki.updateGhostLayerPos();
+ },
+
+ updateGhostLayerPos: function() {
+ Tegaki.layersCnt.insertBefore(
+ Tegaki.ghostCanvas,
+ Tegaki.activeCtx.canvas.nextElementSibling
+ );
+ },
+
+ copyContextState: function(src, dest) {
+ var i, p, props = [
+ 'lineCap', 'lineJoin', 'strokeStyle', 'fillStyle', 'globalAlpha',
+ 'lineWidth', 'globalCompositeOperation'
+ ];
+
+ for (i = 0; p = props[i]; ++i) {
+ dest[p] = src[p];
+ }
+ },
+
+ updateCursor: function() {
+ var radius;
+
+ radius = 0 | (Tegaki.tool.size / 2);
+
+ if (Tegaki.tool.noCursor || radius < 1) {
+ Tegaki.layersCnt.style.cursor = 'default';
+ return;
+ }
+
+ Tegaki.layersCnt.style.cursor = 'url("'
+ + Tegaki.renderCircle(radius).toDataURL('image/png')
+ + '") 16 16, default';
+ },
+
+ updatePosOffset: function() {
+ var aabb = Tegaki.canvas.getBoundingClientRect();
+ Tegaki.offsetX = aabb.left + window.pageXOffset + Tegaki.cnt.scrollLeft;
+ Tegaki.offsetY = aabb.top + window.pageYOffset + Tegaki.cnt.scrollTop;
+ },
+
+ onMouseMove: function(e) {
+ if (Tegaki.isPainting) {
+ Tegaki.tool.draw(Tegaki.getCursorPos(e, 0), Tegaki.getCursorPos(e, 1));
+ }
+ else if (Tegaki.isColorPicking) {
+ TegakiPipette.draw(Tegaki.getCursorPos(e, 0), Tegaki.getCursorPos(e, 1));
+ }
+ },
+
+ onMouseDown: function(e) {
+ if (e.target.parentNode === Tegaki.layersCnt) {
+ if (Tegaki.activeLayer === null) {
+ alert(TegakiStrings.noActiveLayer);
+ return;
+ }
+ if (!Tegaki.layers[Tegaki.activeLayer].visible) {
+ alert(TegakiStrings.hiddenActiveLayer);
+ return;
+ }
+ }
+ else if (e.target !== Tegaki.bg) {
+ return;
+ }
+
+ if (e.which === 3 || e.altKey) {
+ Tegaki.isColorPicking = true;
+ TegakiPipette.draw(Tegaki.getCursorPos(e, 0), Tegaki.getCursorPos(e, 1));
+ }
+ else {
+ Tegaki.isPainting = true;
+ TegakiHistory.pendingAction = new TegakiHistoryActions.Draw(
+ Tegaki.layers[Tegaki.activeLayer].id
+ );
+ TegakiHistory.pendingAction.addCanvasState(Tegaki.activeCtx.canvas, 0);
+ Tegaki.tool.draw(Tegaki.getCursorPos(e, 0), Tegaki.getCursorPos(e, 1), true);
+ }
+ },
+
+ onMouseUp: function(e) {
+ if (Tegaki.isPainting) {
+ Tegaki.tool.commit && Tegaki.tool.commit();
+ TegakiHistory.pendingAction.addCanvasState(Tegaki.activeCtx.canvas, 1);
+ TegakiHistory.push(TegakiHistory.pendingAction);
+ Tegaki.isPainting = false;
+ }
+ else if (Tegaki.isColorPicking) {
+ e.preventDefault();
+ Tegaki.isColorPicking = false;
+ }
+ },
+
+ onDummy: function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+};
+
+// Bienvenido a Internet
+function topen() {
+ console.log(document.forms["imgform"].dataset.w);
+ console.log(document.forms["imgform"].dataset.h);
+ Tegaki.open({
+ onDone: function() {
+ document.getElementById('status').innerHTML = 'Subiendo...';
+ document.getElementById('buttons').style.display = 'none';
+ document.getElementById('links').style.display = 'none';
+ document.getElementById('filebase').value = Tegaki.flatten().toDataURL('image/png');
+ document.forms["imgform"].submit();
+ },
+ onCancel: function() { history.back(-1); },
+ width: document.forms["imgform"].dataset.w,
+ height: document.forms["imgform"].dataset.h
+ });
+}
+window.onload = function() {
+ document.getElementById('topen').addEventListener('click', topen);
+ topen();
+}; \ No newline at end of file
diff --git a/static/js/weabot.js b/static/js/weabot.js
new file mode 100644
index 0000000..0adc2e1
--- /dev/null
+++ b/static/js/weabot.js
@@ -0,0 +1,456 @@
+var style_cookie = 'weabot_style_ib';
+
+function set_stylesheet(styletitle) {
+ var css=document.getElementById("css");
+ if(css) {
+ css.href = "/static/css/" + styletitle.toLowerCase() + ".css";
+ localStorage.setItem(style_cookie, styletitle);
+ }
+}
+
+if(style_cookie && localStorage.hasOwnProperty(style_cookie)) {
+ set_stylesheet(localStorage.getItem(style_cookie));
+}
+
+var hiddenthreads = Array();
+/* IE/Opera fix, because they need to go learn a book on how to use indexOf with arrays */
+if (!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function(elt /*, from*/) {
+ var len = this.length;
+ var from = Number(arguments[1]) || 0;
+ from = (from < 0) ? Math.ceil(from) : Math.floor(from);
+ if (from < 0) from += len;
+ for (; from < len; from++) {
+ if (from in this && this[from] === elt) return from;
+ }
+ return -1;
+ };
+}
+
+function timeAgo(timestamp) {
+ var time = Math.round(Date.now()/1000);
+ var el = time - timestamp;
+ if (el==0) return "un instante";
+ else if (el==1) return "un segundo";
+ else if (el<60) return el + " segundos";
+ else if (el<120) return "un minuto";
+ else if (el<3600) return Math.round(el/60) + " minutos";
+ else if (el<7200) return "una hora";
+ else if (el<86400) return Math.round(el/3600) + " horas";
+ else if (el<172800) return "un día";
+ else if (el<2628000) return Math.round(el/86400) + " días";
+ else if (el<5256000) return "un mes";
+ else if (el<31536000) return Math.round(el/2628000) + " meses";
+ else if (el>31535999) return "más de un año";
+}
+
+function localTime(timestamp, id) {
+ id = id || 0;
+ var lcl = new Date(timestamp*1000);
+ lcl = ("0"+lcl.getDate()).slice(-2) + "/" + ("0" + (lcl.getMonth()+1)).slice(-2) + "/" + lcl.getFullYear().toString().slice(-2) + "(" + week[lcl.getDay()] + ")" + ("0"+lcl.getHours()).slice(-2) + ":" + ("0"+lcl.getMinutes()).slice(-2) + ":" + ("0"+lcl.getSeconds()).slice(-2)
+ if (id) lcl = lcl + " " + id;
+ return lcl;
+}
+
+function postClick(e) {
+ e.preventDefault();
+ var sel = window.getSelection().toString();
+ if (sel) sel = sel.replace(/^/gm, ">") + "\n";
+ insert(">>" + this.textContent + "\n" + sel);
+}
+
+function insert(text) {
+ var textarea=document.forms.postform.message;
+ if(textarea) {
+ if(textarea.createTextRange && textarea.caretPos) { // IE
+ var caretPos=textarea.caretPos;
+ caretPos.text=caretPos.text.charAt(caretPos.text.length-1)==" "?text+" ":text;
+ } else if(textarea.setSelectionRange) { // Firefox
+ var start=textarea.selectionStart;
+ var end=textarea.selectionEnd;
+ textarea.value=textarea.value.substr(0,start)+text+textarea.value.substr(end);
+ textarea.setSelectionRange(start+text.length,start+text.length);
+ } else { textarea.value+=text+" "; }
+ textarea.focus();
+ }
+ return false;
+}
+
+function quote(b, a) {
+ var v = eval("document." + a + ".message");
+ v.value += ">>" + b + "a\ndfs";
+ v.focus();
+}
+
+function checkhighlight() {
+ var match;
+ if(match=/#i([0-9]+)/.exec(document.location.toString()))
+ if(!document.forms.postform.message.value)
+ insert(">>"+match[1]+"\r\n");
+ if(match=/#([0-9]+)/.exec(document.location.toString()))
+ highlight(match[1]);
+}
+
+function highlight(post) {
+ var cells = document.getElementsByClassName("reply");
+ for(var i=0;i<cells.length;i++) if(cells[i].className == "reply highlight") cells[i].className = "reply";
+ var reply = document.getElementById("reply" + post);
+ if(reply) {
+ reply.className = "reply highlight";
+ var match = /^([^#]*)/.exec(document.location.toString());
+ document.location = match[1] + "#" + post;
+ }
+}
+
+function expandimg(e) {
+ var post_id = this.dataset.id;
+ var img_url = this.href;
+ var thumb_url = this.dataset.thumb;
+ var img_w = parseInt(this.dataset.w);
+ var img_h = parseInt(this.dataset.h);
+ var thumb_w = parseInt(this.dataset.tw);
+ var thumb_h = parseInt(this.dataset.th);
+ var format = img_url.substring(img_url.lastIndexOf(".")+1, img_url.length);
+ var exp_vid = 0;
+
+ if(window.innerWidth > 900) var ratio = Math.min((window.innerWidth-130) / img_w, 1);
+ else var ratio = Math.min((window.innerWidth-40) / img_w, 1);
+
+ if(thumb_w < 1) return true;
+
+ var img_cont = document.getElementById("thumb" + post_id);
+ var post_block = img_cont.parentElement.parentElement.getElementsByTagName("blockquote")[0];
+ var img;
+
+ for(var i = 0; i < img_cont.childNodes.length; i++)
+ if(img_cont.childNodes[i].nodeName.toLowerCase() == "img") {
+ img = img_cont.childNodes[i];
+ } else if(img_cont.childNodes[i].nodeName.toLowerCase() == "video") {
+ img = img_cont.childNodes[i];
+ exp_vid = 1;
+ }
+
+ if(img) {
+ if( (format == "webm") && (exp_vid == 0) ) var new_img = document.createElement("video");
+ else var new_img = document.createElement("img");
+ new_img.setAttribute("class", "thumb");
+ new_img.setAttribute("alt", "" + post_id);
+
+ if( (img.getAttribute("width") == ("" + thumb_w)) && (img.getAttribute("height") == ("" + thumb_h)) ) {
+ // thumbnail -> fullsize
+ if(format == "webm") {
+ new_img.setAttribute("controls", "");
+ new_img.setAttribute("loop", "");
+ new_img.setAttribute("autoplay", "");
+ }
+ new_img.setAttribute("src", "" + img_url);
+ new_img.setAttribute("width", img_w);
+ new_img.setAttribute("height", img_h);
+ new_img.setAttribute("style", "max-width:"+Math.floor((img_w*ratio))+"px;max-height:"+Math.floor((img_h*ratio))+"px;");
+ post_block.setAttribute("style", "");
+ img_cont.style.display = 'table';
+ } else {
+ // fullsize -> thumbnail
+ if(format == "webm") {
+ new_img.removeAttribute("controls");
+ new_img.removeAttribute("loop");
+ new_img.removeAttribute("autoplay");
+ }
+ new_img.setAttribute("src", "" + thumb_url);
+ new_img.setAttribute("width", thumb_w);
+ new_img.setAttribute("height", thumb_h);
+ post_block.setAttribute("style", "margin-left:"+(parseInt(thumb_w)+40)+"px;max-width:"+(1000-parseInt(thumb_w))+"px");
+ img_cont.removeAttribute("style");
+ }
+
+ while(img_cont.lastChild) img_cont.removeChild(img_cont.lastChild);
+
+ img_cont.appendChild(new_img);
+ e.preventDefault();
+ }
+}
+
+function filePreview(e) {
+ var file = postform.file.files[0];
+ var inpt = document.getElementById("file");
+ var prev = document.getElementById("filepreview");
+ var noimg = document.getElementById("noimage");
+ if (noimg) noimg = document.getElementById("noimage").parentNode;
+ if (file.size > (maxsize*1024)) { inpt.value = ""; return alert("El archivo es muy grande. El tamaño máximo es " + maxsize + " KB."); }
+ if (!types.includes(inpt.value.slice(inpt.value.lastIndexOf(".")+1).toUpperCase())) { inpt.value = ""; return alert("Tipo de archivo no soportado."); }
+ var read = new FileReader();
+ read.readAsDataURL(file);
+ read.onload = function(){
+ inpt.style.display = "none";
+ if (noimg) noimg.style.display = "none";
+ prev.removeAttribute("style");
+ var fname = (file.name.length < 20) ? file.name : file.name.substr(0, 19) + "…";
+ if (file.type.startsWith("image")) prev.insertAdjacentHTML('beforeend', '<img class="thumbpreview" src="' + read.result + '" /> ' + fname);
+ else prev.insertAdjacentHTML('beforeend', fname);
+ prev.appendChild(document.createTextNode(" ["));
+ var btn = document.createElement("a");
+ btn.href = "#";
+ btn.innerText = "Quitar"
+ btn.addEventListener("click", function(e) {
+ e.preventDefault();
+ prev.innerHTML = "";
+ prev.style.display = "none";
+ inpt.removeAttribute("style");
+ if (noimg) noimg.removeAttribute("style");
+ inpt.value = "";
+ });
+ prev.appendChild(btn);
+ prev.appendChild(document.createTextNode("] "));
+ };
+}
+
+function togglethread(e) {
+ e.preventDefault();
+ if(this.parentElement.id.startsWith("unhide")) {
+ var threadid = this.parentElement.id.substr(6);
+ } else if(this.parentElement.parentElement.id.startsWith("thread")) {
+ var threadid = this.parentElement.parentElement.id.substr(6);
+ } else { return; }
+ if (hiddenthreads.toString().indexOf(threadid) !== -1) {
+ document.getElementById("unhide" + threadid).style.display = "none";
+ document.getElementById("thread" + threadid).removeAttribute("style");
+ hiddenthreads.splice(hiddenthreads.indexOf(threadid), 1);
+ } else {
+ document.getElementById("unhide" + threadid).removeAttribute("style");
+ document.getElementById("thread" + threadid).style.display = "none";
+ hiddenthreads.push(threadid);
+ }
+ if (hiddenthreads == "") localStorage.removeItem("hiddenthreads");
+ else localStorage.setItem("hiddenthreads", hiddenthreads.join("!"));
+}
+
+function saveInputs(e) {
+ var e = e || window.event;
+ var form = e.target || e.srcElement;
+ if(typeof(form.fielda) !== "undefined") weabot.name = form.fielda.value;
+ if(typeof(form.fielda) !== "undefined") weabot.email = form.fieldb.value;
+ localStorage.setItem("weabot", JSON.stringify(weabot));
+}
+
+function setInputs(id) {
+ if (document.getElementById(id)) {
+ with(document.getElementById(id)) {
+ if(typeof(fielda) !== 'undefined' && !fielda.value && weabot.name) fielda.value = weabot.name;
+ if(typeof(fielda) !== 'undefined' && !fieldb.value && weabot.email) fieldb.value = weabot.email;
+ if(!password.value) password.value = getPassword();
+ addEventListener("submit", saveInputs);
+ }
+ }
+}
+
+function setPassword(id) {
+ if (document.getElementById(id).password)
+ with (document.getElementById(id)) if(!password.value) password.value = getPassword("weabot_password");
+}
+
+function getPassword() {
+ if (weabot.password) return weabot.password;
+ var char="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ var pass="";
+ for (var i=0;i<8;i++) {
+ var rnd = Math.floor(Math.random()*char.length);
+ pass += char.substring(rnd, rnd+1);
+ }
+ weabot.password = pass;
+ localStorage.setItem("weabot", JSON.stringify(weabot));
+ return(pass);
+}
+
+function catSort(type) {
+ for(var i=0;i<srt.length;i++) srt[i].innerHTML=srt[i].innerText;
+ srt[type].innerHTML = "<b>"+srt[type].innerText+"</b>";
+ var cont = document.getElementById("catalog");
+ var elem = document.getElementsByClassName("thread");
+ var arr = Array.prototype.slice.call(elem);
+ if (type==0) arr.sort(function (a,b) { return (a.dataset.num-b.dataset.num) });
+ else if (type==1) arr.sort(function (a,b) { return (b.dataset.id-a.dataset.id) });
+ else if (type==2) arr.sort(function (a,b) { return (a.dataset.id-b.dataset.id) });
+ else if (type==3) arr.sort(function (a,b) { return (b.dataset.res-a.dataset.res) });
+ else if (type==4) arr.sort(function (a,b) { return (a.dataset.res-b.dataset.res) });
+ for (var j=0;j<arr.length;j++) cont.appendChild(arr[j]);
+ localStorage.setItem("catalog", JSON.stringify(opcs));
+}
+
+function catSearch() {
+ var filter = document.getElementById("cat_search").value.toLowerCase();
+ var nodes = document.getElementsByTagName("p");
+ for (i = 0; i < nodes.length; i++) {
+ if (nodes[i].innerText.toLowerCase().includes(filter))
+ nodes[i].parentNode.removeAttribute("style");
+ else nodes[i].parentNode.style.display = "none";
+ }
+}
+
+function catThumbs(big) {
+ var btn = document.getElementById("cat_size");
+ var cat = document.getElementById("catalog");
+ var threads = document.getElementsByClassName("thread");
+ if (opcs.big) {
+ cat.className = "enlarged";
+ for (j = 0; j < threads.length; j++) {
+ img = threads[j].getElementsByTagName("a")[0];
+ img.innerHTML = img.innerHTML.replace("/cat/", "/thumb/");
+ }
+ btn.innerText = "Grande";
+ } else {
+ cat.removeAttribute("class");
+ for (j = 0; j < threads.length; j++) {
+ img = threads[j].getElementsByTagName("a")[0];
+ img.innerHTML = img.innerHTML.replace("/thumb/", "/cat/");
+ }
+ btn.innerText = "Pequeño";
+ }
+ localStorage.setItem("catalog", JSON.stringify(opcs));
+}
+
+function catTeasers(teaser) {
+ var btn = document.getElementById("cat_hide");
+ if (!teaser) {
+ var style = document.createElement("style");
+ style.id = "teaser_style";
+ style.type = "text/css";
+ style.innerText = '#catalog p{display:none}';
+ document.head.appendChild(style);
+ btn.innerText = "Mostrar";
+ } else {
+ var style = document.getElementById("teaser_style");
+ if (style) style.parentNode.removeChild(style);
+ btn.innerText = "Ocultar";
+ }
+ localStorage.setItem("catalog", JSON.stringify(opcs));
+}
+
+function catMenu(e) {
+ var brd = document.getElementsByName("board")[0].value;
+ var id = this.dataset.id;
+ this.insertAdjacentHTML('afterbegin', '<div id="thread_ctrl" style="margin-bottom:3px;">[<a href="/cgi/report/' + brd + '/' + id + '">Denunciar</a>] [<a href="#" class="hh">Ocultar</a>]');
+ this.getElementsByClassName("hh")[0].addEventListener("click", function(e) {
+ document.getElementById("cat" + id + brd).style.display = "none";
+ hiddenthreads.push(id + brd);
+ localStorage.setItem("hiddenthreads", hiddenthreads.join("!"))
+ if (document.getElementById("hidden_label")) { hidden_num++; document.getElementById("hidden_num").innerText = hidden_num; }
+ else { hidden_num = 1; catHidden(); }
+ });
+}
+
+function catMenuClose(e) { document.getElementById("thread_ctrl").remove(); }
+
+function catHidden() {
+ var menu = document.getElementById("ctrl");
+ menu.insertAdjacentHTML('beforeend', ' <span id="hidden_label">[Hilos ocultos: <span id="hidden_num">' + hidden_num + '</span> - ');
+ var lbl = document.getElementById("hidden_label");
+ var shw = document.createElement("a");
+ shw.href = "#"; shw.innerText = "Deshacer";
+ shw.addEventListener("click", function(e) {
+ e.preventDefault();
+ for(var i=0;i<hiddenthreads.length;i++){
+ try {document.getElementById("cat" + hiddenthreads[i]).removeAttribute("style");}
+ catch(err) { continue; } }
+ lbl.parentElement.removeChild(lbl); hidden_num = 0;
+ var aux = hiddenthreads.join("!");
+ var exp = new RegExp("\\b[0-9]+" + document.getElementsByName("board")[0].value + "\\b", "g");
+ aux = aux.replace(exp, "!"); aux = aux.replace(/!+/g, "!"); aux = aux.replace(/(^!|!$)/g, "");
+ if (aux == "") { localStorage.removeItem("hiddenthreads"); hiddenthreads = []; }
+ else { localStorage.setItem("hiddenthreads", aux); hiddenthreads = aux.split("!"); }
+ });
+ lbl.appendChild(shw); lbl.appendChild(document.createTextNode("]"));
+}
+
+document.addEventListener("DOMContentLoaded", function(e) {
+ checkhighlight();
+ if (localStorage.hasOwnProperty("weabot")) weabot = JSON.parse(localStorage.getItem("weabot"));
+ else weabot = {"name":null,"email":null,"password":null};
+
+ if(localStorage.hasOwnProperty("hiddenthreads")) {
+ hiddenthreads = localStorage.getItem("hiddenthreads").split("!");
+ if (document.getElementById("catalog")) {
+ hidden_num = 0;
+ for(var i=0;i<hiddenthreads.length;i++){
+ try {
+ document.getElementById("cat" + hiddenthreads[i]).style.display = "none";
+ hidden_num++;
+ } catch(err) { continue; }
+ }
+ if (hidden_num) { catHidden(); }
+ } else {
+ for(var i=0;i<hiddenthreads.length;i++){
+ try {
+ document.getElementById("unhide" + hiddenthreads[i]).removeAttribute("style");
+ document.getElementById("thread" + hiddenthreads[i]).style.display = "none";
+ } catch(err) { continue; }
+ }
+ }
+ }
+
+ if(localStorage.getItem("shobon_time") != "false") {
+ var dts = document.getElementsByClassName("date");
+ if (dts[0].dataset.unix) {
+ week = ["dom", "lun", "mar", "mie", "jue", "vie", "sab"];
+ if (document.getElementsByName("board")[0].value == "2d") week = ["æ—¥", "月", "ç«", "æ°´", "木", "金", "土"];
+ for(var d=0;d<dts.length;d++) {
+ dts[d].addEventListener("mouseover", function(e) { this.title = "Hace " + timeAgo(this.dataset.unix); });
+ if (dts[d].innerText.includes("ID:")) var id = dts[d].innerText.split(" ")[1];
+ dts[d].innerText = localTime(dts[d].dataset.unix, id);
+ }
+ }
+ }
+
+ var ids = document.getElementsByClassName("postid");
+ for(var i=0;i<ids.length;i++) {
+ ids[i].addEventListener('click', postClick);
+ }
+ var tts = document.getElementsByClassName("tt");
+ for(var i=0;i<tts.length;i++) {
+ tts[i].addEventListener('click', togglethread);
+ }
+ var tts = document.getElementsByClassName("expimg");
+ for(var i=0;i<tts.length;i++) {
+ tts[i].addEventListener('click', expandimg);
+ }
+ var sss = document.getElementsByClassName("ss");
+ for(var i=0;i<sss.length;i++) {
+ sss[i].addEventListener('click', function() {
+ var cur = document.getElementById("cur_stl");
+ set_stylesheet(this.textContent);
+ if (cur) cur.removeAttribute("id");
+ this.id = "cur_stl";
+ });
+ if (sss[i].innerText == localStorage.getItem(style_cookie)) sss[i].id = "cur_stl";
+ }
+
+ if (document.getElementById(document.getElementsByName("board")[0].value))
+ document.getElementById(document.getElementsByName("board")[0].value).className = "cur_brd";
+
+ if (document.getElementById("postform")) {
+ setInputs("postform");
+ setPassword("delform");
+ maxsize = document.getElementById("maxsize").innerText;
+ types = document.getElementById("filetypes").innerText.split(", ");
+ if (types.includes("JPG")) types.push("JPEG");
+ postform.file.addEventListener("change", filePreview);
+ }
+
+ window.addEventListener("hashchange", checkhighlight);
+
+ if (document.getElementById("catalog")) {
+ srt = document.getElementsByClassName("cat_sort");
+ for(var i=0;i<srt.length;i++) { srt[i].innerHTML=srt[i].innerText; srt[i].addEventListener("click", function(e) { e.preventDefault(); opcs.sort=this.dataset.sort; catSort(opcs.sort); }); }
+ document.getElementById("cat_size").addEventListener("click", function(e) { e.preventDefault(); opcs.big=!opcs.big; catThumbs(opcs.big); });
+ document.getElementById("cat_hide").addEventListener("click", function(e) { e.preventDefault(); opcs.teaser=!opcs.teaser; catTeasers(opcs.teaser); });
+ document.getElementById("cat_search").addEventListener("keyup", catSearch);
+ if (localStorage.hasOwnProperty("catalog")) {
+ opcs = JSON.parse(localStorage.getItem("catalog"));
+ if(match=/\?sort=([0-9])/.exec(document.location.toString())) opcs.sort=match[1];
+ catSort(opcs.sort); catThumbs(opcs.big); catTeasers(opcs.teaser);
+ } else {
+ opcs = {"sort":1,"big":false,"teaser":true}; localStorage.setItem("catalog", JSON.stringify(opcs));
+ }
+ var thr = document.getElementsByClassName("thread");
+ for(var i=0;i<thr.length;i++) { thr[i].addEventListener("mouseenter", catMenu); thr[i].addEventListener("mouseleave", catMenuClose); }
+ }
+}); \ No newline at end of file
diff --git a/static/js/weabotxt.js b/static/js/weabotxt.js
new file mode 100644
index 0000000..37668d8
--- /dev/null
+++ b/static/js/weabotxt.js
@@ -0,0 +1,299 @@
+var style_cookie = "weabot_style_txt";
+if(style_cookie && localStorage.hasOwnProperty(style_cookie)) { set_stylesheet(localStorage.getItem(style_cookie)); }
+
+var hiddenposts = Array();
+
+function set_stylesheet(styletitle) {
+ var css=document.getElementById("css");
+ if(css) css.href = "/static/css/txt/"+styletitle.toLowerCase()+".css";
+ localStorage.setItem(style_cookie,styletitle);
+}
+
+function changeDate() {
+ var dts = document.getElementsByClassName("date");
+ if (dts[0].dataset.unix) {
+ week = ["dom", "lun", "mar", "mie", "jue", "vie", "sab"];
+ if (board == "world") week = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"];
+ for(var d=0;d<dts.length;d++) {
+ dts[d].addEventListener('mouseover', function(e) { this.title = "Hace " + timeAgo(this.dataset.unix); });
+ if (dts[d].innerText.includes("ID:")) var id = dts[d].innerText.split(" ")[1];
+ dts[d].innerText = localTime(dts[d].dataset.unix, id);
+ }
+ }
+}
+
+function timeAgo(timestamp) {
+ var time = Math.round(Date.now()/1000);
+ var el = time - timestamp;
+ if (el==0) return "un instante";
+ else if (el==1) return "un segundo";
+ else if (el<60) return el + " segundos";
+ else if (el<120) return "un minuto";
+ else if (el<3600) return Math.round(el/60) + " minutos";
+ else if (el<7200) return "una hora";
+ else if (el<86400) return Math.round(el/3600) + " horas";
+ else if (el<172800) return "un día";
+ else if (el<2628000) return Math.round(el/86400) + " días";
+ else if (el<5256000) return "un mes";
+ else if (el<31536000) return Math.round(el/2628000) + " meses";
+ else if (el>31535999) return "más de un año";
+}
+
+function localTime(timestamp, id) {
+ id = id || 0;
+ var lcl = new Date(timestamp*1000);
+ lcl = ("0"+lcl.getDate()).slice(-2) + "/" + ("0" + (lcl.getMonth()+1)).slice(-2) + "/" + lcl.getFullYear().toString().slice(-2) + "(" + week[lcl.getDay()] + ")" + ("0"+lcl.getHours()).slice(-2) + ":" + ("0"+lcl.getMinutes()).slice(-2) + ":" + ("0"+lcl.getSeconds()).slice(-2)
+ if (id) lcl = lcl + " " + id;
+ return lcl;
+}
+
+/* IE/Opera fix, because they need to go learn a book on how to use indexOf with arrays */
+if (!Array.prototype.indexOf) {
+ Array.prototype.indexOf = function(elt /*, from*/) {
+ var len = this.length;
+ var from = Number(arguments[1]) || 0;
+ from = (from < 0) ? Math.ceil(from) : Math.floor(from);
+ if (from < 0) from += len;
+ for (; from < len; from++) { if (from in this && this[from] === elt) return from; }
+ return -1;
+ };
+}
+
+function getPassword() {
+ if (weabot.password) return weabot.password;
+ var char="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ var pass="";
+ for (var i=0;i<8;i++) {
+ var rnd = Math.floor(Math.random()*char.length);
+ pass += char.substring(rnd, rnd+1);
+ }
+ weabot.password = pass;
+ localStorage.setItem("weabot", JSON.stringify(weabot));
+ return(pass);
+}
+
+function saveInputs(e) {
+ var e = e || window.event;
+ var form = e.target || e.srcElement;
+ if(typeof(form.fielda) !== "undefined") weabot.name = form.fielda.value;
+ if(typeof(form.fielda) !== "undefined") weabot.email = form.fieldb.value;
+ localStorage.setItem("weabot", JSON.stringify(weabot));
+}
+
+function setInputs(id) {
+ if (document.getElementById(id)) {
+ with(document.getElementById(id)) {
+ if(typeof(fielda) !== 'undefined' && !fielda.value && weabot.name) fielda.value = weabot.name;
+ if(typeof(fielda) !== 'undefined' && !fieldb.value && weabot.email) fieldb.value = weabot.email;
+ if(!password.value) password.value = getPassword();
+ if(typeof preview !== 'undefined') { preview.id = id; preview.addEventListener("click", previewPost); }
+ addEventListener("submit", saveInputs);
+ }
+ }
+}
+
+function setPassword(id) {
+ if (document.getElementById(id).password)
+ with (document.getElementById(id))
+ if(!password.value) password.value = getPassword("weabot_password");
+}
+
+// Textboard data
+function insert(text) {
+ var textarea=document.forms.postform.message;
+ if(textarea) {
+ if(textarea.createTextRange && textarea.caretPos) { // IE
+ var caretPos=textarea.caretPos;
+ caretPos.text=caretPos.text.charAt(caretPos.text.length-1)==" "?text+" ":text;
+ } else if(textarea.setSelectionRange) { // Firefox
+ var start=textarea.selectionStart;
+ var end=textarea.selectionEnd;
+ textarea.value=textarea.value.substr(0,start)+text+textarea.value.substr(end);
+ textarea.setSelectionRange(start+text.length,start+text.length);
+ } else {
+ textarea.value+=text+" ";
+ }
+ textarea.focus();
+ }
+ return false;
+}
+
+function deletePost(e) {
+ var ids = this.parentElement.firstChild.href.split("/");
+ var post = ids.pop();
+ var realid = ids.pop();
+ if(confirm("¿Seguro que deseas borrar el mensaje "+post+"?")) {
+ var script="/cgi/delete";
+ document.location=script+"?board="+board+"&password="+weabot.password+"&delete="+realid;
+ }
+ e.preventDefault();
+}
+
+function postClick(e) {
+ e.preventDefault();
+ var sel = window.getSelection().toString();
+ if (sel) { sel=sel.replace(/^/gm, ">")+"\n"; sel="\n"+sel; }
+ insert(">>" + this.textContent + sel);
+}
+
+function previewPost(e) {
+ var formid = e.target.id;
+ var thread = "0";
+ if(formid.startsWith("postform")) thread = formid.substr(8);
+
+ var form=document.getElementById(formid);
+ var preview=document.getElementById("preview"+thread);
+ var main=document.getElementById("options");
+
+ if(!form||!preview||!form.message.value) return;
+ if(main) main.style.display="";
+
+ preview.removeAttribute("style");
+ preview.innerHTML="<em>Cargando...</em>";
+
+ var text="message="+encodeURIComponent(form.message.value)+"&board="+board;
+ if (thread) text+="&parentid="+thread;
+
+ var xmlhttp=get_xmlhttp();
+ xmlhttp.open("POST", "/cgi/preview");
+ xmlhttp.onreadystatechange=function() { if(xmlhttp.readyState==4) preview.innerHTML=xmlhttp.responseText; }
+ if(is_ie()||xmlhttp.setRequestHeader) xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
+ xmlhttp.send(text);
+}
+
+function listSort() {
+ var s = opcs.sort;
+ var cont = document.getElementById("content");
+ var elem = document.getElementsByClassName("row");
+ var arr = Array.prototype.slice.call(elem); arr.shift();
+ if (s=="Normal") { arr.sort(function (a,b) { return (parseInt(a.childNodes[1].innerText) - parseInt(b.childNodes[1].innerText)) }); }
+ else if(s=="Edad"){ arr.sort(function (a,b) { return (b.children[1].firstChild.href.split("/")[5] - a.children[1].firstChild.href.split("/")[5]) }); }
+ else if(s=="Largo"){ arr.sort(function (a,b) { return (b.children[2].textContent - a.children[2].textContent) }); }
+ else if(s=="Rapidez"){ var now=Math.round(Date.now()/1000); arr.sort(function (a,b) { return ((b.children[2].textContent/(now-b.children[1].firstChild.href.split("/")[5])) - (a.children[2].textContent/(now-a.children[1].firstChild.href.split("/")[5]))) }); }
+ else if(s=="Aleatorio"){ arr.sort(function(a,b) { return 0.5-Math.random()}); }
+ for (var j=0;j<arr.length;j++) cont.appendChild(arr[j]);
+ localStorage.setItem("threadlist", JSON.stringify(opcs));
+}
+
+function listDisplay() {
+ var d = opcs.disp;
+ if (d=="Malla") {
+ document.getElementById("header").style.display = "none";
+ document.getElementById("content").className = "grid";
+ var style = document.createElement("style");
+ style.id = "labels";
+ style.type = "text/css";
+ style.innerText = '#content .row div.date{display:none}#content.grid div.com:before{content:"("}#content.grid .com:after{content:")"}';
+ document.head.appendChild(style);
+ } else if (d=="Lista") {
+ var style = document.getElementById("labels");
+ if (style) style.parentNode.removeChild(style);
+ document.getElementById("header").removeAttribute("style");
+ document.getElementById("content").className = "list";
+ }
+ localStorage.setItem("threadlist", JSON.stringify(opcs));
+}
+
+function searchSubjects(e) {
+ var filter = this.value.toLowerCase();
+ var nodes = document.getElementsByClassName("thread");
+ for (i=0; i<nodes.length; i++) {
+ if (nodes[i].innerText.toLowerCase().includes(filter)) nodes[i].parentNode.removeAttribute("style");
+ else nodes[i].parentNode.style.display = "none";
+ }
+}
+
+function get_xmlhttp() {
+ var xmlhttp;
+ try { xmlhttp=new ActiveXObject("Msxml2.XMLHTTP"); }
+ catch(e1) {
+ try { xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); }
+ catch(e1) { xmlhttp=null; }
+ }
+ if(!xmlhttp && typeof XMLHttpRequest!='undefined') xmlhttp=new XMLHttpRequest();
+ return(xmlhttp);
+}
+
+function is_ie() { return(document.all&&!document.opera); }
+
+function showpost(post) {
+ post.children[0].classList.remove("hidden");
+ post.children[1].style.display = 'block';
+}
+function hidepost(post) {
+ post.children[0].classList.add("hidden");
+ post.children[1].style.display = 'none';
+}
+function togglepost(e) {
+ e.preventDefault();
+ var post = this.parentElement;
+ var postid = board + this.getElementsByClassName("date")[0].dataset.unix;
+
+ if(post.children[1].style.display == 'none') {
+ showpost(post);
+ if(hiddenposts.includes(postid)) hiddenposts.splice(hiddenposts.indexOf(postid), 1);
+ } else {
+ hidepost(post);
+ if(!hiddenposts.includes(postid)) hiddenposts.push(postid);
+ }
+
+ localStorage.setItem("hiddenposts", hiddenposts.join("!"));
+}
+
+document.addEventListener("DOMContentLoaded", function() {
+ if (localStorage.hasOwnProperty("weabot")) weabot = JSON.parse(localStorage.getItem("weabot"));
+ else weabot = {"name":null,"email":null,"password":null};
+
+ board = document.getElementsByName("board")[0].value;
+
+ if(localStorage.getItem("shobon_time") != "false") {
+ changeDate();
+ }
+
+ var ids = document.getElementsByClassName("num");
+ for(var i=0;i<ids.length;i++) ids[i].addEventListener('click', postClick);
+
+ var forms = document.getElementsByTagName("form");
+ for(var i=0;i<forms.length;i++) { if(forms[i].id.startsWith("postform")) setInputs(forms[i].id); }
+
+ var sss = document.getElementsByClassName("ss");
+ var style = localStorage.getItem(style_cookie);
+ for(var i=0;i<sss.length;i++) {
+ sss[i].addEventListener("click", function() {
+ set_stylesheet(this.textContent);
+ var cur = document.getElementById("cur_stl");
+ if (cur) cur.removeAttribute("id");
+ this.id = "cur_stl";
+ });
+ if (sss[i].innerText == style) sss[i].id = "cur_stl";
+ }
+
+ var dds = document.getElementsByClassName("del");
+ for(var i=0;i<dds.length;i++) { dds[i].children[1].addEventListener("click", deletePost); }
+
+ var where = document.getElementById(document.getElementsByName("board")[0].value);
+ if (where) where.className = "cur_brd";
+
+ if (document.body.className == "threads") {
+ var srt = document.getElementsByClassName("l_s");
+ for(var i=0;i<srt.length;i++){ srt[i].addEventListener("click",function(e){ e.preventDefault(); opcs.sort=this.textContent; listSort(); }); }
+ var dsp = document.getElementsByClassName("l_d");
+ for(var i=0;i<dsp.length;i++){ dsp[i].addEventListener("click",function(e){ e.preventDefault(); opcs.disp=this.textContent; listDisplay(); }); }
+ document.getElementById("l_sr").addEventListener("keyup", searchSubjects);
+ if (localStorage.hasOwnProperty("threadlist")) { opcs = JSON.parse(localStorage.getItem("threadlist")); listSort(); listDisplay(); }
+ else { opcs = {"sort":"Normal","disp":"Lista"}; localStorage.setItem("threadlist", JSON.stringify(opcs)); }
+ }
+
+ if(localStorage.hasOwnProperty("hiddenposts"))
+ hiddenposts = localStorage.getItem("hiddenposts").split("!");
+
+ var pps = document.getElementsByClassName("date");
+ for(var i=0;i<pps.length;i++) {
+ if(hiddenposts.includes(board+pps[i].dataset.unix)) {
+ console.log(pps[i].dataset.unix);
+ hidepost(pps[i].parentElement.parentElement);
+ }
+
+ pps[i].parentElement.addEventListener('dblclick', togglepost);
+ }
+}); \ No newline at end of file
diff --git a/static/js/wpaint/.gitignore b/static/js/wpaint/.gitignore
new file mode 100644
index 0000000..7a48116
--- /dev/null
+++ b/static/js/wpaint/.gitignore
@@ -0,0 +1,3 @@
+test/uploads/wPaint-*
+node_modules/
+npm-debug.txt \ No newline at end of file
diff --git a/static/js/wpaint/README.md b/static/js/wpaint/README.md
new file mode 100644
index 0000000..eac4c2a
--- /dev/null
+++ b/static/js/wpaint/README.md
@@ -0,0 +1,421 @@
+# wPaint.js
+
+A jQuery paint plugin for a simple drawing surface that you can easily pop into your pages, similar to the basic windows paint program.
+
+* [View the wPaint demo](http://wpaint.websanova.com)
+* [Download the lastest version of wPaint](https://github.com/websanova/wPaint/tags)
+
+
+## Related Plugins
+
+* [wScratchPad](http://wscratchpad.websanova.com) - Plugin simulating scratch card.
+* [wColorPicker](http://wcolorpicker.websanova.com) - Color pallette seleciton plugin.
+
+
+## Support
+
+If you enjoy this plugin please leave a small contribution on [Gittip](https://gittip.com/websanova). I work on these plugins completely in my free time and any contribution is greatly appreciated.
+
+
+## Settings
+
+Settings are available per plugin. Meaning only when that plugin is included will those settings be available.
+
+### core
+
+```js
+$.fn.wPaint.defaults = {
+ path: '/', // set absolute path for images and cursors
+ theme: 'standard classic', // set theme
+ autoScaleImage: true, // auto scale images to size of canvas (fg and bg)
+ autoCenterImage: true, // auto center images (fg and bg, default is left/top corner)
+ menuHandle: true, // setting to false will means menus cannot be dragged around
+ menuOrientation: 'horizontal', // menu alignment (horizontal,vertical)
+ menuOffsetLeft: 5, // left offset of primary menu
+ menuOffsetTop: 5, // top offset of primary menu
+ bg: null, // set bg on init
+ image: null, // set image on init
+ imageStretch: false, // stretch smaller images to full canvans dimensions
+ onShapeDown: null, // callback for draw down event
+ onShapeMove: null, // callback for draw move event
+ onShapeUp: null // callback for draw up event
+};
+```
+
+### main
+
+```js
+$.extend($.fn.wPaint.defaults, {
+ mode: 'pencil', // set mode
+ lineWidth: '3', // starting line width
+ fillStyle: '#FFFFFF', // starting fill style
+ strokeStyle: '#FFFF00' // start stroke style
+});
+```
+
+### text
+
+```js
+$.extend($.fn.wPaint.defaults, {
+ fontSize : '12', // current font size for text input
+ fontFamily : 'Arial', // active font family for text input
+ fontBold : false, // text input bold enable/disable
+ fontItalic : false, // text input italic enable/disable
+ fontUnderline : false // text input italic enable/disable
+});
+```
+
+### shapes
+
+No settings.
+
+### file
+
+Note that the callbacks for `file` are user generated for the most part as they deal heavily with client/server side code. You can view the demo code to get a feeling for how they might be setup.
+
+```js
+$.extend($.fn.wPaint.defaults, {
+ saveImg: null, // callback triggerd on image save
+ loadImgFg: null, // callback triggered on image fg
+ loadImgBg: null // callback triggerd on image bg
+});
+```
+
+
+## Examples
+
+To start, you will need to include any dependencies (the paths and versions may differ):
+```html
+<!-- jQuery -->
+<script type="text/javascript" src="./lib/jquery.1.10.2.min.js"></script>
+<!-- jQuery UI -->
+<script type="text/javascript" src="./lib/jquery.ui.core.1.10.3.min.js"></script>
+<script type="text/javascript" src="./lib/jquery.ui.widget.1.10.3.min.js"></script>
+<script type="text/javascript" src="./lib/jquery.ui.mouse.1.10.3.min.js"></script>
+<script type="text/javascript" src="./lib/jquery.ui.draggable.1.10.3.min.js"></script>
+<!-- wColorPicker -->
+<link rel="Stylesheet" type="text/css" href="./lib/wColorPicker.min.css" />
+<script type="text/javascript" src="./lib/wColorPicker.min.js"></script>
+```
+
+
+
+Then you need to include the wPaint core files:
+```html
+<link rel="Stylesheet" type="text/css" href="./wPaint.min.css" />
+<script type="text/javascript" src="./wPaint.min.js"></script>
+```
+
+From here we will need to include plugin files for whatever menu icons we would like to support. This can include the plugins provided with the release of this plugin or any additional plugins that you can write on your own.
+
+```html
+<script type="text/javascript" src="./plugins/main/wPaint.menu.main.min.js"></script>
+<script type="text/javascript" src="./plugins/text/wPaint.menu.text.min.js"></script>
+<script type="text/javascript" src="./plugins/shapes/wPaint.menu.main.shapes.min.js"></script>
+<script type="text/javascript" src="./plugins/file/wPaint.menu.main.file.min.js"></script>
+```
+
+
+### path
+
+If you are putting wPaint into a path other than root (most likely you will) then you will need to set the `path` option since the image and cursor icon paths are set in the JavaScript and not in CSS. This means we can not make them relative from the included file like we can in the CSS file but rather relative to the dispalying page. The default path is just the root folder `/` but a path can be set for wpaint.
+
+```js
+$('#wPaint').wPaint({
+ path: '/js/lib/wPaint/'
+});
+```
+
+
+### save / load
+
+There have been many questions regarding saving / loading images using wPaint. Loading images CANNOT be done locally or from other domains due to browser restrictions with [cross origin](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript) policies. There are some potential workarounds for this using [CORS](https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image?redirectlocale=en-US&redirectslug=CORS_Enabled_Image) but this has not been implemented yet.
+
+As it stands the best approach to this is to first upload the image to your server, save it, then use the url from your server to set images in the future. You can check the `upload.php` file in the `test` folder with a php example for saving an image. However note that saving the image on your server will depend on the language/framework being used.
+
+
+### themes
+
+With this release multiple themeing has been introduced by simply space separating multiple theme keywords. For example 'standard classic'. This is to allow us to theme colours and sizes separately and use them interchangeably.
+
+```js
+$("#elem").wPaint({
+ theme: 'standard classic'
+});
+```
+
+
+### image data
+
+Set image on the fly. This can be a base64 encoded image or simply a path to any image on the same domain.
+
+```js
+$('#wPaint').wPaint('image', '<image_data>');
+```
+
+Get the image data:
+
+```js
+var imageData = $("#wPaint").wPaint("image");
+
+$("#canvasImage").attr('src', imageData);
+```
+
+
+### callbacks
+
+There are three callbacks available for each drawing operation of `down`, `move`, and `up`. Available is the `this` object which refers to the `wPaint` object and gives access to all internal functions.
+
+```js
+$("#elem").wPaint({
+ onDrawDown: function (e) {
+ console.log(this.settings.mode + ": " + e.pageX + ',' + e.pageY);
+ },
+ onDrawMove: function (e) {
+ console.log(this.settings.mode + ": " + e.pageX + ',' + e.pageY);
+ },
+ onDrawUp: function (e) {
+ console.log(this.settings.mode + ": " + e.pageX + ',' + e.pageY);
+ }
+});
+```
+
+
+### image / bg
+
+Set the image or background with an image or color at any time.
+
+```js
+$("#wPaint").wPaint({
+ image: './some/path/imagepreload.png',
+ bg: '#ff0000'
+});
+```
+
+
+### resize
+
+In case you want to resize your canvas there is a `resize` utility function available. Call this after you change the dimensions of your canvas element. Check the `test/fullscreen.html` demo for sample code.
+
+```js
+$("#wPaint").wPaint('resize');
+```
+
+
+### clear
+
+Clear the canvas manually.
+
+```javascript
+$('#wPaint').wPaint('clear');
+```
+
+
+### undo / redo
+
+We can also manually run an `undo` or `redo`.
+
+```javascript
+$('#wPaint').wPaint('undo');
+$('#wPaint').wPaint('redo');
+```
+
+
+## Extending
+
+With version 2.0 wPaint can now easily be extended by setting all or some of the following properties:
+
+```js
+// add menu
+$.fn.wPaint.menus.main = {
+ img: '/plugins/main/img/icons-menu-main.png',
+ items: {
+ undo: {
+ icon: 'generic',
+ title: 'Undo',
+ index: 0,
+ callback: function () { this.undo(); }
+ }
+}
+
+// extend cursors
+$.extend($.fn.wPaint.cursors, {
+ pencil: 'url("/plugins/main/img/cursor-pencil.png") 0 11.99, default',
+});
+
+// extend defaults
+$.extend($.fn.wPaint.defaults, {
+ mode: 'pencil', // set mode
+ lineWidth: '3', // starting line width
+ fillStyle: '#FFFFFF', // starting fill style
+ strokeStyle: '#FFFF00' // start stroke style
+});
+
+// extend functions
+$.fn.wPaint.extend({
+ undo: function () {
+ if (this.undoArray[this.undoCurrent - 1]) {
+ this._setUndo(--this.undoCurrent);
+ }
+
+ this._undoToggleIcons();
+ }
+});
+```
+
+
+### overriding
+
+When calling the `$.fn.wPaint.extend()` function the values for functions will not override the existing functions but just extend them with duck punching technique. This means the original funciton will always run followed by your extended function.
+
+This allows us to just string multiple `generate` or `init` functions together and not have to worry about overwriting any code.
+
+
+
+### menus
+
+The first menu appended will always automatically become the `primary` menu meaning it is the one displayed on init. All other menus will become `secondary` menus meaning they are toggled by icons.
+
+We can extend, modify or add items in the menu by updating the object we want. So for instance if we want to add a new icon to the main menu we could just do:
+
+```js
+$.fn.wPaint.menus.main.items.undo = {
+ // set properties here
+};
+```
+
+Likewise we can overwrite or add properties to an existing object. For instance below we modified the title and added the `after` property to change the position in which the `undo` icon will appear in the menu.
+
+```js
+$.fn.wPaint.menus.main.items.undo = {
+ title: 'Undo at your own risk',
+ after: 'clear'
+};
+```
+
+
+### icon properties
+
+Below is just a sample to list all possible icon properties. Note that the icon name such as `undo` is the `key` name used for CSS styling and internal naming.
+
+```js
+undo: {
+
+ // The icon sets the type of icon we want to generate
+ // below are the available types that come out of the box.
+ //
+ // generic: just runs a callback and nothing else
+ // activate: runs callback and activates (highlights)
+ // colorPicker: generates a color picker
+ // select: generates a select box (list)
+ // toggle: toggles on/off returns true or false
+ // menu: toggles secondary menu (icon/menu name must match)
+ icon: 'generic',
+
+ // Set a group for an icon turning it into a stacked
+ // group select (list). All icons with this group name will
+ // be appended to that select list. If not set the icon will
+ // just be standalone.
+ group: null,
+
+ // Set placement of icon in reference to another icon
+ after: 'clear',
+
+ // Title displayed on hover.
+ title: 'Undo',
+
+ // set an alternate image path to use for this icon
+ img: '/som/path.png',
+
+ // Index position in image file starting from 0
+ index: 0,
+
+ // a range of values to use for a select icon
+ range: [1, 2, 3, 4, 5],
+
+ // User range will set the value of the range as the
+ // css property based on the name of the icon. For instance
+ // if the icon is fontFamily that css property will get set.
+ useRange: true,
+
+ // The default value to set for this icon. This of course
+ // can be overridden using `set` calls on init.
+ value: 3,
+
+ // Callback when icon is clicked.
+ callback: function () { this.undo(); }
+}
+```
+
+If you want to create a new icon type you will need to extend wPaint to include processing for this new icon. A funciton in the form below should be written:
+
+```js
+_createIconType: function (item) {
+
+ // Get your started with a base icon.
+ var $icon = this._createIconBase(item);
+
+ // Return the icon with whatever functionality
+ // you want to add to it.
+ return $icon;
+}
+```
+
+
+### icon images
+
+Images for each plugin should be kept in one file and can be either specificed by the `img` value on the top level and can be overriden at the icon level. Each icon should also specify an index value as to the position of the icon in the image starting from 0. Icons should alll be the same size and dimensions should be set in the `size` theme.
+
+```js
+$.fn.wPaint.menus.main.items.undo = {
+ img: '/plugins/main/img/icons-menu-main.png',
+ items: {
+ undo: {
+ icon: 'generic',
+ title: 'Undo',
+ img: '/some/other/path.png'
+ index: 0,
+ callback: function () { this.undo(); }
+ }
+}
+```
+
+
+### cursors
+
+There is now a master `cursors` object used to store cursor references.
+
+$.extend($.fn.wPaint.cursors, {
+ pencil: 'url("/plugins/main/img/cursor-pencil.png") 0 11.99, default',
+});
+
+We can sepcify the cursor to use by calling `setCursor()` and passing the cursor name to use. Note that this is a set function and we can set the cursor at any time.
+
+```js
+$('#wPaint').wPaint('cursor', 'rocket');
+```
+
+Note that when you are setting the position of the cursor never set it to the exact dimension. For instance if the iamge is `12x12` and you want it's position to be `12` set it to `11.99`. This is do to some strange bug in Chrome which will not position the curosr if set exactly.
+
+
+## Thanks
+
+Thanks to everyone who has contribute code in the previous version and has showed interest in the plugin. Below is some thanks and attribution for code used in this plugin (if I left you out please let me know).
+
+* [Rounded corners and extending Canvas with new shapes](http://js-bits.blogspot.com/2010/07/canvas-rounded-corner-rectangles.html)
+* [Nice efficient algorithm for fill tool](http://www.williammalone.com/articles/html5-canvas-javascript-paint-bucket-tool)
+
+
+## Resources
+
+* [More jQuery plugins by Websanova](http://websanova.com/plugins)
+* [Websanova JavaScript Extensions Project](http://websanova.com/extensions)
+* [jQuery Plugin Development Boilerplate](http://wboiler.websanova.com)
+* [The Ultimate Guide to Writing jQuery Plugins](http://www.websanova.com/blog/jquery/the-ultimate-guide-to-writing-jquery-plugins)
+
+
+## License
+
+MIT licensed
+
+Copyright (C) 2011-2012 Websanova http://www.websanova.com
diff --git a/static/js/wpaint/bai.js b/static/js/wpaint/bai.js
new file mode 100644
index 0000000..6b436c1
--- /dev/null
+++ b/static/js/wpaint/bai.js
@@ -0,0 +1,23 @@
+function saveImg(image) {
+ var _this = this;
+ var url = document.getElementById('finish').href;
+
+ $.ajax({
+ type: 'POST',
+ url: '/oek_temp/upload.php',
+ data: {image: image},
+ success: function (resp) {
+ _this._displayStatus('Image saved successfully');
+ window.location.href = url;
+ }
+ });
+}
+
+$('#wPaint').wPaint({
+ path: '/static/js/wpaint/',
+ bg: '#ffffff',
+ menuOffsetLeft: -35,
+ menuOffsetTop: -50,
+ menuOrientation: 'horizontal',
+ saveImg: saveImg
+}); \ No newline at end of file
diff --git a/static/js/wpaint/demo/demo.css b/static/js/wpaint/demo/demo.css
new file mode 100644
index 0000000..ad8a418
--- /dev/null
+++ b/static/js/wpaint/demo/demo.css
@@ -0,0 +1,266 @@
+/*** layout ***/
+
+body, html {
+ font-family: verdana;
+ font-size: 12px;
+ line-height:20px;
+ color: #333;
+ background-color: #FEFEFE;
+ margin: 0;
+ text-rendering: optimizeLegibility;
+}
+a {
+ color: #3399FF;
+ text-decoration: none;
+}
+code {
+ padding: 1px 3px;
+ color: #D14;
+ background-color: #F7F7F9;
+ border: 1px solid #E1E1E8;
+ border-radius: 5px;
+}
+
+h2 {
+ display: inline-block;
+}
+
+.no-margin-top {
+ margin-top: 0px;
+}
+
+/*** header ***/
+
+header {
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ width: 100%;
+ height: 40px;
+ line-height: 40px;
+ background-color: #1B1B1B;
+ background-image: linear-gradient(to bottom, #222222, #111111);
+ background-repeat: repeat-x;
+ border-color: #252525;
+ box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
+ border-width: 0 0 1px;
+ color: #FFF;
+ font-size: 10px;
+ text-align: left;
+ vertical-align: middle;
+ z-index: 100;
+}
+#header-logo {
+ position: absolute;
+ display: block;
+ width: 94px;
+ height: 20px;
+ left: 10px;
+ top: 10px;
+ background-image: url('./img/websanova-logo-small-full-black.png');
+}
+#header-links {
+ display: none;
+ position: absolute;
+ width: 100%;
+ left: 0px;
+ top: 40px;
+}
+#header-links a {
+ display: block;
+ font-size: 9px;
+ font-weight: bold;
+ font-family: Verdana;
+ color: #FAFAFA;
+ text-transform: uppercase;
+ margin-left: 0px;
+ text-align: center;
+ background-color: #1B1B1B;
+ border-top: solid 1px #CACACA;
+ line-height: 14px;
+ padding: 10px;
+}
+#header-links a:hover {
+ color: #636363;
+}
+
+/*** menu ***/
+
+#header-menu-button {
+ position: absolute;
+ right: 6px;
+ top: 6px;
+ display: block;
+ color: #757575;
+ background-color: #e1e1e1;
+ background-repeat: repeat-x;
+ background-image: -moz-linear-gradient(top, #ebebeb, #e1e1e1);
+ background-image: -ms-linear-gradient(top, #ebebeb, #e1e1e1);
+ background-image: -webkit-linear-gradient(top, #ebebeb, #e1e1e1);
+ background-image: -o-linear-gradient(top, #ebebeb, #e1e1e1);
+ background-image: linear-gradient(top, #ebebeb, #e1e1e1);
+ box-shadow: inset 0 0 8px 2px #c6c6c6, 0 1px 0 0 #f4f4f4;
+ border: none;
+ border-radius: 3px;
+ -webkit-border-radius: 3px;
+ padding: 6px 10px;
+ font-size: 11px;
+ line-height: 16px;
+ cursor: pointer;
+}
+
+/*** content ***/
+
+#plugin-name {
+ padding-bottom: 30px;
+ font-size: 24px;
+ border-bottom: solid #CACACA 1px;
+}
+#github-button {
+ display: block;
+ float: left;
+ margin-right: 2px;
+ width: 16px;
+ height: 16px;
+ cursor: pointer;
+ background-image: url('./img/addthis-github.png');
+}
+#addthis-toolbox {
+ position: absolute;
+ right: 15px;
+ top: 40px;
+}
+#content {
+ position: relative;
+ background: #FEFEFE;
+ max-width: 728px;
+ padding: 20px;
+ margin: 30px auto;
+}
+.content-box {
+ padding-left: 10px;
+}
+#content ul {
+ padding-left: 30px;
+}
+/*** footer ***/
+
+footer {
+ position: fixed;
+ left: 0px;
+ bottom: -1px;
+ width: 100%;
+ height: 40px;
+ line-height: 40px;
+ background-color: #1B1B1B;
+ background-image: linear-gradient(to bottom, #222222, #111111);
+ background-repeat: repeat-x;
+ border-color: #252525;
+ box-shadow: 10px 1px 10px rgba(0, 0, 0, 0.5);
+ border-width: 0 0 1px;
+ color: #FFF;
+ font-size: 10px;
+ text-align: left;
+ vertical-align: middle;
+ z-index: 100;
+}
+#footer-icons {
+ position: absolute;
+ right: 10px;
+ top: 0px;
+}
+#footer-icons a {
+ display: inline-block;
+ *display: inline;
+ zoom: 1;
+ width: 17px;
+ height: 17px;
+ margin: 12px 0 0 10px;
+ background-repeat: no-repeat;
+ background-position: center center;
+}
+#linkedin-icon { background-image: url('./img/linkedin-icon.png'); width: 18px; }
+#stumbleupon-icon { background-image: url('./img/stumbleupon-icon.png'); }
+#googleplus-icon { background-image: url('./img/googleplus-icon.png'); }
+#youtube-icon { background-image: url('./img/youtube-icon.png'); width: 17px; height: 18px; }
+#facebook-icon { background-image: url('./img/facebook-icon.png'); width: 8px; }
+#twitter-icon { background-image: url('./img/twitter-icon.png'); width: 20px; }
+#github-icon { background-image: url('./img/github-icon.png'); width: 20px; }
+#rss-icon { background-image: url('./img/rss-icon.png'); }
+
+
+/*** media ***/
+
+@media screen and (min-width: 600px) {
+ #header-logo {
+ left: 50px;
+ }
+ #footer-icons {
+ left: auto;
+ right: 50px;
+ }
+ #header-links {
+ display: block !important;
+ width: auto;
+ top: 0px;
+ left: auto;
+ right: 50px;
+ }
+ #header-links a {
+ display: inline;
+ font-size: 10px;
+ margin-left: 20px;
+ text-align: left;
+ background-color: none;
+ border-top: 0px;
+ margin-left: 10px;
+ line-height: inherit;
+ padding: 0px;
+ }
+ #header-menu-button {
+ display: none;
+ }
+ #plugin-name {
+ font-size: 30px;
+ }
+ #addthis-toolbox {
+ top: 44px;
+ }
+}
+
+/*** ads ***/
+
+.websanova-plugins-page-horizontal-responsive { display:block; margin:0 auto; width: 320px; height: 50px; }
+@media(min-width: 520px) { .websanova-plugins-page-horizontal-responsive { width: 468px; height: 60px; } }
+@media(min-width: 800px) { .websanova-plugins-page-horizontal-responsive { width: 728px; height: 90px; } }
+
+.adsblock {
+ position: relative;
+ margin: 0 auto;
+}
+.ads2block {
+ margin-top: 20px;
+}
+.adsblock-mobile-banner {
+ width: 320px;
+ height: 50px;
+}
+.adsblock-banner {
+ display: none;
+ width: 468px;
+ height: 60px;
+}
+.adsblock-leaderboard {
+ display: none;
+ width: 728px;
+ height: 90px;
+}
+@media (min-width:520px) {
+ .adsblock-mobile-banner { display: none; }
+ .adsblock-banner { display: block; }
+}
+@media (min-width:800px) {
+ .adsblock-mobile-banner { display: none; }
+ .adsblock-banner { display: none; }
+ .adsblock-leaderboard { display: block; }
+} \ No newline at end of file
diff --git a/static/js/wpaint/demo/img/facebook-icon.png b/static/js/wpaint/demo/img/facebook-icon.png
new file mode 100644
index 0000000..dfb0f3e
--- /dev/null
+++ b/static/js/wpaint/demo/img/facebook-icon.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/favicon.ico b/static/js/wpaint/demo/img/favicon.ico
new file mode 100644
index 0000000..9bd6326
--- /dev/null
+++ b/static/js/wpaint/demo/img/favicon.ico
Binary files differ
diff --git a/static/js/wpaint/demo/img/forkme_right_darkblue.png b/static/js/wpaint/demo/img/forkme_right_darkblue.png
new file mode 100644
index 0000000..146ef8a
--- /dev/null
+++ b/static/js/wpaint/demo/img/forkme_right_darkblue.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/github-icon.png b/static/js/wpaint/demo/img/github-icon.png
new file mode 100644
index 0000000..a28067c
--- /dev/null
+++ b/static/js/wpaint/demo/img/github-icon.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/googleplus-icon.png b/static/js/wpaint/demo/img/googleplus-icon.png
new file mode 100644
index 0000000..6567f6e
--- /dev/null
+++ b/static/js/wpaint/demo/img/googleplus-icon.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/linkedin-icon.png b/static/js/wpaint/demo/img/linkedin-icon.png
new file mode 100644
index 0000000..a2628e7
--- /dev/null
+++ b/static/js/wpaint/demo/img/linkedin-icon.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/rss-icon.png b/static/js/wpaint/demo/img/rss-icon.png
new file mode 100644
index 0000000..faae141
--- /dev/null
+++ b/static/js/wpaint/demo/img/rss-icon.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/stumbleupon-icon.png b/static/js/wpaint/demo/img/stumbleupon-icon.png
new file mode 100644
index 0000000..5e82ea8
--- /dev/null
+++ b/static/js/wpaint/demo/img/stumbleupon-icon.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/twitter-icon.png b/static/js/wpaint/demo/img/twitter-icon.png
new file mode 100644
index 0000000..499ca0c
--- /dev/null
+++ b/static/js/wpaint/demo/img/twitter-icon.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/websanova-logo-small-full-black.png b/static/js/wpaint/demo/img/websanova-logo-small-full-black.png
new file mode 100644
index 0000000..a5bd0f6
--- /dev/null
+++ b/static/js/wpaint/demo/img/websanova-logo-small-full-black.png
Binary files differ
diff --git a/static/js/wpaint/demo/img/youtube-icon.png b/static/js/wpaint/demo/img/youtube-icon.png
new file mode 100644
index 0000000..e697406
--- /dev/null
+++ b/static/js/wpaint/demo/img/youtube-icon.png
Binary files differ
diff --git a/static/js/wpaint/gruntfile.js b/static/js/wpaint/gruntfile.js
new file mode 100644
index 0000000..4e1eb06
--- /dev/null
+++ b/static/js/wpaint/gruntfile.js
@@ -0,0 +1,90 @@
+module.exports = function(grunt) {
+ grunt.initConfig({
+ pkg: grunt.file.readJSON('package.json'),
+ jshint: {
+ options: {
+ bitwise: true,
+ camelcase: true,
+ indent: 2,
+ curly: true,
+ eqeqeq: true,
+ immed: true,
+ latedef: true,
+ newcap: true,
+ noarg: true,
+ sub: true,
+ undef: true,
+ unused: true,
+ boss: true,
+ eqnull: true,
+ white: true,
+ validthis: true,
+ quotmark: 'single',
+ globals: {
+ 'window': true,
+ 'jQuery': true,
+ 'document': true,
+ 'Image': true,
+ 'setTimeout': true,
+ 'clearTimeout': true,
+ 'event': true,
+ 'CanvasRenderingContext2D': true
+ }
+ },
+ files: {
+ src: ['./plugins/**/src/wPaint-*.js', './src/*.js']
+ }
+ },
+ uglify: {
+ options: {
+ banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> */'
+ },
+ my_target: {
+ files: {
+ './wPaint.min.js': ['./src/wPaint.js', './src/wPaint.utils.js'],
+ './plugins/main/wPaint.menu.main.min.js': ['./plugins/main/src/wPaint.menu.main.js', './plugins/main/src/fillArea.min.js'],
+ './plugins/text/wPaint.menu.text.min.js': ['./plugins/text/src/wPaint.menu.text.js'],
+ './plugins/shapes/wPaint.menu.main.shapes.min.js': ['./plugins/shapes/src/wPaint.menu.main.shapes.js', './plugins/shapes/src/shapes.min.js'],
+ './plugins/file/wPaint.menu.main.file.min.js': ['./plugins/file/src/wPaint.menu.main.file.js']
+ }
+ }
+ },
+ stylus: {
+ compile: {
+ options: {
+ import: ['nib', '../lib/mixins'],
+ },
+ files: {
+ './wPaint.min.css': './src/wPaint.css'
+ }
+ }
+ },
+ concat: {
+ basic_and_extras: {
+ files: {
+ 'wPaint-min.js': ['./lib/wColorPicker.min.js', './wPaint.min.js'],
+ 'wPaint-min.css': ['./lib/wColorPicker.min.css', './wPaint.min.css'],
+ },
+ }
+ },
+ watch: {
+ files: [
+ './src/wPaint.css',
+ './src/wPaint.js',
+ './plugins/file/src/wPaint.menu.main.js',
+ './plugins/file/src/wPaint.menu.text.js',
+ './plugins/file/src/wPaint.menu.main.shapes.js',
+ './plugins/file/src/wPaint.menu.main.file.js'
+ ],
+ tasks: ['uglify']
+ }
+ });
+
+ grunt.loadNpmTasks('grunt-contrib-watch');
+ grunt.loadNpmTasks('grunt-contrib-stylus');
+ grunt.loadNpmTasks('grunt-contrib-jshint');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
+ grunt.loadNpmTasks('grunt-contrib-concat');
+
+ grunt.registerTask('default', ['jshint', 'stylus', 'uglify']);
+}; \ No newline at end of file
diff --git a/static/js/wpaint/index.html b/static/js/wpaint/index.html
new file mode 100644
index 0000000..391261e
--- /dev/null
+++ b/static/js/wpaint/index.html
@@ -0,0 +1,136 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width" />
+
+ <title>Websanova :: wPaint</title>
+
+ <!-- filestart -->
+ <link rel="icon" type="image/vnd.microsoft.icon" href="./demo/img/favicon.ico" />
+ <link rel="Stylesheet" type="text/css" href="./demo/demo.css" />
+ <script type="text/javascript" src="./lib/jquery.1.10.2.min.js"></script>
+ <!-- fileend -->
+</head>
+<body>
+ <!-- headstart -->
+ <header>
+ <a id="header-logo" href="http://websanova.com"></a>
+
+ <div id="header-links">
+ <a href="http://websanova.com">Blog</a>
+ <a href="http://websanova.com/plugins">Plugins</a>
+ <a href="http://websanova.com/extensions">Extensions</a>
+ <a href="http://websanova.com/services">Services</a>
+ </div>
+ </header>
+ <!-- headend -->
+
+ <div id="content">
+ <h1 id="plugin-name">wPaint.js</h1>
+
+ <div class="content-box">
+ <!-- jQuery UI -->
+ <script type="text/javascript" src="./lib/jquery.ui.core.1.10.3.min.js"></script>
+ <script type="text/javascript" src="./lib/jquery.ui.widget.1.10.3.min.js"></script>
+ <script type="text/javascript" src="./lib/jquery.ui.mouse.1.10.3.min.js"></script>
+ <script type="text/javascript" src="./lib/jquery.ui.draggable.1.10.3.min.js"></script>
+
+ <!-- wColorPicker -->
+ <link rel="Stylesheet" type="text/css" href="./lib/wColorPicker.min.css" />
+ <script type="text/javascript" src="./lib/wColorPicker.min.js"></script>
+
+ <!-- wPaint -->
+ <link rel="Stylesheet" type="text/css" href="./wPaint.min.css" />
+ <script type="text/javascript" src="./wPaint.min.js"></script>
+ <script type="text/javascript" src="./plugins/main/wPaint.menu.main.min.js"></script>
+ <script type="text/javascript" src="./plugins/text/wPaint.menu.text.min.js"></script>
+ <script type="text/javascript" src="./plugins/shapes/wPaint.menu.main.shapes.min.js"></script>
+ <script type="text/javascript" src="./plugins/file/wPaint.menu.main.file.min.js"></script>
+
+ <div id="wPaint" style="position:relative; width:500px; height:200px; background-color:#7a7a7a; margin:70px auto 20px auto;"></div>
+
+ <center style="margin-bottom: 50px;">
+ <input type="button" value="toggle menu" onclick="console.log($('#wPaint').wPaint('menuOrientation')); $('#wPaint').wPaint('menuOrientation', $('#wPaint').wPaint('menuOrientation') === 'vertical' ? 'horizontal' : 'vertical');"/>
+ </center>
+
+ <center id="wPaint-img"></center>
+
+ <script type="text/javascript">
+ var images = [
+ '/test/uploads/wPaint.png',
+ ];
+
+ function saveImg(image) {
+ var _this = this;
+
+ $.ajax({
+ type: 'POST',
+ url: '/test/upload.php',
+ data: {image: image},
+ success: function (resp) {
+
+ // internal function for displaying status messages in the canvas
+ _this._displayStatus('Image saved successfully');
+
+ // doesn't have to be json, can be anything
+ // returned from server after upload as long
+ // as it contains the path to the image url
+ // or a base64 encoded png, either will work
+ resp = $.parseJSON(resp);
+
+ // update images array / object or whatever
+ // is being used to keep track of the images
+ // can store path or base64 here (but path is better since it's much smaller)
+ images.push(resp.img);
+
+ // do something with the image
+ $('#wPaint-img').attr('src', image);
+ }
+ });
+ }
+
+ function loadImgBg () {
+
+ // internal function for displaying background images modal
+ // where images is an array of images (base64 or url path)
+ // NOTE: that if you can't see the bg image changing it's probably
+ // becasue the foregroud image is not transparent.
+ this._showFileModal('bg', images);
+ }
+
+ function loadImgFg () {
+
+ // internal function for displaying foreground images modal
+ // where images is an array of images (base64 or url path)
+ this._showFileModal('fg', images);
+ }
+
+ // init wPaint
+ $('#wPaint').wPaint({
+ menuOffsetLeft: -35,
+ menuOffsetTop: -50,
+ saveImg: saveImg,
+ loadImgBg: loadImgBg,
+ loadImgFg: loadImgFg
+ });
+ </script>
+ </div>
+ </div>
+
+ <!-- footstart -->
+ <footer>
+ <div id="footer-icons">
+ <!--a id="youtube-icon" href="http://websanova.com/youtube" target="_blank"></a-->
+ <a id="stumbleupon-icon" href="http://websanova.com/stumbleupon" target="_blank"></a>
+ <a id="linkedin-icon" href="http://websanova.com/linkedin" target="_blank"></a>
+ <a id="facebook-icon" href="http://websanova.com/facebook" target="_blank"></a>
+ <a id="googleplus-icon" href="http://websanova.com/googleplus" target="_blank"></a>
+ <a id="twitter-icon" href="http://websanova.com/twitter" target="_blank"></a>
+ <a id="github-icon" href="http://websanova.com/github" target="_blank"></a>
+ <a id="rss-icon" href="http://websanova.com/feed" target="_blank"></a>
+ </div>
+ </footer>
+ <!-- footend -->
+</body>
+</html> \ No newline at end of file
diff --git a/static/js/wpaint/lib/jquery.1.10.2.min.js b/static/js/wpaint/lib/jquery.1.10.2.min.js
new file mode 100644
index 0000000..76d21a4
--- /dev/null
+++ b/static/js/wpaint/lib/jquery.1.10.2.min.js
@@ -0,0 +1,6 @@
+/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery-1.10.2.min.map
+*/
+(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav></:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t
+}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Ct=/^(?:checkbox|radio)$/i,Nt=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle);
+u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],"display");return n.remove(),r}x.each(["height","width"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,"display"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===x.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each(["top","left"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+"px":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||x.css(e,"display"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:"",padding:"",border:"Width"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,"elements");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==x.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}x.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var mn,yn,vn=x.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=o.href}catch(Ln){yn=a.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return"string"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o["*"]&&s("*")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(" ");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&x.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?x("<div>").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":x.parseJSON,"text xml":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks("once memory"),m=p.statusCode||{},y={},v={},b=0,w="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||"*").toLowerCase().match(T)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?"80":"443"))===(mn[3]||("http:"===mn[1]?"80":"443")))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader("If-Modified-Since",x.lastModified[o]),x.etag[o]&&C.setRequestHeader("If-None-Match",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",p.contentType),C.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w="abort";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger("ajaxSend",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort("timeout")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||"",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader("Last-Modified"),T&&(x.lastModified[o]=T),T=C.getResponseHeader("etag"),T&&(x.etag[o]=T)),204===e||"HEAD"===p.type?N="nocontent":304===e?N="notmodified":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N="error",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+"",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?"ajaxSuccess":"ajaxError",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger("ajaxComplete",[C,p]),--x.active||x.event.trigger("ajaxStop")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,"json")},getScript:function(e,n){return x.get(e,t,n,"script")}}),x.each(["get","post"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+" "+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(a=u[l+" "+o]||u["* "+o],!a)for(i in u)if(s=i.split(" "),s[1]===o&&(a=u[l+" "+s[0]]||u["* "+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(p){return{state:"parsererror",error:a?p:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}x.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),x.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=a.head||x("head")[0]||a.documentElement;return{send:function(t,i){n=a.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\?(?=&|$)|\?\?/;x.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Fn.pop()||x.expando+"_"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return l||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||x.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&"withCredentials"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),"string"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+w+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?"":"px"),a=(x.cssNumber[e]||"px"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||".5",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn["*"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,"fxshow");n.queue||(s=x._queueHooks(e,"fx"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,"fx").length||s.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],"inline"===x.css(e,"display")&&"none"===x.css(e,"float")&&(x.support.inlineBlockNeedsLayout&&"inline"!==ln(e.nodeName)?p.zoom=1:p.display="inline-block")),n.overflow&&(p.overflow="hidden",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(f?"hide":"show"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?"hidden"in d&&(f=d.hidden):d=x._data(e,"fxshow",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,"fxshow");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each(["toggle","show","hide"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=x._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&"object"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,"position");"static"===r&&(e.style.position="relative");var i=x(e),o=i.offset(),a=x.css(e,"top"),s=x.css(e,"left"),l=("absolute"===r||"fixed"===r)&&x.inArray("auto",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),"using"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===x.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],"html")||(n=e.offset()),n.top+=x.css(e[0],"borderTopWidth",!0),n.left+=x.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-x.css(r,"marginTop",!0),left:t.left-n.left-x.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,"html")&&"static"===x.css(e,"position"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:"height",Width:"width"},function(e,n){x.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,"function"==typeof define&&define.amd&&define("jquery",[],function(){return x}))})(window); \ No newline at end of file
diff --git a/static/js/wpaint/lib/jquery.ui.core.1.10.3.min.js b/static/js/wpaint/lib/jquery.ui.core.1.10.3.min.js
new file mode 100644
index 0000000..bf1129a
--- /dev/null
+++ b/static/js/wpaint/lib/jquery.ui.core.1.10.3.min.js
@@ -0,0 +1,4 @@
+/*! jQuery UI - v1.10.3 - 2013-06-12
+* http://jqueryui.com
+* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
+(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/lib/jquery.ui.draggable.1.10.3.min.js b/static/js/wpaint/lib/jquery.ui.draggable.1.10.3.min.js
new file mode 100644
index 0000000..3b7b149
--- /dev/null
+++ b/static/js/wpaint/lib/jquery.ui.draggable.1.10.3.min.js
@@ -0,0 +1,4 @@
+/*! jQuery UI - v1.10.3 - 2013-06-12
+* http://jqueryui.com
+* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
+(function(e){e.widget("ui.draggable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var i=this.options;return this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){e("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||e.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1):!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,e(document).width()-this.helperProportions.width-this.margins.left,(e(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(t){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=t.pageX,l=t.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s]),"drag"===t&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i){var s=e(this).data("ui-draggable"),n=s.options,a=e.extend({},i,{item:s.element});s.sortables=[],e(n.connectToSortable).each(function(){var i=e.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",t,a))})},stop:function(t,i){var s=e(this).data("ui-draggable"),n=e.extend({},i,{item:s.element});e.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,n))})},drag:function(t,i){var s=e(this).data("ui-draggable"),n=this;e.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,e.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",t),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",t),s.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(){var t=e("body"),i=e(this).data("ui-draggable").options;t.css("cursor")&&(i._cursor=t.css("cursor")),t.css("cursor",i.cursor)},stop:function(){var t=e(this).data("ui-draggable").options;t._cursor&&e("body").css("cursor",t._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._opacity&&e(i.helper).css("opacity",s._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(){var t=e(this).data("ui-draggable");t.scrollParent[0]!==document&&"HTML"!==t.scrollParent[0].tagName&&(t.overflowOffset=t.scrollParent.offset())},drag:function(t){var i=e(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-t.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:t.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-t.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:t.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(t.pageY-e(document).scrollTop()<s.scrollSensitivity?n=e(document).scrollTop(e(document).scrollTop()-s.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<s.scrollSensitivity&&(n=e(document).scrollTop(e(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(t.pageX-e(document).scrollLeft()<s.scrollSensitivity?n=e(document).scrollLeft(e(document).scrollLeft()-s.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<s.scrollSensitivity&&(n=e(document).scrollLeft(e(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&e.ui.ddmanager&&!s.dropBehaviour&&e.ui.ddmanager.prepareOffsets(i,t)}}),e.ui.plugin.add("draggable","snap",{start:function(){var t=e(this).data("ui-draggable"),i=t.options;t.snapElements=[],e(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=e(this),s=i.offset();this!==t.element[0]&&t.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(t,i){var s,n,a,o,r,h,l,u,c,d,p=e(this).data("ui-draggable"),f=p.options,m=f.snapTolerance,g=i.offset.left,v=g+p.helperProportions.width,b=i.offset.top,y=b+p.helperProportions.height;for(c=p.snapElements.length-1;c>=0;c--)r=p.snapElements[c].left,h=r+p.snapElements[c].width,l=p.snapElements[c].top,u=l+p.snapElements[c].height,r-m>v||g>h+m||l-m>y||b>u+m||!e.contains(p.snapElements[c].item.ownerDocument,p.snapElements[c].item)?(p.snapElements[c].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(s=m>=Math.abs(l-y),n=m>=Math.abs(u-b),a=m>=Math.abs(r-v),o=m>=Math.abs(h-g),s&&(i.position.top=p._convertPositionTo("relative",{top:l-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h}).left-p.margins.left)),d=s||n||a||o,"outer"!==f.snapMode&&(s=m>=Math.abs(l-b),n=m>=Math.abs(u-y),a=m>=Math.abs(r-g),o=m>=Math.abs(h-v),s&&(i.position.top=p._convertPositionTo("relative",{top:l,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[c].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=s||n||a||o||d)}}),e.ui.plugin.add("draggable","stack",{start:function(){var t,i=this.data("ui-draggable").options,s=e.makeArray(e(i.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});s.length&&(t=parseInt(e(s[0]).css("zIndex"),10)||0,e(s).each(function(i){e(this).css("zIndex",t+i)}),this.css("zIndex",t+s.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._zIndex&&e(i.helper).css("zIndex",s._zIndex)}})})(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/lib/jquery.ui.mouse.1.10.3.min.js b/static/js/wpaint/lib/jquery.ui.mouse.1.10.3.min.js
new file mode 100644
index 0000000..82e3367
--- /dev/null
+++ b/static/js/wpaint/lib/jquery.ui.mouse.1.10.3.min.js
@@ -0,0 +1,4 @@
+/*! jQuery UI - v1.10.3 - 2013-06-12
+* http://jqueryui.com
+* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
+(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/lib/jquery.ui.widget.1.10.3.min.js b/static/js/wpaint/lib/jquery.ui.widget.1.10.3.min.js
new file mode 100644
index 0000000..5f7a7c1
--- /dev/null
+++ b/static/js/wpaint/lib/jquery.ui.widget.1.10.3.min.js
@@ -0,0 +1,4 @@
+/*! jQuery UI - v1.10.3 - 2013-06-12
+* http://jqueryui.com
+* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
+(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/lib/mixins.styl b/static/js/wpaint/lib/mixins.styl
new file mode 100644
index 0000000..b92debe
--- /dev/null
+++ b/static/js/wpaint/lib/mixins.styl
@@ -0,0 +1,7 @@
+display(type)
+ if type == 'inline-block'
+ display: inline-block;
+ *display: inline;
+ zoom: 1;
+ else
+ display: type; \ No newline at end of file
diff --git a/static/js/wpaint/lib/wColorPicker.min.css b/static/js/wpaint/lib/wColorPicker.min.css
new file mode 100644
index 0000000..9c39b88
--- /dev/null
+++ b/static/js/wpaint/lib/wColorPicker.min.css
@@ -0,0 +1,42 @@
+.wColorPicker{position:relative;display:inline-block;*display:inline;zoom:1;line-height:0;font-size:0;cursor:default}
+.wColorPicker-bg{position:absolute;left:0;top:0;width:100%;height:100%}
+.wColorPicker-holder{position:relative;display:inline-block;*display:inline;zoom:1;overflow:hidden}
+.wColorPicker-palettes-holder{position:relative;display:inline-block;*display:inline;zoom:1}
+.wColorPicker-zindex{z-index:1000}
+.wColorPicker-palette{position:relative;display:inline-block;*display:inline;zoom:1;margin:0 10px 10px 0}
+.wColorPicker-palette-none,.wColorPicker-palette-simple{margin-left:10px}
+.wColorPicker-palette-color{display:inline-block;*display:inline;zoom:1;vertical-align:middle;width:10px;height:10px;border-right:solid 1px;border-bottom:solid 1px;cursor:pointer}
+.wColorPicker-palette-color-left{border-left:solid 1px}
+.wColorPicker-palette-color-top{border-top:solid 1px}
+.wColorPicker-color-target{position:relative;display:inline-block;*display:inline;zoom:1;vertical-align:middle;width:40px;height:16px;border:solid 1px}
+.wColorPicker-custom-input{position:relative;display:inline-block;*display:inline;zoom:1;vertical-align:middle;width:70px;height:16px;line-height:16px;font-size:9px;font-family:verdana;padding:0 2px;border:solid 1px}
+.wColorPicker-color-target,.wColorPicker-custom-input{margin:10px 10px 10px 0}
+.wColorPicker-dropper{position:relative;display:inline-block;*display:inline;zoom:1;vertical-align:middle;width:16px;height:16px;border:solid 1px;cursor:pointer}
+.wColorPicker-button{position:relative;-webkit-border-radius:5px;border-radius:5px;border:solid #cacaca 1px;padding:1px}
+.wColorPicker-button-color{position:relative;-webkit-border-radius:5px;border-radius:5px}
+.wColorPicker-holder{border:solid 1px}
+.wColorPicker-bg,.wColorPicker-holder{-webkit-border-radius:5px;border-radius:5px}
+.wColorPicker-bg{-webkit-box-shadow:inset 2px 2px 3px #fff,1px 1px 2px #555;box-shadow:inset 2px 2px 3px #fff,1px 1px 2px #555}
+.wColorPicker-custom-input{opacity:.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50)}
+.wColorPicker-dropper{opacity:.6;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";filter:alpha(opacity=60);-webkit-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 1px 1px 2px #fff,0 0 1px #777;box-shadow:inset 1px 1px 2px #fff,0 0 1px #777;background-color:#cacaca;background:no-repeat center center url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOC8wOS8xM9AohnYAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAA4ElEQVQokYXSMUpDARCE4e/FBCEggoVH0BtY2bsiiIWIipVHsLaOYCcWVtpYSBBEsNnO9qGFR/AKVhISNRa+SJDkudWw/DMwyxbD4dB/ExEnWMFBUWeIiAVs4RxtPDdr4DUcY7Va9fA01YAzLFd6gKPMvGhMSd/EKR6r1QsuofkHLLCDr8y8iohPLKKTmX34LR0RLeyij3uso4GHzByMQhtj8B56mdmt4HZm3o3DMFOWZYGogJuI2MZ8Zl5P6tfEHFroRsQ+ZjERHhkOK72Bd9xm5ked4RVLfk74lpm1v/INodZOOpic3qMAAAAASUVORK5CYII=")}
+.wColorPicker-theme-classic .wColorPicker-dropper,.wColorPicker-theme-classic .wColorPicker-custom-input,.wColorPicker-theme-classic .wColorPicker-color-target,.wColorPicker-theme-classic .wColorPicker-palette-color{border-color:#3a3a3a}
+.wColorPicker-theme-classic .wColorPicker-holder{border-color:#bababa}
+.wColorPicker-theme-classic .wColorPicker-bg{background-color:#aaa}
+.wColorPicker-theme-black .wColorPicker-dropper,.wColorPicker-theme-black .wColorPicker-color-target,.wColorPicker-theme-black .wColorPicker-color-input,.wColorPicker-theme-black .wColorPicker-palette-color{border-color:#3f3f3f}
+.wColorPicker-theme-black .wColorPicker-holder{border-color:#7f7f7f}
+.wColorPicker-theme-black .wColorPicker-bg{background-color:#363636}
+.wColorPicker-theme-blue .wColorPicker-dropper,.wColorPicker-theme-blue .wColorPicker-color-target,.wColorPicker-theme-blue .wColorPicker-color-input,.wColorPicker-theme-blue .wColorPicker-palette-color{border-color:#002f4d}
+.wColorPicker-theme-blue .wColorPicker-holder{border-color:#49afcd}
+.wColorPicker-theme-blue .wColorPicker-bg{background-color:#2f96b4}
+.wColorPicker-theme-red .wColorPicker-dropper,.wColorPicker-theme-red .wColorPicker-color-target,.wColorPicker-theme-red .wColorPicker-color-input,.wColorPicker-theme-red .wColorPicker-palette-color{border-color:#8a0f09}
+.wColorPicker-theme-red .wColorPicker-holder{border-color:#da4f49}
+.wColorPicker-theme-red .wColorPicker-bg{background-color:#bd362f}
+.wColorPicker-theme-green .wColorPicker-dropper,.wColorPicker-theme-green .wColorPicker-color-target,.wColorPicker-theme-green .wColorPicker-color-input,.wColorPicker-theme-green .wColorPicker-palette-color{border-color:#0b670b}
+.wColorPicker-theme-green .wColorPicker-holder{border-color:#5bb75b}
+.wColorPicker-theme-green .wColorPicker-bg{background-color:#51a351}
+.wColorPicker-theme-orange .wColorPicker-dropper,.wColorPicker-theme-orange .wColorPicker-color-target,.wColorPicker-theme-orange .wColorPicker-color-input,.wColorPicker-theme-orange .wColorPicker-palette-color{border-color:#9a5700}
+.wColorPicker-theme-orange .wColorPicker-holder{border-color:#faa732}
+.wColorPicker-theme-orange .wColorPicker-bg{background-color:#f89406}
+.wColorPicker-palette-color.active{border-color:#f00}
+.wColorPicker-palette-color.active-right{border-right-color:#f00}
+.wColorPicker-palette-color.active-bottom{border-bottom-color:#f00}
diff --git a/static/js/wpaint/lib/wColorPicker.min.js b/static/js/wpaint/lib/wColorPicker.min.js
new file mode 100644
index 0000000..cb515e6
--- /dev/null
+++ b/static/js/wpaint/lib/wColorPicker.min.js
@@ -0,0 +1,2 @@
+/*! rgbHex - v1.1.2 - 2013-09-27 */window.rgbHex=function(){function a(a){return!isNaN(parseFloat(a))&&isFinite(a)}function b(a){return a.replace(/^\s+|\s+$/g,"")}function c(c){return c=b(c),a(c)&&c>=0&&255>=c}function d(a){return/^[0-9a-f]{3}$|^[0-9a-f]{6}$/i.test(b(a))}function e(a){return a=parseInt(a,10).toString(16),1===a.length?"0"+a:a}function f(a){return parseInt(a,16).toString()}function g(b){return b=b.split(","),(3===b.length||4===b.length)&&c(b[0])&&c(b[1])&&c(b[2])?4!==b.length||a(b[3])?"#"+e(b[0]).toUpperCase()+e(b[1]).toUpperCase()+e(b[2]).toUpperCase():null:null}function h(a){return d(a)?(3===a.length&&(a=a.charAt(0)+a.charAt(0)+a.charAt(1)+a.charAt(1)+a.charAt(2)+a.charAt(2)),"rgb("+f(a.substr(0,2))+","+f(a.substr(2,2))+","+f(a.substr(4,2))+")"):void 0}function i(a){return a.replace(/\s/g,"")}return function(a){if(!a)return null;var c=null,d=/^rgba?\((.*)\);?$/,e=/^#/;return a=b(a.toString()),"transparent"===a||"rgba(0,0,0,0)"===i(a)?"transparent":d.test(a)?g(a.match(d)[1]):e.test(a)?h(a.split("#").reverse()[0]):(c=a.split(","),1===c.length?h(a):3===c.length||4===c.length?g(a):void 0)}}(),jQuery&&jQuery.extend({rgbHex:function(a){return window.rgbHex(a)}});
+/*! wColorPicker - v2.1.7 - 2013-09-27 */!function(a){function b(b,c){this.$el=a(b),this.options=c,this.init=!1,this.generate()}b.prototype={generate:function(){return this.$colorPicker||(this.$noneColorPalette=this._createPalette("none",[["transparent"]]),this.$simpleColorPalette=this._createPalette("simple",a.fn.wColorPicker.simpleColors),this.$mixedColorPalette=this._createPalette("mixed",a.fn.wColorPicker.mixedColors),this.$colorTarget=a('<div class="wColorPicker-color-target"></div>'),this.$customInput=a('<input type="text" class="wColorPicker-custom-input"/>').keyup(a.proxy(this._customInputKeyup,this)),this.options.dropperButton&&(this.$dropperButton=this._createDropperButton()),this.$colorPickerPalettesHolder=a('<div class="wColorPicker-palettes-holder"></div>').append(this.$noneColorPalette).append(this.$colorTarget).append(this.$customInput).append(this.$dropperButton).append("<br/>").append(this.$simpleColorPalette).append(this.$mixedColorPalette),this.$colorPickerHolder=a('<div class="wColorPicker-holder"></div>').append(this.$colorPickerPalettesHolder),this.$colorPickerBg=a('<div class="wColorPicker-bg"></div>'),this.$colorPicker=a('<div class="wColorPicker" title=""></div>').mouseenter(function(a){a.stopPropagation()}).bind("mouseenter mousemove click",function(a){a.stopPropagation()}).append(this.$colorPickerBg).append(this.$colorPickerHolder),this.setOpacity(this.options.opacity),this.setTheme(this.options.theme),this.setColor(this.options.color),a("body").append(this.$colorPicker),this.width=this.$colorPickerPalettesHolder.width(),this.height=this.$colorPickerPalettesHolder.height(),this.$colorPickerPalettesHolder.width(this.width),this.$colorPickerPalettesHolder.height(this.height),this.$el.append(this.$colorPicker),this.setMode(this.options.mode),this.setPosition(this.options.position)),this.init=!0,this},setTheme:function(a){this.$colorPicker.attr("class",this.$colorPicker.attr("class").replace(/wColorPicker-theme-.+\s|wColorPicker-theme-.+$/,"")),this.$colorPicker.addClass("wColorPicker-theme-"+a)},setOpacity:function(a){this.$colorPickerBg.css("opacity",a)},setColor:function(a){return window.rgbHex(a)?(this.options.color=a,this.$colorTarget.css("backgroundColor",a),this.$customInput.val(a),this.init&&this.options.onSelect&&this.options.onSelect.apply(this,[a]),void 0):!0},setMode:function(b){var c=this,d=function(){c._toggleEffect("show")},e=function(){c._toggleEffect("hide")};if("flat"===b?this.$colorPicker.removeClass("wColorPicker-zindex").css({position:"relative",display:""}):this.$colorPicker.addClass("wColorPicker-zindex").css({position:"absolute"}).hide(),this.$el.find("wColorPicker-button").remove(),this.$el.unbind("mouseenter",d).unbind("mouseleave",e),a(document).unbind("click",e),"flat"!==b){var f=null,g=null,h=function(a){a.stopPropagation(),c.options.generateButton&&g.css("backgroundColor",c.options.color),c._toggleEffect()};this.options.generateButton&&(f=a('<div class="wColorPicker-button"></div>'),g=a('<div class="wColorPicker-button-color"></div>').css("backgroundColor",this.options.color),this.$el.append(f),f.append(g.height(this.$el.height()-f.outerHeight(!0)))),this.$noneColorPalette.bind("click",h),this.$simpleColorPalette.bind("click",h),this.$mixedColorPalette.bind("click",h)}"click"===b?(this.$el.click(function(a){c._toggleEffect(),a.stopPropagation()}),this.$colorPicker.click(function(a){a.stopPropagation()}),a(document).bind("click",e)):"hover"===b&&this.$el.bind("mouseenter",d).bind("mouseleave",e)},setEffect:function(a){return"flat"===this.options.mode?!0:(this.$colorPicker.css("opacity",1),this.$colorPickerHolder.width(this.width).height(this.height),"fade"===a?this.$colorPicker.css("opacity",0):"slide"===a&&this.$colorPickerHolder.width("x"===this.positionAxis?0:this.width).height("y"===this.positionAxis?0:this.height),void 0)},setPosition:function(a){if("flat"===this.options.mode)return!0;var b=this.$el.outerWidth(),c=this.$el.outerHeight(),d=this.$el.outerWidth()/2-this.$colorPicker.outerWidth()/2,e=this.$el.outerHeight()/2-this.$colorPicker.outerHeight()/2,f={left:"",right:"",top:"",bottom:""},g=this.options.position.charAt(0);switch("t"===g||"b"===g?this.positionAxis="y":("l"===g||"r"===g)&&(this.positionAxis="x"),a){case"tl":f.left=0,f.bottom=c;break;case"tc":f.left=d,f.bottom=c;break;case"tr":f.right=0,f.bottom=c;break;case"rt":f.left=b,f.top=0;break;case"rm":f.left=b,f.top=e;break;case"rb":f.left=b,f.bottom=0;break;case"br":f.right=0,f.top=c;break;case"bc":f.left=d,f.top=c;break;case"bl":f.left=0,f.top=c;break;case"lb":f.right=b,f.bottom=0;break;case"lm":f.right=b,f.top=e;break;case"lt":f.right=b,f.top=0}this.$colorPicker.css(f),this.setEffect(this.options.effect)},_createPalette:function(b,c){var d=0,e=0,f=0,g=0,h=null,i=a('<div class="wColorPicker-palette wColorPicker-palette-'+b+'"></div>');for(d=0,e=c.length;e>d;d++){for(f=0,g=c[d].length;g>f;f++)h=this._createColor(f,c[d][f]),0===d&&h.addClass("wColorPicker-palette-color-top"),0===f&&h.addClass("wColorPicker-palette-color-left"),i.append(h);e>d&&i.append("<br/>")}return i},_createColor:function(b,c){var d=this;return a('<div class="wColorPicker-palette-color"></div>').attr("id","wColorPicker-palette-color-"+b).addClass("wColorPicker-palette-color-"+b).css("backgroundColor",c).hover(function(){d._colorMouseenter(a(this))},function(){d._colorMouseleave(a(this))}).click(function(){d.setColor(window.rgbHex(a(this).css("backgroundColor")))})},_createDropperButton:function(){return a('<div class="wColorPicker-dropper"></div>').click(a.proxy(this.options.onDropper,this))},_customInputKeyup:function(b){var c=a(b.target).val();window.rgbHex(c)&&(this.$colorTarget.css("backgroundColor",c),13===b.keyCode&&this.setColor(c))},_colorMouseenter:function(a){var b=window.rgbHex(a.css("backgroundColor"));a.addClass("active").prev().addClass("active-right"),a.prevAll("."+a.attr("id")+":first").addClass("active-bottom"),this.$colorTarget.css("backgroundColor",b),this.$customInput.val(b),this.options.onMouseover&&this.options.onMouseover.apply(this,[b])},_colorMouseleave:function(a){a.removeClass("active").prev().removeClass("active-right"),a.prevAll("."+a.attr("id")+":first").removeClass("active-bottom"),this.$colorTarget.css("backgroundColor",this.options.color),this.$customInput.val(this.options.color),this.options.onMouseout&&this.options.onMouseout.apply(this,[this.options.color])},_toggleEffect:function(a){var b=this.$colorPicker.hasClass("wColorPicker-visible");(!a||"show"===a&&b===!1||"hide"===a&&b===!0)&&(b||this.setPosition(this.options.position),this["_"+this.options.effect+"Effect"+(b?"Hide":"Show")](),this.$colorPicker.toggleClass("wColorPicker-visible"))},_noneEffectShow:function(){this.$colorPicker.css("display","inline-block")},_noneEffectHide:function(){this.$colorPicker.hide()},_fadeEffectShow:function(){this.$colorPicker.stop(!0,!1).css({display:"inline-block"}).animate({opacity:1},this.options.showSpeed)},_fadeEffectHide:function(){this.$colorPicker.stop(!0,!1).animate({opacity:0},this.options.hideSpeed,a.proxy(function(){this.$colorPicker.hide()},this))},_slideEffectShow:function(){var a="y"===this.positionAxis?{height:this.height}:{width:this.width};this.$colorPicker.css("display","inline-block"),this.$colorPickerHolder.stop(!0,!1).animate(a,this.options.showSpeed)},_slideEffectHide:function(){var b="y"===this.positionAxis?{height:0}:{width:0};this.$colorPickerHolder.stop(!0,!1).animate(b,this.options.hideSpeed,a.proxy(function(){this.$colorPicker.hide()},this))}},a.fn.wColorPicker=function(c,d){function e(d){var e,f=a.data(d,"wColorPicker");return f||(e=a.extend({},a.fn.wColorPicker.defaults,c),e.color=window.rgbHex(e.color)?e.color:"transparent",f=new b(d,e),a.data(d,"wColorPicker",f)),f}if("string"==typeof c){var f=[],g=null,h=null,i=null;return h=this.each(function(){g=a(this).data("wColorPicker"),g&&(i=(d?"set":"get")+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase(),g[c]?f.push(g[c].apply(g,[d])):d?(g[i]&&g[i].apply(g,[d]),g.options[c]&&(g.options[c]=d)):g[i]?f.push(g[i].apply(g,[d])):g.options[c]?f.push(g.options[c]):f.push(null))}),1===f.length?f[0]:f.length>0?f:h}return this.each(function(){e(this)})},a.fn.wColorPicker.defaults={theme:"classic",opacity:.9,color:"#FF0000",mode:"flat",position:"bl",generateButton:!0,dropperButton:!1,effect:"slide",showSpeed:500,hideSpeed:500,onMouseover:null,onMouseout:null,onSelect:null,onDropper:null},a.fn.wColorPicker.mixedColors=[["#000000","#003300","#006600","#009900","#00CC00","#00FF00","#330000","#333300","#336600","#339900","#33CC00","#33FF00","#660000","#663300","#666600","#669900","#66CC00","#66FF00"],["#000033","#003333","#006633","#009933","#00CC33","#00FF33","#330033","#333333","#336633","#339933","#33CC33","#33FF33","#660033","#663333","#666633","#669933","#66CC33","#66FF33"],["#000066","#003366","#006666","#009966","#00CC66","#00FF66","#330066","#333366","#336666","#339966","#33CC66","#33FF66","#660066","#663366","#666666","#669966","#66CC66","#66FF66"],["#000099","#003399","#006699","#009999","#00CC99","#00FF99","#330099","#333399","#336699","#339999","#33CC99","#33FF99","#660099","#663399","#666699","#669999","#66CC99","#66FF99"],["#0000CC","#0033CC","#0066CC","#0099CC","#00CCCC","#00FFCC","#3300CC","#3333CC","#3366CC","#3399CC","#33CCCC","#33FFCC","#6600CC","#6633CC","#6666CC","#6699CC","#66CCCC","#66FFCC"],["#0000FF","#0033FF","#0066FF","#0099FF","#00CCFF","#00FFFF","#3300FF","#3333FF","#3366FF","#3399FF","#33CCFF","#33FFFF","#6600FF","#6633FF","#6666FF","#6699FF","#66CCFF","#66FFFF"],["#990000","#993300","#996600","#999900","#99CC00","#99FF00","#CC0000","#CC3300","#CC6600","#CC9900","#CCCC00","#CCFF00","#FF0000","#FF3300","#FF6600","#FF9900","#FFCC00","#FFFF00"],["#990033","#993333","#996633","#999933","#99CC33","#99FF33","#CC0033","#CC3333","#CC6633","#CC9933","#CCCC33","#CCFF33","#FF0033","#FF3333","#FF6633","#FF9933","#FFCC33","#FFFF33"],["#990066","#993366","#996666","#999966","#99CC66","#99FF66","#CC0066","#CC3366","#CC6666","#CC9966","#CCCC66","#CCFF66","#FF0066","#FF3366","#FF6666","#FF9966","#FFCC66","#FFFF66"],["#990099","#993399","#996699","#999999","#99CC99","#99FF99","#CC0099","#CC3399","#CC6699","#CC9999","#CCCC99","#CCFF99","#FF0099","#FF3399","#FF6699","#FF9999","#FFCC99","#FFFF99"],["#9900CC","#9933CC","#9966CC","#9999CC","#99CCCC","#99FFCC","#CC00CC","#CC33CC","#CC66CC","#CC99CC","#CCCCCC","#CCFFCC","#FF00CC","#FF33CC","#FF66CC","#FF99CC","#FFCCCC","#FFFFCC"],["#9900FF","#9933FF","#9966FF","#9999FF","#99CCFF","#99FFFF","#CC00FF","#CC33FF","#CC66FF","#CC99FF","#CCCCFF","#CCFFFF","#FF00FF","#FF33FF","#FF66FF","#FF99FF","#FFCCFF","#FFFFFF"]],a.fn.wColorPicker.simpleColors=[["#000000"],["#333333"],["#666666"],["#999999"],["#CCCCCC"],["#FFFFFF"],["#FF0000"],["#00FF00"],["#0000FF"],["#FFFF00"],["#00FFFF"],["#FF00FF"]]}(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/package.json b/static/js/wpaint/package.json
new file mode 100644
index 0000000..49ea26f
--- /dev/null
+++ b/static/js/wpaint/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "wPaint",
+ "title": "wPaint jQuery Paint Plugin",
+ "version": "2.5.0",
+ "description": "A jQuery paint plugin for a simple drawing surface that you can easily pop into your pages, similar to the basic windows paint program.",
+ "main": "wPaint.js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/websanova/wPaint"
+ },
+ "author": {
+ "name": "Websanova",
+ "email": "rob@websanova.com",
+ "url": "http://websanova.com"
+ },
+ "homepage" : "http://wpaint.websanova.com",
+ "license": "MIT, GPL",
+ "dependencies": {
+ "grunt-contrib-uglify": "",
+ "grunt-contrib-jshint": "",
+ "grunt-contrib-stylus": "",
+ "grunt-contrib-concat": "",
+ "grunt-contrib-watch": ""
+ }
+} \ No newline at end of file
diff --git a/static/js/wpaint/plugins/file/img/icons-menu-main-file.png b/static/js/wpaint/plugins/file/img/icons-menu-main-file.png
new file mode 100644
index 0000000..cda4bde
--- /dev/null
+++ b/static/js/wpaint/plugins/file/img/icons-menu-main-file.png
Binary files differ
diff --git a/static/js/wpaint/plugins/file/src/wPaint.menu.main.file.js b/static/js/wpaint/plugins/file/src/wPaint.menu.main.file.js
new file mode 100644
index 0000000..15cfa46
--- /dev/null
+++ b/static/js/wpaint/plugins/file/src/wPaint.menu.main.file.js
@@ -0,0 +1,75 @@
+(function ($) {
+ var img = 'plugins/file/img/icons-menu-main-file.png';
+
+ // extend menu
+ $.extend(true, $.fn.wPaint.menus.main.items, {
+ save: {
+ icon: 'generic',
+ title: 'Save Image',
+ img: img,
+ index: 0,
+ callback: function () {
+ this.options.saveImg.apply(this, [this.getImage()]);
+ }
+ },
+ loadBg: {
+ icon: 'generic',
+ group: 'loadImg',
+ title: 'Load Image to Foreground',
+ img: img,
+ index: 2,
+ callback: function () {
+ this.options.loadImgFg.apply(this, []);
+ }
+ },
+ loadFg: {
+ icon: 'generic',
+ group: 'loadImg',
+ title: 'Load Image to Background',
+ img: img,
+ index: 1,
+ callback: function () {
+ this.options.loadImgBg.apply(this, []);
+ }
+ }
+ });
+
+ // extend defaults
+ $.extend($.fn.wPaint.defaults, {
+ saveImg: null, // callback triggerd on image save
+ loadImgFg: null, // callback triggered on image fg
+ loadImgBg: null // callback triggerd on image bg
+ });
+
+ // extend functions
+ $.fn.wPaint.extend({
+ _showFileModal: function (type, images) {
+ var _this = this,
+ $content = $('<div></div>'),
+ $img = null;
+
+ function appendContent(type, image) {
+ function imgClick(e) {
+
+ // just in case to not draw on canvas
+ e.stopPropagation();
+ if (type === 'fg') { _this.setImage(image); }
+ else if (type === 'bg') { _this.setBg(image, null, null, true); }
+ }
+
+ $img.on('click', imgClick);
+ }
+
+ for (var i = 0, ii = images.length; i < ii; i++) {
+ $img = $('<img class="wPaint-modal-img"/>').attr('src', images[i]);
+ $img = $('<div class="wPaint-modal-img-holder"></div>').append($img);
+
+ (appendContent)(type, images[i]);
+
+ $content.append($img);
+ }
+
+ this._showModal($content);
+ }
+ });
+})(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/plugins/file/wPaint.menu.main.file.min.js b/static/js/wpaint/plugins/file/wPaint.menu.main.file.min.js
new file mode 100644
index 0000000..a2631b7
--- /dev/null
+++ b/static/js/wpaint/plugins/file/wPaint.menu.main.file.min.js
@@ -0,0 +1 @@
+/*! wPaint - v2.5.0 - 2014-03-01 */!function(a){var b="plugins/file/img/icons-menu-main-file.png";a.extend(!0,a.fn.wPaint.menus.main.items,{save:{icon:"generic",title:"Save Image",img:b,index:0,callback:function(){this.options.saveImg.apply(this,[this.getImage()])}},loadBg:{icon:"generic",group:"loadImg",title:"Load Image to Foreground",img:b,index:2,callback:function(){this.options.loadImgFg.apply(this,[])}},loadFg:{icon:"generic",group:"loadImg",title:"Load Image to Background",img:b,index:1,callback:function(){this.options.loadImgBg.apply(this,[])}}}),a.extend(a.fn.wPaint.defaults,{saveImg:null,loadImgFg:null,loadImgBg:null}),a.fn.wPaint.extend({_showFileModal:function(b,c){function d(a,b){function c(c){c.stopPropagation(),"fg"===a?e.setImage(b):"bg"===a&&e.setBg(b,null,null,!0)}g.on("click",c)}for(var e=this,f=a("<div></div>"),g=null,h=0,i=c.length;i>h;h++)g=a('<img class="wPaint-modal-img"/>').attr("src",c[h]),g=a('<div class="wPaint-modal-img-holder"></div>').append(g),d(b,c[h]),f.append(g);this._showModal(f)}})}(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/plugins/main/img/cursor-bucket.png b/static/js/wpaint/plugins/main/img/cursor-bucket.png
new file mode 100644
index 0000000..b6757ad
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-bucket.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-crosshair.png b/static/js/wpaint/plugins/main/img/cursor-crosshair.png
new file mode 100644
index 0000000..362e069
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-crosshair.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-dropper.png b/static/js/wpaint/plugins/main/img/cursor-dropper.png
new file mode 100644
index 0000000..e8396d1
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-dropper.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser1.png b/static/js/wpaint/plugins/main/img/cursor-eraser1.png
new file mode 100644
index 0000000..1a25ec5
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser1.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser10.png b/static/js/wpaint/plugins/main/img/cursor-eraser10.png
new file mode 100644
index 0000000..5f5d83f
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser10.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser2.png b/static/js/wpaint/plugins/main/img/cursor-eraser2.png
new file mode 100644
index 0000000..d15f875
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser2.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser3.png b/static/js/wpaint/plugins/main/img/cursor-eraser3.png
new file mode 100644
index 0000000..c81814d
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser3.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser4.png b/static/js/wpaint/plugins/main/img/cursor-eraser4.png
new file mode 100644
index 0000000..c512bfc
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser4.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser5.png b/static/js/wpaint/plugins/main/img/cursor-eraser5.png
new file mode 100644
index 0000000..fff0873
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser5.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser6.png b/static/js/wpaint/plugins/main/img/cursor-eraser6.png
new file mode 100644
index 0000000..d413f05
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser6.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser7.png b/static/js/wpaint/plugins/main/img/cursor-eraser7.png
new file mode 100644
index 0000000..52876a5
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser7.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser8.png b/static/js/wpaint/plugins/main/img/cursor-eraser8.png
new file mode 100644
index 0000000..6c1577b
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser8.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser9.png b/static/js/wpaint/plugins/main/img/cursor-eraser9.png
new file mode 100644
index 0000000..4441a3e
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-eraser9.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/cursor-pencil.png b/static/js/wpaint/plugins/main/img/cursor-pencil.png
new file mode 100644
index 0000000..d54322d
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/cursor-pencil.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/icon-group-arrow.png b/static/js/wpaint/plugins/main/img/icon-group-arrow.png
new file mode 100644
index 0000000..ff501ac
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/icon-group-arrow.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/img/icons-menu-main.png b/static/js/wpaint/plugins/main/img/icons-menu-main.png
new file mode 100644
index 0000000..4b1a90b
--- /dev/null
+++ b/static/js/wpaint/plugins/main/img/icons-menu-main.png
Binary files differ
diff --git a/static/js/wpaint/plugins/main/src/fillArea.min.js b/static/js/wpaint/plugins/main/src/fillArea.min.js
new file mode 100644
index 0000000..08aa950
--- /dev/null
+++ b/static/js/wpaint/plugins/main/src/fillArea.min.js
@@ -0,0 +1 @@
+!function(){window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.fillArea=function(a,b,c){function d(a){return{r:p[a],g:p[a+1],b:p[a+2],a:p[a+3]}}function e(a){p[a]=c.r,p[a+1]=c.g,p[a+2]=c.b,p[a+3]=c.a}function f(a){return g.r===a.r&&g.g===a.g&&g.b===a.b&&g.a===a.a}if(!a||!b||!c)return!0;var g,h,i,j,k,l,m=this.canvas.width,n=this.canvas.height,o=this.getImageData(0,0,m,n),p=o.data,q=[[a,b]];if(g=d(4*(b*m+a)),l=this.canvas.style.color,this.canvas.style.color=c,c=this.canvas.style.color.match(/^rgba?\((.*)\);?$/)[1].split(","),this.canvas.style.color=l,c={r:parseInt(c[0],10),g:parseInt(c[1],10),b:parseInt(c[2],10),a:parseInt(c[3]||255,10)},f(c))return!0;for(;q.length;){for(h=q.pop(),i=4*(h[1]*m+h[0]);h[1]-->=0&&f(d(i));)i-=4*m;for(i+=4*m,++h[1],j=!1,k=!1;h[1]++<n-1&&f(d(i));)e(i),h[0]>0&&(f(d(i-4))?j||(q.push([h[0]-1,h[1]]),j=!0):j&&(j=!1)),h[0]<m-1&&(f(d(i+4))?k||(q.push([h[0]+1,h[1]]),k=!0):k&&(k=!1)),i+=4*m}this.putImageData(o,0,0)})}(); \ No newline at end of file
diff --git a/static/js/wpaint/plugins/main/src/wPaint.menu.main.js b/static/js/wpaint/plugins/main/src/wPaint.menu.main.js
new file mode 100644
index 0000000..459bb73
--- /dev/null
+++ b/static/js/wpaint/plugins/main/src/wPaint.menu.main.js
@@ -0,0 +1,338 @@
+(function ($) {
+
+ // setup menu
+ $.fn.wPaint.menus.main = {
+ img: 'plugins/main/img/icons-menu-main.png',
+ items: {
+ undo: {
+ icon: 'generic',
+ title: 'Undo',
+ index: 0,
+ callback: function () { this.undo(); }
+ },
+ redo: {
+ icon: 'generic',
+ title: 'Redo',
+ index: 1,
+ callback: function () { this.redo(); }
+ },
+ clear: {
+ icon: 'generic',
+ title: 'Clear',
+ index: 2,
+ callback: function () { this.clear(); }
+ },
+ rectangle: {
+ icon: 'activate',
+ title: 'Rectangle',
+ index: 3,
+ callback: function () { this.setMode('rectangle'); }
+ },
+ ellipse: {
+ icon: 'activate',
+ title: 'Ellipse',
+ index: 4,
+ callback: function () { this.setMode('ellipse'); }
+ },
+ line: {
+ icon: 'activate',
+ title: 'Line',
+ index: 5,
+ callback: function () { this.setMode('line'); }
+ },
+ pencil: {
+ icon: 'activate',
+ title: 'Pencil',
+ index: 6,
+ callback: function () { this.setMode('pencil'); }
+ },
+ eraser: {
+ icon: 'activate',
+ title: 'Eraser',
+ index: 8,
+ callback: function () { this.setMode('eraser'); }
+ },
+ bucket: {
+ icon: 'activate',
+ title: 'Bucket',
+ index: 9,
+ callback: function () { this.setMode('bucket'); }
+ },
+ fillStyle: {
+ title: 'Fill Color',
+ icon: 'colorPicker',
+ callback: function (color) { this.setFillStyle(color); }
+ },
+ lineWidth: {
+ icon: 'select',
+ title: 'Stroke Width',
+ range: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
+ value: 2,
+ callback: function (width) { this.setLineWidth(width); }
+ },
+ strokeStyle: {
+ icon: 'colorPicker',
+ title: 'Stroke Color',
+ callback: function (color) { this.setStrokeStyle(color); }
+ }
+ }
+ };
+
+ // extend cursors
+ $.extend($.fn.wPaint.cursors, {
+ 'default': {path: 'plugins/main/img/cursor-crosshair.png', left: 7, top: 7},
+ dropper: {path: 'plugins/main/img/cursor-dropper.png', left: 0, top: 12},
+ pencil: {path: 'plugins/main/img/cursor-pencil.png', left: 0, top: 11.99},
+ bucket: {path: 'plugins/main/img/cursor-bucket.png', left: 0, top: 10},
+ eraser1: {path: 'plugins/main/img/cursor-eraser1.png', left: 1, top: 1},
+ eraser2: {path: 'plugins/main/img/cursor-eraser2.png', left: 2, top: 2},
+ eraser3: {path: 'plugins/main/img/cursor-eraser3.png', left: 2, top: 2},
+ eraser4: {path: 'plugins/main/img/cursor-eraser4.png', left: 3, top: 3},
+ eraser5: {path: 'plugins/main/img/cursor-eraser5.png', left: 3, top: 3},
+ eraser6: {path: 'plugins/main/img/cursor-eraser6.png', left: 4, top: 4},
+ eraser7: {path: 'plugins/main/img/cursor-eraser7.png', left: 4, top: 4},
+ eraser8: {path: 'plugins/main/img/cursor-eraser8.png', left: 5, top: 5 },
+ eraser9: {path: 'plugins/main/img/cursor-eraser9.png', left: 5, top: 5},
+ eraser10: {path: 'plugins/main/img/cursor-eraser10.png', left: 6, top: 6}
+ });
+
+ // extend defaults
+ $.extend($.fn.wPaint.defaults, {
+ mode: 'pencil', // set mode
+ lineWidth: '3', // starting line width
+ fillStyle: '#FFFFFF', // starting fill style
+ strokeStyle: '#FFFF00' // start stroke style
+ });
+
+ // extend functions
+ $.fn.wPaint.extend({
+ undoCurrent: -1,
+ undoArray: [],
+ setUndoFlag: true,
+
+ generate: function () {
+ this.menus.all.main = this._createMenu('main', {
+ offsetLeft: this.options.menuOffsetLeft,
+ offsetTop: this.options.menuOffsetTop
+ });
+ },
+
+ _init: function () {
+ // must add undo on init to set the first undo as the initial drawing (bg or blank)
+ this._addUndo();
+ this.menus.all.main._setIconDisabled('clear', true);
+ },
+
+ setStrokeStyle: function (color) {
+ this.options.strokeStyle = color;
+ this.menus.all.main._setColorPickerValue('strokeStyle', color);
+ },
+
+ setLineWidth: function (width) {
+ this.options.lineWidth = width;
+ this.menus.all.main._setSelectValue('lineWidth', width);
+
+ // reset cursor here based on mode in case we need to update cursor (for instance when changing cursor for eraser sizes)
+ this.setCursor(this.options.mode);
+ },
+
+ setFillStyle: function (color) {
+ this.options.fillStyle = color;
+ this.menus.all.main._setColorPickerValue('fillStyle', color);
+ },
+
+ setCursor: function (cursor) {
+ if (cursor === 'eraser') {
+ this.setCursor('eraser' + this.options.lineWidth);
+ }
+ },
+
+ /****************************************
+ * undo / redo
+ ****************************************/
+ undo: function () {
+ if (this.undoArray[this.undoCurrent - 1]) {
+ this._setUndo(--this.undoCurrent);
+ }
+
+ this._undoToggleIcons();
+ },
+
+ redo: function () {
+ if (this.undoArray[this.undoCurrent + 1]) {
+ this._setUndo(++this.undoCurrent);
+ }
+
+ this._undoToggleIcons();
+ },
+
+ _addUndo: function () {
+
+ //if it's not at the end of the array we need to repalce the current array position
+ if (this.undoCurrent < this.undoArray.length - 1) {
+ this.undoArray[++this.undoCurrent] = this.getImage(false);
+ }
+ else { // owtherwise we push normally here
+ this.undoArray.push(this.getImage(false));
+
+ //if we're at the end of the array we need to slice off the front - in increment required
+ if (this.undoArray.length > this.undoMax) {
+ this.undoArray = this.undoArray.slice(1, this.undoArray.length);
+ }
+ //if we're NOT at the end of the array, we just increment
+ else { this.undoCurrent++; }
+ }
+
+ //for undo's then a new draw we want to remove everything afterwards - in most cases nothing will happen here
+ while (this.undoCurrent !== this.undoArray.length - 1) { this.undoArray.pop(); }
+
+ this._undoToggleIcons();
+ this.menus.all.main._setIconDisabled('clear', false);
+ },
+
+ _undoToggleIcons: function () {
+ var undoIndex = (this.undoCurrent > 0 && this.undoArray.length > 1) ? 0 : 1,
+ redoIndex = (this.undoCurrent < this.undoArray.length - 1) ? 2 : 3;
+
+ this.menus.all.main._setIconDisabled('undo', undoIndex === 1 ? true : false);
+ this.menus.all.main._setIconDisabled('redo', redoIndex === 3 ? true : false);
+ },
+
+ _setUndo: function (undoCurrent) {
+ this.setImage(this.undoArray[undoCurrent], null, null, true);
+ },
+
+ /****************************************
+ * clear
+ ****************************************/
+ clear: function () {
+
+ // only run if not disabled (make sure we only run one clear at a time)
+ if (!this.menus.all.main._isIconDisabled('clear')) {
+ this.ctx.clearRect(0, 0, this.width, this.height);
+ this._addUndo();
+ this.menus.all.main._setIconDisabled('clear', true);
+ }
+ },
+
+ /****************************************
+ * rectangle
+ ****************************************/
+ _drawRectangleDown: function (e) { this._drawShapeDown(e); },
+
+ _drawRectangleMove: function (e) {
+ this._drawShapeMove(e);
+
+ this.ctxTemp.rect(e.x, e.y, e.w, e.h);
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawRectangleUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * ellipse
+ ****************************************/
+ _drawEllipseDown: function (e) { this._drawShapeDown(e); },
+
+ _drawEllipseMove: function (e) {
+ this._drawShapeMove(e);
+
+ this.ctxTemp.ellipse(e.x, e.y, e.w, e.h);
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawEllipseUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * line
+ ****************************************/
+ _drawLineDown: function (e) { this._drawShapeDown(e); },
+
+ _drawLineMove: function (e) {
+ this._drawShapeMove(e, 1);
+
+ var xo = this.canvasTempLeftOriginal;
+ var yo = this.canvasTempTopOriginal;
+
+ if (e.pageX < xo) { e.x = e.x + e.w; e.w = e.w * - 1; }
+ if (e.pageY < yo) { e.y = e.y + e.h; e.h = e.h * - 1; }
+
+ this.ctxTemp.lineJoin = 'round';
+ this.ctxTemp.beginPath();
+ this.ctxTemp.moveTo(e.x, e.y);
+ this.ctxTemp.lineTo(e.x + e.w, e.y + e.h);
+ this.ctxTemp.closePath();
+ this.ctxTemp.stroke();
+ },
+
+ _drawLineUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * pencil
+ ****************************************/
+ _drawPencilDown: function (e) {
+ this.ctx.lineJoin = 'round';
+ this.ctx.lineCap = 'round';
+ this.ctx.strokeStyle = this.options.strokeStyle;
+ this.ctx.fillStyle = this.options.strokeStyle;
+ this.ctx.lineWidth = this.options.lineWidth;
+
+ //draw single dot in case of a click without a move
+ this.ctx.beginPath();
+ this.ctx.arc(e.pageX, e.pageY, this.options.lineWidth / 2, 0, Math.PI * 2, true);
+ this.ctx.closePath();
+ this.ctx.fill();
+
+ //start the path for a drag
+ this.ctx.beginPath();
+ this.ctx.moveTo(e.pageX, e.pageY);
+ },
+
+ _drawPencilMove: function (e) {
+ this.ctx.lineTo(e.pageX, e.pageY);
+ this.ctx.stroke();
+ },
+
+ _drawPencilUp: function () {
+ this.ctx.closePath();
+ this._addUndo();
+ },
+
+ /****************************************
+ * eraser
+ ****************************************/
+ _drawEraserDown: function (e) {
+ this.ctx.save();
+ this.ctx.globalCompositeOperation = 'destination-out';
+ this._drawPencilDown(e);
+ },
+
+ _drawEraserMove: function (e) {
+ this._drawPencilMove(e);
+ },
+
+ _drawEraserUp: function (e) {
+ this._drawPencilUp(e);
+ this.ctx.restore();
+ },
+
+ /****************************************
+ * bucket
+ ****************************************/
+ _drawBucketDown: function (e) {
+ this.ctx.fillArea(e.pageX, e.pageY, this.options.fillStyle);
+ this._addUndo();
+ }
+ });
+})(jQuery);
diff --git a/static/js/wpaint/plugins/main/wPaint.menu.main.min.js b/static/js/wpaint/plugins/main/wPaint.menu.main.min.js
new file mode 100644
index 0000000..0a950c5
--- /dev/null
+++ b/static/js/wpaint/plugins/main/wPaint.menu.main.min.js
@@ -0,0 +1 @@
+/*! wPaint - v2.5.0 - 2014-03-01 */!function(a){a.fn.wPaint.menus.main={img:"plugins/main/img/icons-menu-main.png",items:{undo:{icon:"generic",title:"Undo",index:0,callback:function(){this.undo()}},redo:{icon:"generic",title:"Redo",index:1,callback:function(){this.redo()}},clear:{icon:"generic",title:"Clear",index:2,callback:function(){this.clear()}},rectangle:{icon:"activate",title:"Rectangle",index:3,callback:function(){this.setMode("rectangle")}},ellipse:{icon:"activate",title:"Ellipse",index:4,callback:function(){this.setMode("ellipse")}},line:{icon:"activate",title:"Line",index:5,callback:function(){this.setMode("line")}},pencil:{icon:"activate",title:"Pencil",index:6,callback:function(){this.setMode("pencil")}},eraser:{icon:"activate",title:"Eraser",index:8,callback:function(){this.setMode("eraser")}},bucket:{icon:"activate",title:"Bucket",index:9,callback:function(){this.setMode("bucket")}},fillStyle:{title:"Fill Color",icon:"colorPicker",callback:function(a){this.setFillStyle(a)}},lineWidth:{icon:"select",title:"Stroke Width",range:[1,2,3,4,5,6,7,8,9,10],value:2,callback:function(a){this.setLineWidth(a)}},strokeStyle:{icon:"colorPicker",title:"Stroke Color",callback:function(a){this.setStrokeStyle(a)}}}},a.extend(a.fn.wPaint.cursors,{"default":{path:"plugins/main/img/cursor-crosshair.png",left:7,top:7},dropper:{path:"plugins/main/img/cursor-dropper.png",left:0,top:12},pencil:{path:"plugins/main/img/cursor-pencil.png",left:0,top:11.99},bucket:{path:"plugins/main/img/cursor-bucket.png",left:0,top:10},eraser1:{path:"plugins/main/img/cursor-eraser1.png",left:1,top:1},eraser2:{path:"plugins/main/img/cursor-eraser2.png",left:2,top:2},eraser3:{path:"plugins/main/img/cursor-eraser3.png",left:2,top:2},eraser4:{path:"plugins/main/img/cursor-eraser4.png",left:3,top:3},eraser5:{path:"plugins/main/img/cursor-eraser5.png",left:3,top:3},eraser6:{path:"plugins/main/img/cursor-eraser6.png",left:4,top:4},eraser7:{path:"plugins/main/img/cursor-eraser7.png",left:4,top:4},eraser8:{path:"plugins/main/img/cursor-eraser8.png",left:5,top:5},eraser9:{path:"plugins/main/img/cursor-eraser9.png",left:5,top:5},eraser10:{path:"plugins/main/img/cursor-eraser10.png",left:6,top:6}}),a.extend(a.fn.wPaint.defaults,{mode:"pencil",lineWidth:"3",fillStyle:"#FFFFFF",strokeStyle:"#FFFF00"}),a.fn.wPaint.extend({undoCurrent:-1,undoArray:[],setUndoFlag:!0,generate:function(){this.menus.all.main=this._createMenu("main",{offsetLeft:this.options.menuOffsetLeft,offsetTop:this.options.menuOffsetTop})},_init:function(){this._addUndo(),this.menus.all.main._setIconDisabled("clear",!0)},setStrokeStyle:function(a){this.options.strokeStyle=a,this.menus.all.main._setColorPickerValue("strokeStyle",a)},setLineWidth:function(a){this.options.lineWidth=a,this.menus.all.main._setSelectValue("lineWidth",a),this.setCursor(this.options.mode)},setFillStyle:function(a){this.options.fillStyle=a,this.menus.all.main._setColorPickerValue("fillStyle",a)},setCursor:function(a){"eraser"===a&&this.setCursor("eraser"+this.options.lineWidth)},undo:function(){this.undoArray[this.undoCurrent-1]&&this._setUndo(--this.undoCurrent),this._undoToggleIcons()},redo:function(){this.undoArray[this.undoCurrent+1]&&this._setUndo(++this.undoCurrent),this._undoToggleIcons()},_addUndo:function(){for(this.undoCurrent<this.undoArray.length-1?this.undoArray[++this.undoCurrent]=this.getImage(!1):(this.undoArray.push(this.getImage(!1)),this.undoArray.length>this.undoMax?this.undoArray=this.undoArray.slice(1,this.undoArray.length):this.undoCurrent++);this.undoCurrent!==this.undoArray.length-1;)this.undoArray.pop();this._undoToggleIcons(),this.menus.all.main._setIconDisabled("clear",!1)},_undoToggleIcons:function(){var a=this.undoCurrent>0&&this.undoArray.length>1?0:1,b=this.undoCurrent<this.undoArray.length-1?2:3;this.menus.all.main._setIconDisabled("undo",1===a?!0:!1),this.menus.all.main._setIconDisabled("redo",3===b?!0:!1)},_setUndo:function(a){this.setImage(this.undoArray[a],null,null,!0)},clear:function(){this.menus.all.main._isIconDisabled("clear")||(this.ctx.clearRect(0,0,this.width,this.height),this._addUndo(),this.menus.all.main._setIconDisabled("clear",!0))},_drawRectangleDown:function(a){this._drawShapeDown(a)},_drawRectangleMove:function(a){this._drawShapeMove(a),this.ctxTemp.rect(a.x,a.y,a.w,a.h),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawRectangleUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawEllipseDown:function(a){this._drawShapeDown(a)},_drawEllipseMove:function(a){this._drawShapeMove(a),this.ctxTemp.ellipse(a.x,a.y,a.w,a.h),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawEllipseUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawLineDown:function(a){this._drawShapeDown(a)},_drawLineMove:function(a){this._drawShapeMove(a,1);var b=this.canvasTempLeftOriginal,c=this.canvasTempTopOriginal;a.pageX<b&&(a.x=a.x+a.w,a.w=-1*a.w),a.pageY<c&&(a.y=a.y+a.h,a.h=-1*a.h),this.ctxTemp.lineJoin="round",this.ctxTemp.beginPath(),this.ctxTemp.moveTo(a.x,a.y),this.ctxTemp.lineTo(a.x+a.w,a.y+a.h),this.ctxTemp.closePath(),this.ctxTemp.stroke()},_drawLineUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawPencilDown:function(a){this.ctx.lineJoin="round",this.ctx.lineCap="round",this.ctx.strokeStyle=this.options.strokeStyle,this.ctx.fillStyle=this.options.strokeStyle,this.ctx.lineWidth=this.options.lineWidth,this.ctx.beginPath(),this.ctx.arc(a.pageX,a.pageY,this.options.lineWidth/2,0,2*Math.PI,!0),this.ctx.closePath(),this.ctx.fill(),this.ctx.beginPath(),this.ctx.moveTo(a.pageX,a.pageY)},_drawPencilMove:function(a){this.ctx.lineTo(a.pageX,a.pageY),this.ctx.stroke()},_drawPencilUp:function(){this.ctx.closePath(),this._addUndo()},_drawEraserDown:function(a){this.ctx.save(),this.ctx.globalCompositeOperation="destination-out",this._drawPencilDown(a)},_drawEraserMove:function(a){this._drawPencilMove(a)},_drawEraserUp:function(a){this._drawPencilUp(a),this.ctx.restore()},_drawBucketDown:function(a){this.ctx.fillArea(a.pageX,a.pageY,this.options.fillStyle),this._addUndo()}})}(jQuery),!function(){window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.fillArea=function(a,b,c){function d(a){return{r:p[a],g:p[a+1],b:p[a+2],a:p[a+3]}}function e(a){p[a]=c.r,p[a+1]=c.g,p[a+2]=c.b,p[a+3]=c.a}function f(a){return g.r===a.r&&g.g===a.g&&g.b===a.b&&g.a===a.a}if(!a||!b||!c)return!0;var g,h,i,j,k,l,m=this.canvas.width,n=this.canvas.height,o=this.getImageData(0,0,m,n),p=o.data,q=[[a,b]];if(g=d(4*(b*m+a)),l=this.canvas.style.color,this.canvas.style.color=c,c=this.canvas.style.color.match(/^rgba?\((.*)\);?$/)[1].split(","),this.canvas.style.color=l,c={r:parseInt(c[0],10),g:parseInt(c[1],10),b:parseInt(c[2],10),a:parseInt(c[3]||255,10)},f(c))return!0;for(;q.length;){for(h=q.pop(),i=4*(h[1]*m+h[0]);h[1]-->=0&&f(d(i));)i-=4*m;for(i+=4*m,++h[1],j=!1,k=!1;h[1]++<n-1&&f(d(i));)e(i),h[0]>0&&(f(d(i-4))?j||(q.push([h[0]-1,h[1]]),j=!0):j&&(j=!1)),h[0]<m-1&&(f(d(i+4))?k||(q.push([h[0]+1,h[1]]),k=!0):k&&(k=!1)),i+=4*m}this.putImageData(o,0,0)})}(); \ No newline at end of file
diff --git a/static/js/wpaint/plugins/shapes/img/icons-menu-main-shapes.png b/static/js/wpaint/plugins/shapes/img/icons-menu-main-shapes.png
new file mode 100644
index 0000000..b2cb874
--- /dev/null
+++ b/static/js/wpaint/plugins/shapes/img/icons-menu-main-shapes.png
Binary files differ
diff --git a/static/js/wpaint/plugins/shapes/src/shapes.min.js b/static/js/wpaint/plugins/shapes/src/shapes.min.js
new file mode 100644
index 0000000..585aa85
--- /dev/null
+++ b/static/js/wpaint/plugins/shapes/src/shapes.min.js
@@ -0,0 +1 @@
+!function(){window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.diamond=function(a,b,c,d){return a&&b&&c&&d?(this.beginPath(),this.moveTo(a+.5*c,b),this.lineTo(a,b+.5*d),this.lineTo(a+.5*c,b+d),this.lineTo(a+c,b+.5*d),this.lineTo(a+.5*c,b),this.closePath(),void 0):!0}),window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.ellipse=function(a,b,c,d){if(!(a&&b&&c&&d))return!0;var e=.5522848,f=c/2*e,g=d/2*e,h=a+c,i=b+d,j=a+c/2,k=b+d/2;this.beginPath(),this.moveTo(a,k),this.bezierCurveTo(a,k-g,j-f,b,j,b),this.bezierCurveTo(j+f,b,h,k-g,h,k),this.bezierCurveTo(h,k+g,j+f,i,j,i),this.bezierCurveTo(j-f,i,a,k+g,a,k),this.closePath()}),window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.hexagon=function(a,b,c,d){if(!(a&&b&&c&&d))return!0;var e=.225,f=1-e;this.beginPath(),this.moveTo(a+.5*c,b),this.lineTo(a,b+d*e),this.lineTo(a,b+d*f),this.lineTo(a+.5*c,b+d),this.lineTo(a+c,b+d*f),this.lineTo(a+c,b+d*e),this.lineTo(a+.5*c,b),this.closePath()}),window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.pentagon=function(a,b,c,d){return a&&b&&c&&d?(this.beginPath(),this.moveTo(a+c/2,b),this.lineTo(a,b+.4*d),this.lineTo(a+.2*c,b+d),this.lineTo(a+.8*c,b+d),this.lineTo(a+c,b+.4*d),this.lineTo(a+c/2,b),this.closePath(),void 0):!0}),window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.roundedRect=function(a,b,c,d,e){return a&&b&&c&&d?(e||(e=5),this.beginPath(),this.moveTo(a+e,b),this.lineTo(a+c-e,b),this.quadraticCurveTo(a+c,b,a+c,b+e),this.lineTo(a+c,b+d-e),this.quadraticCurveTo(a+c,b+d,a+c-e,b+d),this.lineTo(a+e,b+d),this.quadraticCurveTo(a,b+d,a,b+d-e),this.lineTo(a,b+e),this.quadraticCurveTo(a,b,a+e,b),this.closePath(),void 0):!0})}(); \ No newline at end of file
diff --git a/static/js/wpaint/plugins/shapes/src/wPaint.menu.main.shapes.js b/static/js/wpaint/plugins/shapes/src/wPaint.menu.main.shapes.js
new file mode 100644
index 0000000..1d4daeb
--- /dev/null
+++ b/static/js/wpaint/plugins/shapes/src/wPaint.menu.main.shapes.js
@@ -0,0 +1,207 @@
+(function ($) {
+ var img = 'plugins/shapes/img/icons-menu-main-shapes.png';
+
+ // extend menu
+ $.extend(true, $.fn.wPaint.menus.main.items, {
+ rectangle: {
+ group: 'shapes'
+ },
+ roundedRect: {
+ icon: 'activate',
+ group: 'shapes',
+ title: 'Rounded Rectangle',
+ img: img,
+ index: 0,
+ callback: function () { this.setMode('roundedRect'); }
+ },
+ square: {
+ icon: 'activate',
+ group: 'shapes',
+ title: 'Square',
+ img: img,
+ index: 1,
+ callback: function () { this.setMode('square'); }
+ },
+ roundedSquare: {
+ icon: 'activate',
+ group: 'shapes',
+ title: 'Rounded Square',
+ img: img,
+ index: 2,
+ callback: function () { this.setMode('roundedSquare'); }
+ },
+ diamond: {
+ icon: 'activate',
+ group: 'shapes',
+ title: 'Diamond',
+ img: img,
+ index: 4,
+ callback: function () { this.setMode('diamond'); }
+ },
+
+ ellipse: {
+ group: 'shapes2'
+ },
+ circle: {
+ icon: 'activate',
+ group: 'shapes2',
+ title: 'Circle',
+ img: img,
+ index: 3,
+ callback: function () { this.setMode('circle'); }
+ },
+ pentagon: {
+ icon: 'activate',
+ group: 'shapes2',
+ title: 'Pentagon',
+ img: img,
+ index: 5,
+ callback: function () { this.setMode('pentagon'); }
+ },
+ hexagon: {
+ icon: 'activate',
+ group: 'shapes2',
+ title: 'Hexagon',
+ img: img,
+ index: 6,
+ callback: function () { this.setMode('hexagon'); }
+ }
+ });
+
+ // extend functions
+ $.fn.wPaint.extend({
+ /****************************************
+ * roundedRect
+ ****************************************/
+ _drawRoundedRectDown: function (e) { this._drawShapeDown(e); },
+
+ _drawRoundedRectMove: function (e) {
+ this._drawShapeMove(e);
+
+ var radius = e.w > e.h ? e.h / e.w : e.w / e.h;
+
+ this.ctxTemp.roundedRect(e.x, e.y, e.w, e.h, Math.ceil(radius * (e.w * e.h * 0.001)));
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawRoundedRectUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * square
+ ****************************************/
+ _drawSquareDown: function (e) { this._drawShapeDown(e); },
+
+ _drawSquareMove: function (e) {
+ this._drawShapeMove(e);
+
+ var l = e.w > e.h ? e.h : e.w;
+
+ this.ctxTemp.rect(e.x, e.y, l, l);
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawSquareUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * roundedSquare
+ ****************************************/
+ _drawRoundedSquareDown: function (e) { this._drawShapeDown(e); },
+
+ _drawRoundedSquareMove: function (e) {
+ this._drawShapeMove(e);
+
+ var l = e.w > e.h ? e.h : e.w;
+
+ this.ctxTemp.roundedRect(e.x, e.y, l, l, Math.ceil(l * l * 0.001));
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawRoundedSquareUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * diamond
+ ****************************************/
+ _drawDiamondDown: function (e) { this._drawShapeDown(e); },
+
+ _drawDiamondMove: function (e) {
+ this._drawShapeMove(e);
+
+ this.ctxTemp.diamond(e.x, e.y, e.w, e.h);
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawDiamondUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * circle
+ ****************************************/
+ _drawCircleDown: function (e) { this._drawShapeDown(e); },
+
+ _drawCircleMove: function (e) {
+ this._drawShapeMove(e);
+
+ var l = e.w > e.h ? e.h : e.w;
+
+ this.ctxTemp.ellipse(e.x, e.y, l, l);
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawCircleUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * pentagon
+ ****************************************/
+ _drawPentagonDown: function (e) { this._drawShapeDown(e); },
+
+ _drawPentagonMove: function (e) {
+ this._drawShapeMove(e);
+
+ this.ctxTemp.pentagon(e.x, e.y, e.w, e.h);
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawPentagonUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ },
+
+ /****************************************
+ * hexagon
+ ****************************************/
+ _drawHexagonDown: function (e) { this._drawShapeDown(e); },
+
+ _drawHexagonMove: function (e) {
+ this._drawShapeMove(e);
+
+ this.ctxTemp.hexagon(e.x, e.y, e.w, e.h);
+ this.ctxTemp.stroke();
+ this.ctxTemp.fill();
+ },
+
+ _drawHexagonUp: function (e) {
+ this._drawShapeUp(e);
+ this._addUndo();
+ }
+ });
+})(jQuery);
diff --git a/static/js/wpaint/plugins/shapes/wPaint.menu.main.shapes.min.js b/static/js/wpaint/plugins/shapes/wPaint.menu.main.shapes.min.js
new file mode 100644
index 0000000..ac765bd
--- /dev/null
+++ b/static/js/wpaint/plugins/shapes/wPaint.menu.main.shapes.min.js
@@ -0,0 +1 @@
+/*! wPaint - v2.5.0 - 2014-03-01 */!function(a){var b="plugins/shapes/img/icons-menu-main-shapes.png";a.extend(!0,a.fn.wPaint.menus.main.items,{rectangle:{group:"shapes"},roundedRect:{icon:"activate",group:"shapes",title:"Rounded Rectangle",img:b,index:0,callback:function(){this.setMode("roundedRect")}},square:{icon:"activate",group:"shapes",title:"Square",img:b,index:1,callback:function(){this.setMode("square")}},roundedSquare:{icon:"activate",group:"shapes",title:"Rounded Square",img:b,index:2,callback:function(){this.setMode("roundedSquare")}},diamond:{icon:"activate",group:"shapes",title:"Diamond",img:b,index:4,callback:function(){this.setMode("diamond")}},ellipse:{group:"shapes2"},circle:{icon:"activate",group:"shapes2",title:"Circle",img:b,index:3,callback:function(){this.setMode("circle")}},pentagon:{icon:"activate",group:"shapes2",title:"Pentagon",img:b,index:5,callback:function(){this.setMode("pentagon")}},hexagon:{icon:"activate",group:"shapes2",title:"Hexagon",img:b,index:6,callback:function(){this.setMode("hexagon")}}}),a.fn.wPaint.extend({_drawRoundedRectDown:function(a){this._drawShapeDown(a)},_drawRoundedRectMove:function(a){this._drawShapeMove(a);var b=a.w>a.h?a.h/a.w:a.w/a.h;this.ctxTemp.roundedRect(a.x,a.y,a.w,a.h,Math.ceil(b*a.w*a.h*.001)),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawRoundedRectUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawSquareDown:function(a){this._drawShapeDown(a)},_drawSquareMove:function(a){this._drawShapeMove(a);var b=a.w>a.h?a.h:a.w;this.ctxTemp.rect(a.x,a.y,b,b),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawSquareUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawRoundedSquareDown:function(a){this._drawShapeDown(a)},_drawRoundedSquareMove:function(a){this._drawShapeMove(a);var b=a.w>a.h?a.h:a.w;this.ctxTemp.roundedRect(a.x,a.y,b,b,Math.ceil(b*b*.001)),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawRoundedSquareUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawDiamondDown:function(a){this._drawShapeDown(a)},_drawDiamondMove:function(a){this._drawShapeMove(a),this.ctxTemp.diamond(a.x,a.y,a.w,a.h),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawDiamondUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawCircleDown:function(a){this._drawShapeDown(a)},_drawCircleMove:function(a){this._drawShapeMove(a);var b=a.w>a.h?a.h:a.w;this.ctxTemp.ellipse(a.x,a.y,b,b),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawCircleUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawPentagonDown:function(a){this._drawShapeDown(a)},_drawPentagonMove:function(a){this._drawShapeMove(a),this.ctxTemp.pentagon(a.x,a.y,a.w,a.h),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawPentagonUp:function(a){this._drawShapeUp(a),this._addUndo()},_drawHexagonDown:function(a){this._drawShapeDown(a)},_drawHexagonMove:function(a){this._drawShapeMove(a),this.ctxTemp.hexagon(a.x,a.y,a.w,a.h),this.ctxTemp.stroke(),this.ctxTemp.fill()},_drawHexagonUp:function(a){this._drawShapeUp(a),this._addUndo()}})}(jQuery),!function(){window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.diamond=function(a,b,c,d){return a&&b&&c&&d?(this.beginPath(),this.moveTo(a+.5*c,b),this.lineTo(a,b+.5*d),this.lineTo(a+.5*c,b+d),this.lineTo(a+c,b+.5*d),this.lineTo(a+.5*c,b),void this.closePath()):!0}),window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.ellipse=function(a,b,c,d){if(!(a&&b&&c&&d))return!0;var e=.5522848,f=c/2*e,g=d/2*e,h=a+c,i=b+d,j=a+c/2,k=b+d/2;this.beginPath(),this.moveTo(a,k),this.bezierCurveTo(a,k-g,j-f,b,j,b),this.bezierCurveTo(j+f,b,h,k-g,h,k),this.bezierCurveTo(h,k+g,j+f,i,j,i),this.bezierCurveTo(j-f,i,a,k+g,a,k),this.closePath()}),window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.hexagon=function(a,b,c,d){if(!(a&&b&&c&&d))return!0;var e=.225,f=1-e;this.beginPath(),this.moveTo(a+.5*c,b),this.lineTo(a,b+d*e),this.lineTo(a,b+d*f),this.lineTo(a+.5*c,b+d),this.lineTo(a+c,b+d*f),this.lineTo(a+c,b+d*e),this.lineTo(a+.5*c,b),this.closePath()}),window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.pentagon=function(a,b,c,d){return a&&b&&c&&d?(this.beginPath(),this.moveTo(a+c/2,b),this.lineTo(a,b+.4*d),this.lineTo(a+.2*c,b+d),this.lineTo(a+.8*c,b+d),this.lineTo(a+c,b+.4*d),this.lineTo(a+c/2,b),void this.closePath()):!0}),window.CanvasRenderingContext2D&&(CanvasRenderingContext2D.prototype.roundedRect=function(a,b,c,d,e){return a&&b&&c&&d?(e||(e=5),this.beginPath(),this.moveTo(a+e,b),this.lineTo(a+c-e,b),this.quadraticCurveTo(a+c,b,a+c,b+e),this.lineTo(a+c,b+d-e),this.quadraticCurveTo(a+c,b+d,a+c-e,b+d),this.lineTo(a+e,b+d),this.quadraticCurveTo(a,b+d,a,b+d-e),this.lineTo(a,b+e),this.quadraticCurveTo(a,b,a+e,b),void this.closePath()):!0})}(); \ No newline at end of file
diff --git a/static/js/wpaint/plugins/text/img/icons-menu-text.png b/static/js/wpaint/plugins/text/img/icons-menu-text.png
new file mode 100644
index 0000000..d7bed8c
--- /dev/null
+++ b/static/js/wpaint/plugins/text/img/icons-menu-text.png
Binary files differ
diff --git a/static/js/wpaint/plugins/text/src/wPaint.menu.text.js b/static/js/wpaint/plugins/text/src/wPaint.menu.text.js
new file mode 100644
index 0000000..5a15ac0
--- /dev/null
+++ b/static/js/wpaint/plugins/text/src/wPaint.menu.text.js
@@ -0,0 +1,227 @@
+(function ($) {
+
+ // setup menu
+ $.fn.wPaint.menus.text = {
+ img: 'plugins/text/img/icons-menu-text.png',
+ items: {
+ bold: {
+ icon: 'toggle',
+ title: 'Bold',
+ index: 0,
+ callback: function (toggle) { this.setFontBold(toggle); }
+ },
+ italic: {
+ icon: 'toggle',
+ title: 'Italic',
+ index: 1,
+ callback: function (toggle) { this.setFontItalic(toggle); }
+ },
+ /*underline: {
+ icon: 'toggle',
+ title: 'Undelrine',
+ index: 2,
+ callback: function (toggle) { this.setFontUnderline(toggle); }
+ },*/
+ fontSize: {
+ title: 'Font Size',
+ icon: 'select',
+ range: [8, 9, 10, 12, 14, 16, 20, 24, 30],
+ value: 12,
+ callback: function (size) { this.setFontSize(size); }
+ },
+ fontFamily: {
+ icon: 'select',
+ title: 'Font Family',
+ range: ['Arial', 'Courier', 'Times', 'Verdana'],
+ useRange: true,
+ value: 'Arial',
+ callback: function (family) { this.setFontFamily(family); }
+ }
+ }
+ };
+
+ // add icon to main menu
+ $.fn.wPaint.menus.main.items.text = {
+ icon: 'menu',
+ after: 'pencil',
+ title: 'Text',
+ index: 7,
+ callback: function () { this.setMode('text'); }
+ };
+
+ // extend defaults
+ $.extend($.fn.wPaint.defaults, {
+ fontSize : '12', // current font size for text input
+ fontFamily : 'Arial', // active font family for text input
+ fontBold : false, // text input bold enable/disable
+ fontItalic : false, // text input italic enable/disable
+ fontUnderline : false // text input italic enable/disable
+ });
+
+ // extend functions
+ $.fn.wPaint.extend({
+ generate: function () {
+ this.$textCalc = $('<div></div>').hide();
+
+ // make sure clicking on the text-tnput doesn't trigger another textInput
+ this.$textInput = $('<textarea class="wPaint-text-input" spellcheck="false"></textarea>')
+ .on('mousedown', this._stopPropagation)
+ .css({position: 'absolute'})
+ .hide();
+
+ $('body').append(this.$textCalc);
+ this.$el.append(this.$textInput);
+
+ this.menus.all.text = this._createMenu('text');
+ },
+
+ _init: function () {
+ var _this = this;
+
+ function inputClick() {
+ _this._drawTextIfNotEmpty();
+ _this.$textInput.hide();
+ _this.$canvasTemp.hide();
+ }
+
+ // in case we click on another element while typing - just auto set the text
+ for (var i in this.menus.all) {
+ this.menus.all[i].$menu
+ .on('click', inputClick)
+ .on('mousedown', this._stopPropagation);
+ }
+
+ // same idea here for clicking outside of the canvas area
+ $(document).on('mousedown', inputClick);
+ },
+
+ /****************************************
+ * setters
+ ****************************************/
+ setFillStyle: function (fillStyle) {
+ this.$textInput.css('color', fillStyle);
+ },
+
+ setFontSize: function (size) {
+ this.options.fontSize = parseInt(size, 10);
+ this._setFont({fontSize: size + 'px', lineHeight: size + 'px'});
+ this.menus.all.text._setSelectValue('fontSize', size);
+ },
+
+ setFontFamily: function (family) {
+ this.options.fontFamily = family;
+ this._setFont({fontFamily: family});
+ this.menus.all.text._setSelectValue('fontFamily', family);
+ },
+
+ setFontBold: function (bold) {
+ this.options.fontBold = bold;
+ this._setFont({fontWeight: (bold ? 'bold' : '')});
+ },
+
+ setFontItalic: function (italic) {
+ this.options.fontItalic = italic;
+ this._setFont({fontStyle: (italic ? 'italic' : '')});
+ },
+
+ setFontUnderline: function (underline) {
+ this.options.fontUnderline = underline;
+ this._setFont({fontWeight: (underline ? 'underline' : '')});
+ },
+
+ _setFont: function (css) {
+ this.$textInput.css(css);
+ this.$textCalc.css(css);
+ },
+
+ /****************************************
+ * Text
+ ****************************************/
+ _drawTextDown: function (e) {
+ this._drawTextIfNotEmpty();
+ this._drawShapeDown(e, 1);
+
+ this.$textInput
+ .css({left: e.pageX - 1, top: e.pageY - 1, width: 0, height: 0})
+ .show().focus();
+ },
+
+ _drawTextMove: function (e) {
+ this._drawShapeMove(e, 1);
+
+ this.$textInput.css({left: e.left - 1, top: e.top - 1, width: e.width, height: e.height});
+ },
+
+ _drawTextIfNotEmpty: function () {
+ if (this.$textInput.val() !== '') { this._drawText(); }
+ },
+
+ // just draw text - don't want to trigger up here since we are just copying text from input box here
+ _drawText: function () {
+ var fontString = '',
+ lines = this.$textInput.val().split('\n'),
+ linesNew = [],
+ textInputWidth = this.$textInput.width() - 2,
+ width = 0,
+ lastj = 0,
+ offset = this.$textInput.position(),
+ left = offset.left + 1,
+ top = offset.top + 1,
+ //underlineOffset = 0,
+ i, ii, j, jj;
+
+ if (this.options.fontItalic) { fontString += 'italic '; }
+ //if(this.settings.fontUnderline) { fontString += 'underline '; }
+ if (this.options.fontBold) { fontString += 'bold '; }
+
+ fontString += this.options.fontSize + 'px ' + this.options.fontFamily;
+
+ for (i = 0, ii = lines.length; i < ii; i++) {
+ this.$textCalc.html('');
+ lastj = 0;
+
+ for (j = 0, jj = lines[0].length; j < jj; j++) {
+ width = this.$textCalc.append(lines[i][j]).width();
+
+ if (width > textInputWidth) {
+ linesNew.push(lines[i].substring(lastj, j));
+ lastj = j;
+ this.$textCalc.html(lines[i][j]);
+ }
+ }
+
+ if (lastj !== j) { linesNew.push(lines[i].substring(lastj, j)); }
+ }
+
+ lines = this.$textInput.val(linesNew.join('\n')).val().split('\n');
+
+ for (i = 0, ii = lines.length; i < ii; i++) {
+ this.ctx.fillStyle = this.options.fillStyle;
+ this.ctx.textBaseline = 'top';
+ this.ctx.font = fontString;
+ this.ctx.fillText(lines[i], left, top);
+
+ top += this.options.fontSize;
+
+ /*if(lines[i] !== '' && this.options.fontTypeUnderline) {
+ width = this.$textCalc.html(lines[i]).width();
+
+ //manually set pixels for underline since to avoid antialiasing 1px issue, and lack of support for underline in canvas
+ var imgData = this.ctx.getImageData(0, top+underlineOffset, width, 1);
+
+ for (j=0; j<imgData.width*imgData.height*4; j+=4) {
+ imgData.data[j] = parseInt(this.options.fillStyle.substring(1,3), 16);
+ imgData.data[j+1] = parseInt(this.options.fillStyle.substring(3,5), 16);
+ imgData.data[j+2] = parseInt(this.options.fillStyle.substring(5,7), 16);
+ imgData.data[j+3] = 255;
+ }
+
+ this.ctx.putImageData(imgData, left, top+underlineOffset);
+ }*/
+ }
+
+ this.$textInput.val('');
+ this._addUndo();
+ }
+ });
+})(jQuery);
diff --git a/static/js/wpaint/plugins/text/wPaint.menu.text.min.js b/static/js/wpaint/plugins/text/wPaint.menu.text.min.js
new file mode 100644
index 0000000..6cd1f3d
--- /dev/null
+++ b/static/js/wpaint/plugins/text/wPaint.menu.text.min.js
@@ -0,0 +1 @@
+/*! wPaint - v2.5.0 - 2014-03-01 */!function(a){a.fn.wPaint.menus.text={img:"plugins/text/img/icons-menu-text.png",items:{bold:{icon:"toggle",title:"Bold",index:0,callback:function(a){this.setFontBold(a)}},italic:{icon:"toggle",title:"Italic",index:1,callback:function(a){this.setFontItalic(a)}},fontSize:{title:"Font Size",icon:"select",range:[8,9,10,12,14,16,20,24,30],value:12,callback:function(a){this.setFontSize(a)}},fontFamily:{icon:"select",title:"Font Family",range:["Arial","Courier","Times","Verdana"],useRange:!0,value:"Arial",callback:function(a){this.setFontFamily(a)}}}},a.fn.wPaint.menus.main.items.text={icon:"menu",after:"pencil",title:"Text",index:7,callback:function(){this.setMode("text")}},a.extend(a.fn.wPaint.defaults,{fontSize:"12",fontFamily:"Arial",fontBold:!1,fontItalic:!1,fontUnderline:!1}),a.fn.wPaint.extend({generate:function(){this.$textCalc=a("<div></div>").hide(),this.$textInput=a('<textarea class="wPaint-text-input" spellcheck="false"></textarea>').on("mousedown",this._stopPropagation).css({position:"absolute"}).hide(),a("body").append(this.$textCalc),this.$el.append(this.$textInput),this.menus.all.text=this._createMenu("text")},_init:function(){function b(){c._drawTextIfNotEmpty(),c.$textInput.hide(),c.$canvasTemp.hide()}var c=this;for(var d in this.menus.all)this.menus.all[d].$menu.on("click",b).on("mousedown",this._stopPropagation);a(document).on("mousedown",b)},setFillStyle:function(a){this.$textInput.css("color",a)},setFontSize:function(a){this.options.fontSize=parseInt(a,10),this._setFont({fontSize:a+"px",lineHeight:a+"px"}),this.menus.all.text._setSelectValue("fontSize",a)},setFontFamily:function(a){this.options.fontFamily=a,this._setFont({fontFamily:a}),this.menus.all.text._setSelectValue("fontFamily",a)},setFontBold:function(a){this.options.fontBold=a,this._setFont({fontWeight:a?"bold":""})},setFontItalic:function(a){this.options.fontItalic=a,this._setFont({fontStyle:a?"italic":""})},setFontUnderline:function(a){this.options.fontUnderline=a,this._setFont({fontWeight:a?"underline":""})},_setFont:function(a){this.$textInput.css(a),this.$textCalc.css(a)},_drawTextDown:function(a){this._drawTextIfNotEmpty(),this._drawShapeDown(a,1),this.$textInput.css({left:a.pageX-1,top:a.pageY-1,width:0,height:0}).show().focus()},_drawTextMove:function(a){this._drawShapeMove(a,1),this.$textInput.css({left:a.left-1,top:a.top-1,width:a.width,height:a.height})},_drawTextIfNotEmpty:function(){""!==this.$textInput.val()&&this._drawText()},_drawText:function(){var a,b,c,d,e="",f=this.$textInput.val().split("\n"),g=[],h=this.$textInput.width()-2,i=0,j=0,k=this.$textInput.position(),l=k.left+1,m=k.top+1;for(this.options.fontItalic&&(e+="italic "),this.options.fontBold&&(e+="bold "),e+=this.options.fontSize+"px "+this.options.fontFamily,a=0,b=f.length;b>a;a++){for(this.$textCalc.html(""),j=0,c=0,d=f[0].length;d>c;c++)i=this.$textCalc.append(f[a][c]).width(),i>h&&(g.push(f[a].substring(j,c)),j=c,this.$textCalc.html(f[a][c]));j!==c&&g.push(f[a].substring(j,c))}for(f=this.$textInput.val(g.join("\n")).val().split("\n"),a=0,b=f.length;b>a;a++)this.ctx.fillStyle=this.options.fillStyle,this.ctx.textBaseline="top",this.ctx.font=e,this.ctx.fillText(f[a],l,m),m+=this.options.fontSize;this.$textInput.val(""),this._addUndo()}})}(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/src/wPaint.css b/static/js/wpaint/src/wPaint.css
new file mode 100644
index 0000000..7bc0a70
--- /dev/null
+++ b/static/js/wpaint/src/wPaint.css
@@ -0,0 +1,348 @@
+/**********************************************************************
+ * Layout
+ **********************************************************************/
+
+/*** menu ***/
+.wPaint-menu {
+ position: absolute !important;
+ display: inline-block;
+ line-height: 0px;
+ z-index: 99;
+}
+.wPaint-menu-behind {
+ z-index: 98;
+}
+.wPaint-menu-holder {
+ position: relative;
+ margin: 0 1px 1px 0;
+}
+.wPaint-menu-handle {
+ display: inline-block;
+}
+.wPaint-menu-icon {
+ position: relative;
+ vertical-align: top;
+}
+.wPaint-menu-icon-img {
+ position: relative;
+ display: inline-block;
+ background-repeat: no-repeat;
+ overflow: hidden;
+}
+/*** select ***/
+.wPaint-menu-select-holder{
+ position: absolute;
+ left: 1px;
+ z-index: 10;
+ overflow: hidden;
+}
+.wPaint-menu-select {
+ position: relative;
+ text-align: center;
+ overflow-y: scroll;
+ z-index: 100;
+}
+.wPaint-menu-select-option.first {
+ border-top: 0px;
+}
+/*** alignment ***/
+.wPaint-menu-alignment-horizontal .wPaint-menu-icon {
+ display: inline-block;
+}
+.wPaint-menu-alignment-vertical .wPaint-menu-icon {
+ display: block;
+}
+/*** status ***/
+.wPaint-status {
+ position: absolute;
+ display: none;
+ right: 0px;
+ bottom: 0px;
+}
+/*** modal ***/
+.wPaint-modal-bg {
+ position: absolute;
+ left: 0px;
+ top: 0px;
+ width: 100%;
+ height: 100%;
+}
+.wPaint-modal {
+ position: absolute;
+ display: inline-block;
+}
+.wPaint-modal-holder {
+ display: inline-block;
+ overflow: hidden;
+}
+.wPaint-modal-content {
+ overflow-y: scroll;
+ width: 100%;
+ height: 100%;
+}
+.wPaint-modal-close {
+ position: absolute;
+}
+/*** text input ***/
+.wPaint-text-input{
+ margin: 0px;
+ padding: 0px;
+ outline-width: 0;
+ word-wrap: break-word;
+ overflow: hidden;
+}
+/*** file load ***/
+.wPaint-modal-img-holder {
+ line-height: 0px;
+}
+.wPaint-modal-img {
+ display: inline-block;
+}
+
+/**********************************************************************
+ * Generic Appearance
+ *
+ * Probably don't need to change these styles but can overwrite
+ * whatever is necessary.
+ **********************************************************************/
+
+/*** menu ***/
+.wPaint-menu-holder {
+ border-style: solid;
+ border-width: 1px;
+ box-shadow:3px 3px 5px #555555;
+}
+.wPaint-menu-handle {
+ cursor: pointer;
+}
+.wPaint-menu-icon {
+ border-style: solid;
+ border-width: 1px;
+ cursor: pointer;
+}
+.wPaint-menu-icon.disabled {
+ cursor: default;
+}
+.wPaint-menu-icon.disabled .wPaint-menu-icon-img {
+ opacity: 0.3;
+}
+.wPaint-menu-icon-img {
+ font-family: verdana;
+ font-weight: bold;
+ text-align: center;
+}
+/*** select ***/
+.wPaint-menu-select-holder {
+ border-style: solid;
+ border-width: 1px;
+ box-shadow: 1px 1px 2px #666;
+}
+.wPaint-menu-select {
+ font-family: verdana;
+ text-align: center;
+}
+.wPaint-menu-select-option {
+ border-top-style: solid;
+ border-top-width: 1px;
+ cursor: pointer;
+}
+.wPaint-menu-icon-select-img {
+ background-repeat: no-repeat;
+}
+.wPaint-menu-icon-group-arrow {
+ position: absolute;
+ right: 1px;
+ bottom: 1px;
+}
+/*** alignment ***/
+.wPaint-menu-alignment-horizontal .wPaint-menu-handle {
+ border-right-style: solid;
+ border-right-width: 1px;
+}
+.wPaint-menu-alignment-vertical .wPaint-menu-handle {
+ border-bottom-style: solid;
+ border-bottom-width: 1px;
+}
+/*** status ***/
+.wPaint-status {
+ font-size: 10px;
+ font-family: verdana;
+ line-height: 10px;
+ height: 10px;
+ background-color: #3a3a3a;
+ color: #f0f0f0;
+ padding: 5px;
+ opacity: 0.5;
+}
+/*** modal ***/
+.wPaint-modal-bg {
+ background-color: #3a3a3a;
+ opacity: 0.8;
+}
+.wPaint-modal-holder {
+ height: 100px;
+ box-shadow: 3px 3px 5px #555555;
+ border-radius: 5px;
+ border-style: solid;
+ border-width: 2px;
+ cursor: default;
+}
+.wPaint-modal-close {
+ right: -7px;
+ top: -7px;
+ border-radius: 10px;
+ font-size: 8px;
+ line-height: 14px;
+ padding: 0 4px;
+ font-weight:bold;
+ border-style: solid;
+ border-width: 2px;
+ cursor: pointer;
+}
+/*** text input ***/
+.wPaint-text-input{
+ border: dotted #0000FF 1px;
+ background: none;
+}
+/*** file load ***/
+.wPaint-modal-img-holder {
+ border: solid #333 1px;
+ border-radius: 5px;
+ margin: 3px;
+ padding: 2px;
+ cursor: pointer;
+}
+.wPaint-modal-img {
+ width: 100px;
+ border-radius: 4px;
+ margin-bottom: 0px;
+}
+
+/**********************************************************************
+ * Size - standard theme
+ **********************************************************************/
+
+/*** menu ***/
+.wPaint-theme-standard .wPaint-menu-holder {
+ border-radius: 7px;
+}
+.wPaint-theme-standard .wPaint-menu-select-holder {
+ border-radius: 5px;
+}
+.wPaint-theme-standard .wPaint-menu-icon {
+ border-radius: 7px;
+}
+.wPaint-theme-standard .wPaint-menu-icon-img {
+ margin: 6px 5px 5px 6px;
+ width: 18px;
+ height: 18px;
+ line-height: 18px;
+ font-size: 12px;
+}
+.wPaint-theme-standard .wPaint-menu-colorpicker .wPaint-menu-icon-img {
+ margin: 3px 2px 2px 3px;
+ width: 24px;
+ height: 24px;
+ border-radius: 5px;
+}
+/*** select ***/
+.wPaint-theme-standard .wPaint-menu-icon-group .wPaint-menu-select-option {
+ padding: 4px;
+}
+.wPaint-theme-standard .wPaint-menu-icon-group-arrow {
+ width: 5px;
+ height: 3px;
+ background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAADCAYAAABbNsX4AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOC8xMS8xMyj8hykAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAKElEQVQImV3IwQ0AMAyDQKerspZ3pa9IVXmdGMB8nbbzjrYTNWoA1xeQ3RPyxUyE/gAAAABJRU5ErkJggg==');
+}
+.wPaint-theme-standard .wPaint-menu-select {
+ line-height: 10px;
+ font-size: 10px;
+ max-height: 136px;
+}
+.wPaint-theme-standard .wPaint-menu-select-option {
+ max-width: 50px;
+ padding: 4px 7px;
+}
+.wPaint-theme-standard .wPaint-menu-icon-select-img {
+ width: 18px;
+ height: 18px;
+}
+/* horizontal */
+.wPaint-theme-standard .wPaint-menu-alignment-horizontal.wPaint-menu-nohandle .wPaint-menu-holder {
+ padding-left: 4px;
+}
+.wPaint-theme-standard .wPaint-menu-alignment-horizontal .wPaint-menu-icon {
+ margin: 4px 5px 4px 0;
+}
+.wPaint-theme-standard .wPaint-menu-alignment-horizontal .wPaint-menu-handle {
+ width: 30px;
+ height: 39px;
+ margin-right: 5px;
+ border-top-left-radius: 7px;
+ border-bottom-left-radius: 7px;
+}
+/* vertical */
+.wPaint-theme-standard .wPaint-menu-alignment-vertical.wPaint-menu-nohandle .wPaint-menu-holder {
+ padding-top: 4px;
+}
+.wPaint-theme-standard .wPaint-menu-alignment-vertical .wPaint-menu-icon {
+ margin: 0 4px 5px 4px;
+}
+.wPaint-theme-standard .wPaint-menu-alignment-vertical .wPaint-menu-handle {
+ width: 39px;
+ height: 30px;
+ margin-bottom: 5px;
+ border-top-left-radius: 7px;
+ border-top-right-radius: 7px;
+}
+
+/**********************************************************************
+ * Style - classic theme
+ **********************************************************************/
+
+/*** menu ***/
+.wPaint-theme-classic .wPaint-menu-holder {
+ border-color: #dadada;
+ background-color: #f0f0f0;
+}
+.wPaint-theme-classic .wPaint-menu-handle {
+ background-color: #dadada;
+ box-shadow: inset 1px 1px 3px #FFF;
+ border-color: #dadada;
+}
+.wPaint-theme-classic .wPaint-menu-icon {
+ border-color: #b9b9b9;
+ background-color: #b9b9b9;
+ box-shadow: inset 2px 2px 3px #eee, 1px 1px 2px #666;
+}
+.wPaint-theme-classic .wPaint-menu-icon.hover,
+.wPaint-theme-classic .wPaint-menu-icon.active {
+ border-color: #99ccff;
+ background-color: #aaccff;
+}
+.wPaint-theme-classic .wPaint-menu-icon-img {
+ color: #696969;
+}
+/*** select ***/
+.wPaint-theme-classic .wPaint-menu-select-holder {
+ border-color: #CACACA;
+}
+.wPaint-theme-classic .wPaint-menu-select {
+ color: #494949;
+}
+.wPaint-theme-classic .wPaint-menu-select-option {
+ box-shadow: inset 2px 2px 3px #fff;
+ border-top-color: #CACACA;
+ background-color: #F0F0F0;
+}
+.wPaint-theme-classic .wPaint-menu-select-option:hover {
+ box-shadow: inset 1px 1px 1px #fff;
+ background-color: #99ccff;
+ color: #f0f0f0;
+}
+/*** modal ***/
+.wPaint-theme-classic .wPaint-modal-close,
+.wPaint-theme-classic .wPaint-modal-holder {
+ border-color: #3a3a3a;
+ background-color: #f0f0f0;
+}
diff --git a/static/js/wpaint/src/wPaint.js b/static/js/wpaint/src/wPaint.js
new file mode 100644
index 0000000..9717f6d
--- /dev/null
+++ b/static/js/wpaint/src/wPaint.js
@@ -0,0 +1,1181 @@
+(function ($) {
+ 'use strict';
+
+ /************************************************************************
+ * Paint class
+ ************************************************************************/
+ function Paint(el, options) {
+ this.$el = $(el);
+ this.options = options;
+ this.init = false;
+
+ this.menus = {primary: null, active: null, all: {}};
+ this.previousMode = null;
+ this.width = this.$el.width();
+ this.height = this.$el.height();
+
+ this.ctxBgResize = false;
+ this.ctxResize = false;
+
+ this.generate();
+ this._init();
+ }
+
+ Paint.prototype = {
+ generate: function () {
+ if (this.init) { return this; }
+
+ var _this = this;
+
+ // automatically appends each canvas
+ // also returns the jQuery object so we can chain events right off the function call.
+ // for the tempCanvas we will be setting some extra attributes but don't won't matter
+ // as they will be reset on mousedown anyway.
+ function createCanvas(name) {
+ var newName = (name ? name.capitalize() : ''),
+ canvasName = 'canvas' + newName,
+ ctxName = 'ctx' + newName;
+
+ _this[canvasName] = document.createElement('canvas');
+ _this[ctxName] = _this[canvasName].getContext('2d');
+ _this['$' + canvasName] = $(_this[canvasName]);
+
+ _this['$' + canvasName]
+ .attr('class', 'wPaint-canvas' + (name ? '-' + name : ''))
+ .attr('width', _this.width + 'px')
+ .attr('height', _this.height + 'px')
+ .css({position: 'absolute', left: 0, top: 0});
+
+ _this.$el.append(_this['$' + canvasName]);
+
+ return _this['$' + canvasName];
+ }
+
+ // event functions
+ function canvasMousedown(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ _this.draw = true;
+ e.canvasEvent = 'down';
+ _this._closeSelectBoxes();
+ _this._callShapeFunc.apply(_this, [e]);
+ }
+
+ function documentMousemove(e) {
+ if (_this.draw) {
+ e.canvasEvent = 'move';
+ _this._callShapeFunc.apply(_this, [e]);
+ }
+ }
+
+ function documentMouseup(e) {
+
+ //make sure we are in draw mode otherwise this will fire on any mouse up.
+ if (_this.draw) {
+ _this.draw = false;
+ e.canvasEvent = 'up';
+ _this._callShapeFunc.apply(_this, [e]);
+ }
+ }
+
+ // create bg canvases
+ createCanvas('bg');
+
+ // create drawing canvas
+ createCanvas('')
+ .on('mousedown', canvasMousedown)
+ .bindMobileEvents();
+
+ // create temp canvas for drawing shapes temporarily
+ // before transfering to main canvas
+ createCanvas('temp').hide();
+
+ // event handlers for drawing
+ $(document)
+ .on('mousemove', documentMousemove)
+ .on('mousedown', $.proxy(this._closeSelectBoxes, this))
+ .on('mouseup', documentMouseup);
+
+ // we will need to preset theme to get proper dimensions
+ // when creating menus which will be appended after this
+ this.setTheme(this.options.theme);
+ },
+
+ _init: function () {
+ var index = null,
+ setFuncName = null;
+
+ this.init = true;
+
+ // run any set functions if they exist
+ for (index in this.options) {
+ setFuncName = 'set' + index.capitalize();
+ if (this[setFuncName]) { this[setFuncName](this.options[index]); }
+ }
+
+ // fix menus
+ this._fixMenus();
+
+ // initialize active menu button
+ this.menus.primary._getIcon(this.options.mode).trigger('click');
+ },
+
+ resize: function () {
+ var bg = this.getBg(),
+ image = this.getImage();
+
+ this.width = this.$el.width();
+ this.height = this.$el.height();
+
+ this.canvasBg.width = this.width;
+ this.canvasBg.height = this.height;
+ this.canvas.width = this.width;
+ this.canvas.height = this.height;
+
+ if (this.ctxBgResize === false) {
+ this.ctxBgResize = true;
+ this.setBg(bg, true);
+ }
+
+ if (this.ctxResize === false) {
+ this.ctxResize = true;
+ this.setImage(image, '', true, true);
+ }
+ },
+
+ /************************************
+ * setters
+ ************************************/
+ setTheme: function (theme) {
+ var i, ii;
+
+ theme = theme.split(' ');
+
+ // remove anything beginning with "wPaint-theme-" first
+ this.$el.attr('class', (this.$el.attr('class') || '').replace(/wPaint-theme-.+\s|wPaint-theme-.+$/, ''));
+
+ // add each theme
+ for (i = 0, ii = theme.length; i < ii; i++) {
+ this.$el.addClass('wPaint-theme-' + theme[i]);
+ }
+ },
+
+ setMode: function (mode) {
+ this.setCursor(mode);
+ this.previousMode = this.options.mode;
+ this.options.mode = mode;
+ },
+
+ setImage: function (img, ctxType, resize, notUndo) {
+ if (!img) { return true; }
+
+ var _this = this,
+ myImage = null,
+ ctx = '';
+
+ function loadImage() {
+ var ratio = 1, xR = 0, yR = 0, x = 0, y = 0, w = myImage.width, h = myImage.height;
+
+ if (!resize) {
+ // get width/height
+ if (myImage.width > _this.width || myImage.height > _this.height || _this.options.imageStretch) {
+ xR = _this.width / myImage.width;
+ yR = _this.height / myImage.height;
+
+ ratio = xR < yR ? xR : yR;
+
+ w = myImage.width * ratio;
+ h = myImage.height * ratio;
+ }
+
+ // get left/top (centering)
+ x = (_this.width - w) / 2;
+ y = (_this.height - h) / 2;
+ }
+
+ ctx.clearRect(0, 0, _this.width, _this.height);
+ ctx.drawImage(myImage, x, y, w, h);
+
+ _this[ctxType + 'Resize'] = false;
+
+ // Default is to run the undo.
+ // If it's not to be run set it the flag to true.
+ if (!notUndo) {
+ _this._addUndo();
+ }
+ }
+
+ ctxType = 'ctx' + (ctxType || '').capitalize();
+ ctx = this[ctxType];
+
+ if (window.rgbHex(img)) {
+ ctx.clearRect(0, 0, this.width, this.height);
+ ctx.fillStyle = img;
+ ctx.rect(0, 0, this.width, this.height);
+ ctx.fill();
+ }
+ else {
+ myImage = new Image();
+ myImage.src = img.toString();
+ $(myImage).load(loadImage);
+ }
+ },
+
+ setBg: function (img, resize) {
+ if (!img) { return true; }
+
+ this.setImage(img, 'bg', resize, true);
+ },
+
+ setCursor: function (cursor) {
+ cursor = $.fn.wPaint.cursors[cursor] || $.fn.wPaint.cursors['default'];
+
+ this.$el.css('cursor', 'url("' + this.options.path + cursor.path + '") ' + cursor.left + ' ' + cursor.top + ', default');
+ },
+
+ setMenuOrientation: function (orientation) {
+ $.each(this.menus.all, function (i, menu) {
+ menu.options.aligment = orientation;
+ menu.setAlignment(orientation);
+ });
+ },
+
+ getImage: function (withBg) {
+ var canvasSave = document.createElement('canvas'),
+ ctxSave = canvasSave.getContext('2d');
+
+ withBg = withBg === false ? false : true;
+
+ $(canvasSave)
+ .css({display: 'none', position: 'absolute', left: 0, top: 0})
+ .attr('width', this.width)
+ .attr('height', this.height);
+
+ if (withBg) { ctxSave.drawImage(this.canvasBg, 0, 0); }
+ ctxSave.drawImage(this.canvas, 0, 0);
+
+ return canvasSave.toDataURL();
+ },
+
+ getBg: function () {
+ return this.canvasBg.toDataURL();
+ },
+
+ /************************************
+ * prompts
+ ************************************/
+ _displayStatus: function (msg) {
+ var _this = this;
+
+ if (!this.$status) {
+ this.$status = $('<div class="wPaint-status"></div>');
+ this.$el.append(this.$status);
+ }
+
+ this.$status.html(msg);
+ clearTimeout(this.displayStatusTimer);
+
+ this.$status.fadeIn(500, function () {
+ _this.displayStatusTimer = setTimeout(function () { _this.$status.fadeOut(500); }, 1500);
+ });
+ },
+
+ _showModal: function ($content) {
+ var _this = this,
+ $bg = this.$el.children('.wPaint-modal-bg'),
+ $modal = this.$el.children('.wPaint-modal');
+
+ function modalFadeOut() {
+ $bg.remove();
+ $modal.remove();
+ _this._createModal($content);
+ }
+
+ if ($bg.length) {
+ $modal.fadeOut(500, modalFadeOut);
+ }
+ else {
+ this._createModal($content);
+ }
+ },
+
+ _createModal: function ($content) {
+ $content = $('<div class="wPaint-modal-content"></div>').append($content.children());
+
+ var $bg = $('<div class="wPaint-modal-bg"></div>'),
+ $modal = $('<div class="wPaint-modal"></div>'),
+ $holder = $('<div class="wPaint-modal-holder"></div>'),
+ $close = $('<div class="wPaint-modal-close">X</div>');
+
+ function modalClick() {
+ $modal.fadeOut(500, modalFadeOut);
+ }
+
+ function modalFadeOut() {
+ $bg.remove();
+ $modal.remove();
+ }
+
+ $close.on('click', modalClick);
+ $modal.append($holder.append($content)).append($close);
+ this.$el.append($bg).append($modal);
+
+ $modal.css({
+ left: (this.$el.outerWidth() / 2) - ($modal.outerWidth(true) / 2),
+ top: (this.$el.outerHeight() / 2) - ($modal.outerHeight(true) / 2)
+ });
+
+ $modal.fadeIn(500);
+ },
+
+ /************************************
+ * menu helpers
+ ************************************/
+ _createMenu: function (name, options) {
+ options = options || {};
+ options.alignment = this.options.menuOrientation;
+ options.handle = this.options.menuHandle;
+
+ return new Menu(this, name, options);
+ },
+
+ _fixMenus: function () {
+ var _this = this,
+ $selectHolder = null;
+
+ function selectEach(i, el) {
+ var $el = $(el),
+ $select = $el.clone();
+
+ $select.appendTo(_this.$el);
+
+ if ($select.outerHeight() === $select.get(0).scrollHeight) {
+ $el.css({overflowY: 'auto'});
+ }
+
+ $select.remove();
+ }
+
+ // TODO: would be nice to do this better way
+ // for some reason when setting overflowY:auto with dynamic content makes the width act up
+ for (var key in this.menus.all) {
+ $selectHolder = _this.menus.all[key].$menu.find('.wPaint-menu-select-holder');
+ if ($selectHolder.length) { $selectHolder.children().each(selectEach); }
+ }
+ },
+
+ _closeSelectBoxes: function (item) {
+ var key, $selectBoxes;
+
+ for (key in this.menus.all) {
+ $selectBoxes = this.menus.all[key].$menuHolder.children('.wPaint-menu-icon-select');
+
+ // hide any open select menus excluding the current menu
+ // this is to avoid the double toggle since there are some
+ // other events running here
+ if (item) { $selectBoxes = $selectBoxes.not('.wPaint-menu-icon-name-' + item.name); }
+
+ $selectBoxes.children('.wPaint-menu-select-holder').hide();
+ }
+ },
+
+ /************************************
+ * events
+ ************************************/
+ //_imageOnload: function () {
+ // /* a blank helper function for post image load calls on canvas - can be extended by other plugins using the setImage called */
+ //},
+
+ _callShapeFunc: function (e) {
+
+ // TODO: this is where issues with mobile offsets are probably off
+ var canvasOffset = this.$canvas.offset(),
+ canvasEvent = e.canvasEvent.capitalize(),
+ func = '_draw' + this.options.mode.capitalize() + canvasEvent;
+
+ // update offsets here since we are detecting mouseup on $(document) not on the canvas
+ e.pageX = Math.floor(e.pageX - canvasOffset.left);
+ e.pageY = Math.floor(e.pageY - canvasOffset.top);
+
+ // call drawing func
+ if (this[func]) { this[func].apply(this, [e]); }
+
+ // run callback if set
+ if (this.options['draw' + canvasEvent]) { this.options['_draw' + canvasEvent].apply(this, [e]); }
+
+ // run options (user) callback if set
+ if (canvasEvent === 'Down' && this.options.onShapeDown) { this.options.onShapeDown.apply(this, [e]); }
+ else if (canvasEvent === 'Move' && this.options.onShapeMove) { this.options.onShapeMove.apply(this, [e]); }
+ else if (canvasEvent === 'Up' && this.options.onShapeUp) { this.options.onShapeUp.apply(this, [e]); }
+ },
+
+ _stopPropagation: function (e) {
+ e.stopPropagation();
+ },
+
+ /************************************
+ * shape helpers
+ ************************************/
+ _drawShapeDown: function (e) {
+ this.$canvasTemp
+ .css({left: e.PageX, top: e.PageY})
+ .attr('width', 0)
+ .attr('height', 0)
+ .show();
+
+ this.canvasTempLeftOriginal = e.pageX;
+ this.canvasTempTopOriginal = e.pageY;
+ },
+
+ _drawShapeMove: function (e, factor) {
+ var xo = this.canvasTempLeftOriginal,
+ yo = this.canvasTempTopOriginal;
+
+ // we may need these in other funcs, so we'll just pass them along with the event
+ factor = factor || 2;
+ e.left = (e.pageX < xo ? e.pageX : xo);
+ e.top = (e.pageY < yo ? e.pageY : yo);
+ e.width = Math.abs(e.pageX - xo);
+ e.height = Math.abs(e.pageY - yo);
+ e.x = this.options.lineWidth / 2 * factor;
+ e.y = this.options.lineWidth / 2 * factor;
+ e.w = e.width - this.options.lineWidth * factor;
+ e.h = e.height - this.options.lineWidth * factor;
+
+ $(this.canvasTemp)
+ .css({left: e.left, top: e.top})
+ .attr('width', e.width)
+ .attr('height', e.height);
+
+ // store these for later to use in our "up" call
+ this.canvasTempLeftNew = e.left;
+ this.canvasTempTopNew = e.top;
+
+ factor = factor || 2;
+
+ // TODO: set this globally in _drawShapeDown (for some reason colors are being reset due to canvas resize - is there way to permanently set it)
+ this.ctxTemp.fillStyle = this.options.fillStyle;
+ this.ctxTemp.strokeStyle = this.options.strokeStyle;
+ this.ctxTemp.lineWidth = this.options.lineWidth * factor;
+ },
+
+ _drawShapeUp: function () {
+ this.ctx.drawImage(this.canvasTemp, this.canvasTempLeftNew, this.canvasTempTopNew);
+ this.$canvasTemp.hide();
+ },
+
+ /****************************************
+ * dropper
+ ****************************************/
+ _drawDropperDown: function (e) {
+ var pos = {x: e.pageX, y: e.pageY},
+ pixel = this._getPixel(this.ctx, pos),
+ color = null;
+
+ // if we get no color try getting from the background
+ //if(pixel.r === 0 && pixel.g === 0 && pixel.b === 0 && pixel.a === 0) {
+ // imageData = this.ctxBg.getImageData(0, 0, this.width, this.height)
+ // pixel = this._getPixel(imageData, pos);
+ //}
+
+ color = 'rgba(' + [ pixel.r, pixel.g, pixel.b, pixel.a ].join(',') + ')';
+
+ // set color from dropper here
+ this.options[this.dropper] = color;
+ this.menus.active._getIcon(this.dropper).wColorPicker('color', color);
+ },
+
+ _drawDropperUp: function () {
+ this.setMode(this.previousMode);
+ },
+
+ // get pixel data represented as RGBa color from pixel array.
+ _getPixel: function (ctx, pos) {
+ var imageData = ctx.getImageData(0, 0, this.width, this.height),
+ pixelArray = imageData.data,
+ base = ((pos.y * imageData.width) + pos.x) * 4;
+
+ return {
+ r: pixelArray[base],
+ g: pixelArray[base + 1],
+ b: pixelArray[base + 2],
+ a: pixelArray[base + 3]
+ };
+ }
+ };
+
+ /************************************************************************
+ * Menu class
+ ************************************************************************/
+ function Menu(wPaint, name, options) {
+ this.wPaint = wPaint;
+ this.options = options;
+ this.name = name;
+ this.type = !wPaint.menus.primary ? 'primary' : 'secondary';
+ this.docked = true;
+ this.dockOffset = {left: 0, top: 0};
+
+ this.generate();
+ }
+
+ Menu.prototype = {
+ generate: function () {
+ this.$menu = $('<div class="wPaint-menu"></div>');
+ this.$menuHolder = $('<div class="wPaint-menu-holder wPaint-menu-name-' + this.name + '"></div>');
+
+ if (this.options.handle) { this.$menuHandle = this._createHandle(); }
+ else { this.$menu.addClass('wPaint-menu-nohandle'); }
+
+ if (this.type === 'primary') {
+
+ // store the primary menu in primary object - we will need this reference later
+ this.wPaint.menus.primary = this;
+
+ this.setOffsetLeft(this.options.offsetLeft);
+ this.setOffsetTop(this.options.offsetTop);
+ }
+ else if (this.type === 'secondary') {
+ this.$menu.hide();
+ }
+
+ // append menu items
+ this.$menu.append(this.$menuHolder.append(this.$menuHandle));
+ this.reset();
+
+ // append menu
+ this.wPaint.$el.append(this.$menu);
+
+ this.setAlignment(this.options.alignment);
+ },
+
+ // create / reset menu - will add new entries in the array
+ reset: function () {
+ var _this = this,
+ menu = $.fn.wPaint.menus[this.name],
+ key;
+
+ // self invoking function
+ function itemAppend(item) { _this._appendItem(item); }
+
+ for (key in menu.items) {
+
+ // only add unique (new) items (icons)
+ if (!this.$menuHolder.children('.wPaint-menu-icon-name-' + key).length) {
+
+ // add the item name, we will need this internally
+ menu.items[key].name = key;
+
+ // use default img if img not set
+ menu.items[key].img = _this.wPaint.options.path + (menu.items[key].img || menu.img);
+
+ // make self invoking to avoid overwrites
+ (itemAppend)(menu.items[key]);
+ }
+ }
+ },
+
+ _appendItem: function (item) {
+ var $item = this['_createIcon' + item.icon.capitalize()](item);
+
+ if (item.after) {
+ this.$menuHolder.children('.wPaint-menu-icon-name-' + item.after).after($item);
+ }
+ else {
+ this.$menuHolder.append($item);
+ }
+ },
+
+ /************************************
+ * setters
+ ************************************/
+ setOffsetLeft: function (left) {
+ this.$menu.css({left: left});
+ },
+
+ setOffsetTop: function (top) {
+ this.$menu.css({top: top});
+ },
+
+ setAlignment: function (alignment) {
+ var tempLeft = this.$menu.css('left');
+
+ this.$menu.attr('class', this.$menu.attr('class').replace(/wPaint-menu-alignment-.+\s|wPaint-menu-alignment-.+$/, ''));
+ this.$menu.addClass('wPaint-menu-alignment-' + alignment);
+
+ this.$menu.width('auto').css('left', -10000);
+ this.$menu.width(this.$menu.width()).css('left', tempLeft);
+
+ // set proper offsets based on alignment
+ if (this.type === 'secondary') {
+ if (this.options.alignment === 'horizontal') {
+ this.dockOffset.top = this.wPaint.menus.primary.$menu.outerHeight(true);
+ }
+ else {
+ this.dockOffset.left = this.wPaint.menus.primary.$menu.outerWidth(true);
+ }
+ }
+ },
+
+ /************************************
+ * handle
+ ************************************/
+ _createHandle: function () {
+ var _this = this,
+ $handle = $('<div class="wPaint-menu-handle"></div>');
+
+ // draggable functions
+ function draggableStart() {
+ _this.docked = false;
+ _this._setDrag();
+ }
+
+ function draggableStop() {
+ $.each(_this.$menu.data('ui-draggable').snapElements, function (i, el) {
+ var offset = _this.$menu.offset(),
+ offsetPrimary = _this.wPaint.menus.primary.$menu.offset();
+
+ _this.dockOffset.left = offset.left - offsetPrimary.left;
+ _this.dockOffset.top = offset.top - offsetPrimary.top;
+ _this.docked = el.snapping;
+ });
+
+ _this._setDrag();
+ }
+
+ function draggableDrag() {
+ _this._setIndex();
+ }
+
+ // the drag/snap events for menus are tricky
+ // init handle for ALL menus, primary menu will drag a secondary menu with it, but that is un/binded in the toggle function
+ this.$menu.draggable({handle: $handle});
+
+ // if it's a secondary menu we want to check for snapping
+ // on drag we set docked to false, on snap we set it back to true
+ if (this.type === 'secondary') {
+ this.$menu.draggable('option', 'snap', this.wPaint.menus.primary.$menu);
+ this.$menu.draggable('option', 'start', draggableStart);
+ this.$menu.draggable('option', 'stop', draggableStop);
+ this.$menu.draggable('option', 'drag', draggableDrag);
+ }
+
+ $handle.bindMobileEvents();
+
+ return $handle;
+ },
+
+ /************************************
+ * generic icon
+ ************************************/
+ _createIconBase: function (item) {
+ var _this = this,
+ $icon = $('<div class="wPaint-menu-icon wPaint-menu-icon-name-' + item.name + '"></div>'),
+ $iconImg = $('<div class="wPaint-menu-icon-img"></div>'),
+ width = $iconImg.realWidth(null, null, this.wPaint.$el);
+
+ function mouseenter(e) {
+ var $el = $(e.currentTarget);
+
+ $el.siblings('.hover').removeClass('hover');
+ if (!$el.hasClass('disabled')) { $el.addClass('hover'); }
+ }
+
+ function mouseleave(e) {
+ $(e.currentTarget).removeClass('hover');
+ }
+
+ function click() {
+ _this.wPaint.menus.active = _this;
+ }
+
+ $icon
+ .attr('title', item.title)
+ .on('mousedown', $.proxy(this.wPaint._closeSelectBoxes, this.wPaint, item))
+ .on('mouseenter', mouseenter)
+ .on('mouseleave', mouseleave)
+ .on('click', click);
+
+ // can have index:0 so be careful here
+ if ($.isNumeric(item.index)) {
+ $iconImg
+ .css({
+ backgroundImage: 'url(' + item.img + ')',
+ backgroundPosition: (-width * item.index) + 'px 0px'
+ });
+ }
+
+ return $icon.append($iconImg);
+ },
+
+ /************************************
+ * icon group
+ ************************************/
+ _createIconGroup: function (item) {
+ var _this = this,
+ css = {backgroundImage: 'url(' + item.img + ')'},
+ $icon = this.$menuHolder.children('.wPaint-menu-icon-group-' + item.group),
+ iconExists = $icon.length,
+ $selectHolder = null,
+ $option = null,
+ $item = null,
+ width = 0;
+
+ // local functions
+ function setIconClick() {
+
+ // only trigger if menu is not visible otherwise it will fire twice
+ // from the mousedown to open the menu which we want just to display the menu
+ // not fire the button callback
+ if (!$icon.children('.wPaint-menu-select-holder').is(':visible')) {
+ item.callback.apply(_this.wPaint, []);
+ }
+ }
+
+ function selectHolderClick() {
+ $icon.addClass('active').siblings('.active').removeClass('active');
+ }
+
+ function optionClick() {
+
+ // rebind the main icon when we select an option
+ $icon
+ .attr('title', item.title)
+ .off('click.setIcon')
+ .on('click.setIcon', setIconClick);
+
+ // run the callback right away when we select an option
+ $icon.children('.wPaint-menu-icon-img').css(css);
+ item.callback.apply(_this.wPaint, []);
+ }
+
+ // crate icon if it doesn't exist yet
+ if (!iconExists) {
+ $icon = this._createIconBase(item)
+ .addClass('wPaint-menu-icon-group wPaint-menu-icon-group-' + item.group)
+ .on('click.setIcon', setIconClick)
+ .on('mousedown', $.proxy(this._iconClick, this));
+ }
+
+ // get the proper width here now that we have the icon
+ // this is for the select box group not the main icon
+ width = $icon.children('.wPaint-menu-icon-img').realWidth(null, null, this.wPaint.$el);
+ css.backgroundPosition = (-width * item.index) + 'px center';
+
+ // create selectHolder if it doesn't exist
+ $selectHolder = $icon.children('.wPaint-menu-select-holder');
+ if (!$selectHolder.length) {
+ $selectHolder = this._createSelectBox($icon);
+ $selectHolder.children().on('click', selectHolderClick);
+ }
+
+ $item = $('<div class="wPaint-menu-icon-select-img"></div>')
+ .attr('title', item.title)
+ .css(css);
+
+ $option = this._createSelectOption($selectHolder, $item)
+ .addClass('wPaint-menu-icon-name-' + item.name)
+ .on('click', optionClick);
+
+ // move select option into place if after is set
+ if (item.after) {
+ $selectHolder.children('.wPaint-menu-select').children('.wPaint-menu-icon-name-' + item.after).after($option);
+ }
+
+ // we only want to return an icon to append on the first run of a group
+ if (!iconExists) { return $icon; }
+ },
+
+ /************************************
+ * icon generic
+ ************************************/
+ _createIconGeneric: function (item) {
+
+ // just a go between for the iconGeneric type
+ return this._createIconActivate(item);
+ },
+
+ /************************************
+ * icon
+ ************************************/
+ _createIconActivate: function (item) {
+
+ // since we are piggy backing icon with the item.group
+ // we'll just do a redirect and keep the code separate for group icons
+ if (item.group) { return this._createIconGroup(item); }
+
+ var _this = this,
+ $icon = this._createIconBase(item);
+
+ function iconClick(e) {
+ if (item.icon !== 'generic') { _this._iconClick(e); }
+ item.callback.apply(_this.wPaint, [e]);
+ }
+
+ $icon.on('click', iconClick);
+
+ return $icon;
+ },
+
+ _isIconDisabled: function (name) {
+ return this.$menuHolder.children('.wPaint-menu-icon-name-' + name).hasClass('disabled');
+ },
+
+ _setIconDisabled: function (name, disabled) {
+ var $icon = this.$menuHolder.children('.wPaint-menu-icon-name-' + name);
+
+ if (disabled) {
+ $icon.addClass('disabled').removeClass('hover');
+ }
+ else {
+ $icon.removeClass('disabled');
+ }
+ },
+
+ _getIcon: function (name) {
+ return this.$menuHolder.children('.wPaint-menu-icon-name-' + name);
+ },
+
+ _iconClick: function (e) {
+ var $el = $(e.currentTarget),
+ menus = this.wPaint.menus.all;
+
+ // make sure to loop using parent object - don't use .wPaint-menu-secondary otherwise we would hide menu for all canvases
+ for (var menu in menus) {
+ if (menus[menu] && menus[menu].type === 'secondary') { menus[menu].$menu.hide(); }
+ }
+
+ $el.siblings('.active').removeClass('active');
+ if (!$el.hasClass('disabled')) { $el.addClass('active'); }
+ },
+
+ /************************************
+ * iconToggle
+ ************************************/
+ _createIconToggle: function (item) {
+ var _this = this,
+ $icon = this._createIconBase(item);
+
+ function iconClick() {
+ $icon.toggleClass('active');
+ item.callback.apply(_this.wPaint, [$icon.hasClass('active')]);
+ }
+
+ $icon.on('click', iconClick);
+
+ return $icon;
+ },
+
+ /************************************
+ * select
+ ************************************/
+ _createIconSelect: function (item) {
+ var _this = this,
+ $icon = this._createIconBase(item),
+ $selectHolder = this._createSelectBox($icon),
+ i, ii, $option;
+
+ function optionClick(e) {
+ $icon.children('.wPaint-menu-icon-img').html($(e.currentTarget).html());
+ item.callback.apply(_this.wPaint, [$(e.currentTarget).html()]);
+ }
+
+ // add values for select
+ for (i = 0, ii = item.range.length; i < ii; i++) {
+ $option = this._createSelectOption($selectHolder, item.range[i]);
+ $option.on('click', optionClick);
+ if (item.useRange) { $option.css(item.name, item.range[i]); }
+ }
+
+ return $icon;
+ },
+
+ _createSelectBox: function ($icon) {
+ var $selectHolder = $('<div class="wPaint-menu-select-holder"></div>'),
+ $select = $('<div class="wPaint-menu-select"></div>'),
+ timer = null;
+
+ function clickSelectHolder(e) {
+ e.stopPropagation();
+ $selectHolder.hide();
+ }
+
+ function iconMousedown() {
+ timer = setTimeout(function () { $selectHolder.toggle(); }, 200);
+ }
+
+ function iconMouseup() {
+ clearTimeout(timer);
+ }
+
+ function iconClick() {
+ $selectHolder.toggle();
+ }
+
+ $selectHolder
+ .on('mousedown mouseup', this.wPaint._stopPropagation)
+ .on('click', clickSelectHolder)
+ .hide();
+
+ // of hozizontal we'll pop below the icon
+ if (this.options.alignment === 'horizontal') {
+ $selectHolder.css({left: 0, top: $icon.children('.wPaint-menu-icon-img').realHeight('outer', true, this.wPaint.$el)});
+ }
+ // vertical we'll pop to the right
+ else {
+ $selectHolder.css({left: $icon.children('.wPaint-menu-icon-img').realWidth('outer', true, this.wPaint.$el), top: 0});
+ }
+
+ $icon
+ .addClass('wPaint-menu-icon-select')
+ .append('<div class="wPaint-menu-icon-group-arrow"></div>')
+ .append($selectHolder.append($select));
+
+ // for groups we want to add a delay before the selectBox pops up
+ if ($icon.hasClass('wPaint-menu-icon-group')) {
+ $icon
+ .on('mousedown', iconMousedown)
+ .on('mouseup', iconMouseup);
+ }
+ else { $icon.on('click', iconClick); }
+
+ return $selectHolder;
+ },
+
+ _createSelectOption: function ($selectHolder, value) {
+ var $select = $selectHolder.children('.wPaint-menu-select'),
+ $option = $('<div class="wPaint-menu-select-option"></div>').append(value);
+
+ // set class for first item to remove any undesired styles like borders
+ if (!$select.children().length) { $option.addClass('first'); }
+
+ $select.append($option);
+
+ return $option;
+ },
+
+ _setSelectValue: function (icon, value) {
+ this._getIcon(icon).children('.wPaint-menu-icon-img').html(value);
+ },
+
+ /************************************
+ * color picker
+ ************************************/
+ _createIconColorPicker: function (item) {
+ var _this = this,
+ $icon = this._createIconBase(item);
+
+ function iconClick() {
+
+ // if we happen to click on this while in dropper mode just revert to previous
+ if (_this.wPaint.options.mode === 'dropper') { _this.wPaint.setMode(_this.wPaint.previousMode); }
+ }
+
+ function iconOnSelect(color) {
+ item.callback.apply(_this.wPaint, [color]);
+ }
+
+ function iconOnDropper() {
+ $icon.trigger('click');
+ _this.wPaint.dropper = item.name;
+ _this.wPaint.setMode('dropper');
+ }
+
+ $icon
+ .on('click', iconClick)
+ .addClass('wPaint-menu-colorpicker')
+ .wColorPicker({
+ mode: 'click',
+ generateButton: false,
+ dropperButton: true,
+ onSelect: iconOnSelect,
+ onDropper: iconOnDropper
+ });
+
+ return $icon;
+ },
+
+ _setColorPickerValue: function (icon, value) {
+ this._getIcon(icon).children('.wPaint-menu-icon-img').css('backgroundColor', value);
+ },
+
+ /************************************
+ * menu toggle
+ ************************************/
+ _createIconMenu: function (item) {
+ var _this = this,
+ $icon = this._createIconActivate(item);
+
+ function iconClick() {
+ _this.wPaint.setCursor(item.name);
+
+ // the items name here will be the menu name
+ var menu = _this.wPaint.menus.all[item.name];
+ menu.$menu.toggle();
+ if (_this.handle) {
+ menu._setDrag();
+ } else {
+ menu._setPosition();
+ }
+ }
+
+ $icon.on('click', iconClick);
+
+ return $icon;
+ },
+
+ // here we specify which menu will be dragged
+ _setDrag: function () {
+ var $menu = this.$menu,
+ drag = null, stop = null;
+
+ if ($menu.is(':visible')) {
+ if (this.docked) {
+
+ // make sure we are setting proper menu object here
+ drag = stop = $.proxy(this._setPosition, this);
+ this._setPosition();
+ }
+
+ // register drag/stop events
+ this.wPaint.menus.primary.$menu.draggable('option', 'drag', drag);
+ this.wPaint.menus.primary.$menu.draggable('option', 'stop', stop);
+ }
+ },
+
+ _setPosition: function () {
+ var offset = this.wPaint.menus.primary.$menu.position();
+
+ this.$menu.css({
+ left: offset.left + this.dockOffset.left,
+ top: offset.top + this.dockOffset.top
+ });
+ },
+
+ _setIndex: function () {
+ var primaryOffset = this.wPaint.menus.primary.$menu.offset(),
+ secondaryOffset = this.$menu.offset();
+
+ if (
+ secondaryOffset.top < primaryOffset.top ||
+ secondaryOffset.left < primaryOffset.left
+ ) {
+ this.$menu.addClass('wPaint-menu-behind');
+ }
+ else {
+ this.$menu.removeClass('wPaint-menu-behind');
+ }
+ }
+ };
+
+ /************************************************************************
+ * wPaint
+ ************************************************************************/
+ $.support.canvas = (document.createElement('canvas')).getContext;
+
+ $.fn.wPaint = function (options, value) {
+
+ function create() {
+ if (!$.support.canvas) {
+ $(this).html('Browser does not support HTML5 canvas, please upgrade to a more modern browser.');
+ return false;
+ }
+
+ return $.proxy(get, this)();
+ }
+
+ function get() {
+ var wPaint = $.data(this, 'wPaint');
+
+ if (!wPaint) {
+ wPaint = new Paint(this, $.extend(true, {}, options));
+ $.data(this, 'wPaint', wPaint);
+ }
+
+ return wPaint;
+ }
+
+ function runOpts() {
+ var wPaint = $.data(this, 'wPaint');
+
+ if (wPaint) {
+ if (wPaint[options]) { wPaint[options].apply(wPaint, [value]); }
+ else if (value !== undefined) {
+ if (wPaint[func]) { wPaint[func].apply(wPaint, [value]); }
+ if (wPaint.options[options]) { wPaint.options[options] = value; }
+ }
+ else {
+ if (wPaint[func]) { values.push(wPaint[func].apply(wPaint, [value])); }
+ else if (wPaint.options[options]) { values.push(wPaint.options[options]); }
+ else { values.push(undefined); }
+ }
+ }
+ }
+
+ if (typeof options === 'string') {
+ var values = [],
+ func = (value ? 'set' : 'get') + options.charAt(0).toUpperCase() + options.substring(1);
+
+ this.each(runOpts);
+
+ if (values.length) { return values.length === 1 ? values[0] : values; }
+
+ return this;
+ }
+
+ options = $.extend({}, $.fn.wPaint.defaults, options);
+ options.lineWidth = parseInt(options.lineWidth, 10);
+ options.fontSize = parseInt(options.fontSize, 10);
+
+ return this.each(create);
+ };
+
+ /************************************************************************
+ * extend
+ ************************************************************************/
+ $.fn.wPaint.extend = function (funcs, protoType) {
+ var key;
+
+ function elEach(func) {
+ if (protoType[func]) {
+ var tmpFunc = Paint.prototype[func],
+ newFunc = funcs[func];
+
+ protoType[func] = function () {
+ tmpFunc.apply(this, arguments);
+ newFunc.apply(this, arguments);
+ };
+ }
+ else {
+ protoType[func] = funcs[func];
+ }
+ }
+
+ protoType = protoType === 'menu' ? Menu.prototype : Paint.prototype;
+
+ for (key in funcs) { (elEach)(key); }
+ };
+
+ /************************************************************************
+ * Init holders
+ ************************************************************************/
+ $.fn.wPaint.menus = {};
+
+ $.fn.wPaint.cursors = {};
+
+ $.fn.wPaint.defaults = {
+ path: '/', // set absolute path for images and cursors
+ theme: 'standard classic', // set theme
+ autoScaleImage: true, // auto scale images to size of canvas (fg and bg)
+ autoCenterImage: true, // auto center images (fg and bg, default is left/top corner)
+ menuHandle: true, // setting to false will means menus cannot be dragged around
+ menuOrientation: 'horizontal', // menu alignment (horizontal,vertical)
+ menuOffsetLeft: 5, // left offset of primary menu
+ menuOffsetTop: 5, // top offset of primary menu
+ bg: null, // set bg on init
+ image: null, // set image on init
+ imageStretch: false, // stretch smaller images to full canvans dimensions
+ onShapeDown: null, // callback for draw down event
+ onShapeMove: null, // callback for draw move event
+ onShapeUp: null // callback for draw up event
+ };
+})(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/src/wPaint.utils.js b/static/js/wpaint/src/wPaint.utils.js
new file mode 100644
index 0000000..7f1346a
--- /dev/null
+++ b/static/js/wpaint/src/wPaint.utils.js
@@ -0,0 +1,70 @@
+(function () {
+ if (!String.prototype.capitalize) {
+ String.prototype.capitalize = function () {
+ return this.slice(0, 1).toUpperCase() + this.slice(1);
+ };
+ }
+})();
+
+(function ($) {
+ $.fn.realWidth = function (type, margin, $el) {
+ var width = null, $div = null, method = null;
+
+ type = type === 'inner' || type === 'outer' ? type : '';
+ method = type === '' ? 'width' : type + 'Width';
+ margin = margin === true ? true : false;
+ $div = $(this).clone().css({position: 'absolute', left: -10000}).appendTo($el || 'body');
+ width = margin ? $div[method](margin) : $div[method]();
+
+ $div.remove();
+
+ return width;
+ };
+
+ $.fn.realHeight = function (type, margin, $el) {
+ var height = null, $div = null, method = null;
+
+ type = type === 'inner' || type === 'outer' ? type : '';
+ method = type === '' ? 'height' : type + 'Height';
+ margin = margin === true ? true : false;
+ $div = $(this).clone().css({position: 'absolute', left: -10000}).appendTo($el || 'body');
+ height = margin ? $div[method](margin) : $div[method]();
+
+ $div.remove();
+
+ return height;
+ };
+
+ $.fn.bindMobileEvents = function () {
+ $(this).on('touchstart touchmove touchend touchcancel', function () {
+ var touches = (event.changedTouches || event.originalEvent.targetTouches),
+ first = touches[0],
+ type = '';
+
+ switch (event.type) {
+ case 'touchstart':
+ type = 'mousedown';
+ break;
+ case 'touchmove':
+ type = 'mousemove';
+ event.preventDefault();
+ break;
+ case 'touchend':
+ type = 'mouseup';
+ break;
+ default:
+ return;
+ }
+
+ var simulatedEvent = document.createEvent('MouseEvent');
+
+ simulatedEvent.initMouseEvent(
+ type, true, true, window, 1,
+ first.screenX, first.screenY, first.clientX, first.clientY,
+ false, false, false, false, 0/*left*/, null
+ );
+
+ first.target.dispatchEvent(simulatedEvent);
+ });
+ };
+})(jQuery); \ No newline at end of file
diff --git a/static/js/wpaint/test/dev.html b/static/js/wpaint/test/dev.html
new file mode 100644
index 0000000..b9cd1bf
--- /dev/null
+++ b/static/js/wpaint/test/dev.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width" />
+
+ <title>Websanova :: wPaint</title>
+
+ <link rel="icon" type="image/vnd.microsoft.icon" href="./demo/img/favicon.ico" />
+ <script type="text/javascript" src="../lib/jquery.1.10.2.min.js"></script>
+</head>
+<body>
+
+ <!-- jQuery UI -->
+ <script type="text/javascript" src="../lib/jquery.ui.core.1.10.3.min.js"></script>
+ <script type="text/javascript" src="../lib/jquery.ui.widget.1.10.3.min.js"></script>
+ <script type="text/javascript" src="../lib/jquery.ui.mouse.1.10.3.min.js"></script>
+ <script type="text/javascript" src="../lib/jquery.ui.draggable.1.10.3.min.js"></script>
+
+ <!-- wColorPicker -->
+ <link rel="Stylesheet" type="text/css" href="../lib/wColorPicker.min.css" />
+ <script type="text/javascript" src="../lib/wColorPicker.min.js"></script>
+
+ <!-- wPaint -->
+ <link rel="Stylesheet" type="text/css" href="../src/wPaint.css" />
+ <script type="text/javascript" src="../src/wPaint.utils.js"></script>
+ <script type="text/javascript" src="../src/wPaint.js"></script>
+
+ <!-- wPaint main -->
+ <script type="text/javascript" src="../plugins/main/src/fillArea.min.js"></script>
+ <script type="text/javascript" src="../plugins/main/src/wPaint.menu.main.js"></script>
+
+ <!-- wPaint text -->
+ <script type="text/javascript" src="../plugins/text/src/wPaint.menu.text.js"></script>
+
+ <!-- wPaint shapes -->
+ <script type="text/javascript" src="../plugins/shapes/src/shapes.min.js"></script>
+ <script type="text/javascript" src="../plugins/shapes/src/wPaint.menu.main.shapes.js"></script>
+
+ <!-- wPaint file -->
+ <script type="text/javascript" src="../plugins/file/src/wPaint.menu.main.file.js"></script>
+
+ <div id="wPaint-demo1" style="position:relative; width:500px; height:200px; background-color:#7a7a7a; margin:70px auto 20px auto;"></div>
+
+ <center style="margin-bottom: 50px;">
+ <input type="button" value="toggle menu" onclick="console.log($('#wPaint-demo1').wPaint('menuOrientation')); $('#wPaint-demo1').wPaint('menuOrientation', $('#wPaint-demo1').wPaint('menuOrientation') === 'vertical' ? 'horizontal' : 'vertical');"/>
+ </center>
+
+ <center id="wPaint-img"></center>
+
+ <script type="text/javascript">
+ var images = [
+ '/test/uploads/wPaint.png',
+ ];
+
+ function saveImg(image) {
+ var _this = this;
+
+ $.ajax({
+ type: 'POST',
+ url: '/test/upload.php',
+ data: {image: image},
+ success: function (resp) {
+
+ // internal function for displaying status messages in the canvas
+ _this._displayStatus('Image saved successfully');
+
+ // doesn't have to be json, can be anything
+ // returned from server after upload as long
+ // as it contains the path to the image url
+ // or a base64 encoded png, either will work
+ resp = $.parseJSON(resp);
+
+ // update images array / object or whatever
+ // is being used to keep track of the images
+ // can store path or base64 here (but path is better since it's much smaller)
+ images.push(resp.img);
+
+ // do something with the image
+ $('#wPaint-img').append($('<img/>').attr('src', image));
+ }
+ });
+ }
+
+ function loadImgBg () {
+
+ // internal function for displaying background images modal
+ // where images is an array of images (base64 or url path)
+ // NOTE: that if you can't see the bg image changing it's probably
+ // becasue the foregroud image is not transparent.
+ this._showFileModal('bg', images);
+ }
+
+ function loadImgFg () {
+
+ // internal function for displaying foreground images modal
+ // where images is an array of images (base64 or url path)
+ this._showFileModal('fg', images);
+ }
+
+ function createCallback(cbName) {
+ return function() {
+ if (console) {
+ console.log(cbName, arguments);
+ }
+ }
+ }
+
+ // init wPaint
+ $('#wPaint-demo1').wPaint({
+ menuOffsetLeft: -35,
+ menuOffsetTop: -50,
+ saveImg: saveImg,
+ loadImgBg: loadImgBg,
+ loadImgFg: loadImgFg,
+ onShapeDown: createCallback('onShapeDown'),
+ onShapeUp: createCallback('onShapeUp'),
+ onShapeMove: createCallback('onShapeDMove')
+ });
+ </script>
+
+</body>
+</html> \ No newline at end of file
diff --git a/static/js/wpaint/test/fullscreen.html b/static/js/wpaint/test/fullscreen.html
new file mode 100644
index 0000000..91b3e15
--- /dev/null
+++ b/static/js/wpaint/test/fullscreen.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width" />
+
+ <title>Websanova :: Paint</title>
+
+ <script type="text/javascript" src="../lib/jquery.1.10.2.min.js"></script>
+</head>
+<body>
+ <!-- jQuery UI -->
+ <script type="text/javascript" src="../lib/jquery.ui.core.1.10.3.min.js"></script>
+ <script type="text/javascript" src="../lib/jquery.ui.widget.1.10.3.min.js"></script>
+ <script type="text/javascript" src="../lib/jquery.ui.mouse.1.10.3.min.js"></script>
+ <script type="text/javascript" src="../lib/jquery.ui.draggable.1.10.3.min.js"></script>
+
+ <!-- wColorPicker -->
+ <link rel="Stylesheet" type="text/css" href="../lib/wColorPicker.min.css" />
+ <script type="text/javascript" src="../lib/wColorPicker.min.js"></script>
+
+ <!-- wPaint -->
+ <link rel="Stylesheet" type="text/css" href="../src/wPaint.css" />
+ <script type="text/javascript" src="../src/wPaint.utils.js"></script>
+ <script type="text/javascript" src="../src/wPaint.js"></script>
+
+ <!-- wPaint main -->
+ <script type="text/javascript" src="../plugins/main/src/fillArea.min.js"></script>
+ <script type="text/javascript" src="../plugins/main/src/wPaint.menu.main.js"></script>
+
+ <!-- wPaint text -->
+ <script type="text/javascript" src="../plugins/text/src/wPaint.menu.text.js"></script>
+
+ <!-- wPaint shapes -->
+ <script type="text/javascript" src="../plugins/shapes/src/shapes.min.js"></script>
+ <script type="text/javascript" src="../plugins/shapes/src/wPaint.menu.main.shapes.js"></script>
+
+ <!-- wPaint file -->
+ <script type="text/javascript" src="../plugins/file/src/wPaint.menu.main.file.js"></script>
+
+ <div id="wPaint" style="position:relative; width:200px; height:200px; background:#CACACA;"></div>
+
+ <style>
+ body, html {
+ margin: 0px;
+ overflow: hidden;
+ }
+ </style>
+
+ <script type="text/javascript">
+
+ // update elements dimensions
+ // call wPaint('resize')
+ $(window).resize(function () {
+ $('#wPaint').css({
+ width: $(window).width(),
+ height: $(window).height()
+ })
+ .wPaint('resize');
+ })
+
+ // init size based on browser dimensions
+ $(window).resize();
+
+ // set test image
+ // get from tapping enter below
+ $('#wPaint').wPaint({
+ image: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABAYAAAErCAYAAABNUIGWAAARs0lEQVR4nO3dzY4dV7UH8PUkvMh9CXgC9yATBr5vgMSAGSNGSJdRELN7lUQRwys5EoMgpCsEkWywxFWIMCDHOI4SN273x2LgOnT1PlWnz8euj3Pq95OOlNh99l51Plpe/9q1KwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmKnMuMmMm6nrAAAAAEbWhALZPIQDAAAAsCStUCAzIyuPfZkZ1/c8LmvOCQAAAOygdjCQGReZcVWsRLjvIRwAAACAKRwSDGTGeSsE2CUIKB83mXE+1DECAAAAPXYJBjLj6x2DgJt7LiMox1iNawUBAAAAjKFpyK9bTXn56Gvi7wsD7m3umz0IXF7ATppw6mrqOgAAAE5C08QfcgnATdOoXew5/2XPCgR3SGBN81lbfUaEAwAAAIfaIxhYBQHV9wTId3sWtAMCqwa4I91eEwAAoK4tLiX493X/mfF0hHouNX70EQwAAABUVq4ImLqeiLXmz6oB/k0wAAAAUNlMgwGrBugkGAAAAKhsjsFAhFUDdBMMAAAAVDbjYOBKA0hJMAAAAFDZjIOBr4raPp26JqYnGAAAgIVodsm/nrqOJZhrMBDhcgLWCQYAAGABmlDAP/xHMvNgwCaE3CEYAACABSiCgcyMq6lrOmVzDgYi1hpBq0gWTjAAAAALUf7jPzPOp67pVB1BMHBZ1OizsGCCAQAAWIjM+KIjHPhi6rpO0dyDgQjNILd8FgAAYEEy41wT8E5mPMiMBwONfQzBwHlRp40IF8rvBAAAWJjiXvaLvMY8M85ax382wPhH8foWe0/Mtk6GJRgAAIAFWnojkBkfto7/wwHGbwcDX9YevxbBABF+HwAAwGIteWf6zHjUOvZHA4wvGOBoCAYAAGChiqZwUc1AZjxuHfvjAcY/lmDgaqmfAW4JBgAAYMGWumogM563jvv5AOO3g4H/rD1+LZnxZVHr/05dE+MTDAAAwIItddVAZrxsHffLAcaf9R0J2oqm0J0JFkgwAAAAC7fEVQOCgVv2GUAwAAAAC7fEpiAzvm0d87eVx/5IMMAxWeLvAAAAoGWJTUFmnLeO+bzy2F8KBjgmS/wdAAAAtCyxKciMi9YxX1QeWzDAUVni7wAAAKBliRsQZsbb1jG/rTy2YICjIhgAAICFK86eL6IpyIzLoXbib4cCggGOgWAAAAA4ql30a8iMq9YxX1UeWzDAUSm+D4IBAABYouKMYdVr7udIMHBLMEBmvBAMAADAwhXBwMk3h4KBW4IBItZ+B7yYuh4AAGBkS9uAcMhmWDDAMSqCgaphGQAAcAQy4+uiof1i6pqGJBi4JRggwj4DAABArJ0xrLpT/9wIBm4JBoiwzwAAABDLOmMoGLglGGDFPgMAALBwS7qcoGiA3lQeWzDAUbLPAAAAsIjLCTLjs/bKiMx4WHn8tWAgMx5kxoOa89QiGDhdzSqgm+Zx7/d56M9CZvxXZnww1+8CAAAQa8HASV5OMELzk8XjrPXfv86M/6g95yEEA6epuDRoq+90Zryu/f3PjP/OjL9kxnn5vagxPgAAUNlYwUBmXDYN6airEjLjYXGMnw0wx6ZgYPW4yIxHtefexxJWiSxRTzCwWiVz3fO4KR7l31+1HpeZ8bb1uGia//Pm/2965hcMAADAnI0RDBRnqEdtRpuGZejj67qU4FcbmrTHQ9SxZa2XYwRBTCPvXkqwqUkf8/FCKAAAADM2ZDDQnEnsalBGa0hzhM3VuoKB5s8/zIy/zikgyAWsFsh3KzYWf037hOHATb5bTfA8Mz6Z+nUAAADuMUQwkLeXDWxqHkZpSovjezrQHJ3BQOvvv5MZn/SFJJnxVWb8fIjaWjVcDhkCzUXevYzjbOp6urS+H6vHYN+F1vu+7+UE215K8I/M+J+hjgMAABhQVt6IbkMgsGoyRmtMM+PpGPPt0nBnxpOegGAVElxnxj8q1vayZ75TXi0wy2CgI5wpvx9/mqiudk2vp6gBAACYUHPWr0rznOu7kK+a3fPm778q/u7TOkfRW88oQcQ+Z+LvCQhWr9vHB9bVG9IcMu7cNeHA2dR1tOXdvR3uW4Y/9gad7lIBAABLVjkYuLmvwSl+ZtAmpGh4BtlfoJln7yX6mfEsb5dzV7nkYsOZ6dHvCrF0eXcpf9fqkN4VBCPWOOpKHgAAYIbaDcmez+9qRM83/OwoDVBR06uR5tm7scqMn+fduyi0m8i3mfGLDc9dXbfet4/By33rYj89qwTWArMNQc5gn9li/k8P/R0AAAAcuX2bguy/68DGZj/Xl7gPchZ7rGanVjDQGu/jDWeSuzaR2/SzVghMpOd96X0/MuP92p+lPWu9GGteAABgJvZpCjqa+50a0eL51RugzHg1VoM1VDOXGd9saPpndZ06d3UENlu9J8XndrRLCtI+AwAAsGy7BgPZvUR652aimLdaI5sZPyrGHnovg0HP8mbGmy0CgtVKAoHAiFarNjr+rHx/tt7jouP5g18GkhX3GgEAAI7QrmcLO86Edu4nsMU4l7WbkZ6z7IM2y0MHA6153mtCgvJSAmHABPq+Nx3fj503vhzrM1XM2f7ODHrHEAAAYGZ2CQZy/ZaEjw+cu9qqgZ4ztYMvi56iiWN6fe97jc9DZrwcM9xq5mzXPdhdPAAAgBnaJhjI7p3Ta2y0V+Xa5ly/vOEmM745tL4t515UMJC3189v85jN9eqrmiqPV17KUX5HDvlMD7oPxz3zzeZ9AwAARpD33Me850x8lbOYtZqfcpzM+NGhte0w92KCgY7Gd5vH5E3mEO9RRzCwtu/DgeP/rhjvJzXq3jDfaBt2AgAAM5MZXxcNyBetvzvo7gNbzF2e6d+riSwas9c1attz7pNtqPYMBeYSDNypqcJ4ZRC1tnqgUt2DbNDZM9efl/A5BgAAenQ1IF1Ne2Y8GWDuMnzYuQGq2fTtMffJLsHOu5cNdAVEmx6rn/m/GRzHWv0Vx1sLBirWXX2Dznvmm+x7BAAATKyruS2anTFv+bfTXJnxesozncVr92rs+YfSEdhsdUa8I1CquspkX101HTDWKMFAx1xj3mHjz0POBQAAzEx5ZjLXLy/448Dz733Wfeoz9sXr9Pux5x9K3yqBLZ7XFyisPltXmfFojGPoqK3KqoGOYGCwSyfGXDVQHMvJhFwAAMCWNjQ7Yyxh3qv5yfXbJ45+VvoUg4GOZnfr6+Zz/fr7TSHBqO9XZrxf1LDXfhQbjmuQ78pYqwamDtkAAICJbTjTO0rzljteTpAZPxk7wOipo/1a/XiKGmrq+Bzs9Lp2BEw/zu7bXbZ/5ulQx9NR38GrBjYcy3ntepv5Rlk1IBgAAICF6wkGRmu2c8c7FHQ0oIPezm1DHQcvTZ+TQ8OWTc+/JyC4zoyH9Y6kt77Xxbzv7zHGaKsFWnMOvmpAMAAAAAvX0ZiPvjS/I5xYa04y46cdzeUgZ2q3ceLBwM7N4TbBQmb8oC+Iav78s8OPZGONh6yIuJoiQBtj1YBgAAAAWDUf181jkl3kN4UDmfHPjlBgsgYmM753SsFA8drv1XzusuIgM55uWEFwkxlv9juSnWrc6X3rCzSGqLNj7kFXDQgGAACA2egKB3oaskmbl8z4/YkFAwfv2bDPGJnxdkNAUP09zoxvDggG9rpbQw1DrxoQDAAAALPSEwS0zyb/cwY1CgY2j3G143M/a973wVeFFON/s8PzJgsGOuavfWtEwQAAADAvfcu2M+OnU9cWEZEZf5miORzKocFAjWChGedhx3u/U8iwxRx7NfYzCAbKvUA+rzi2YAAAAJifOTcreXcjuqqN6xQOaewz42+1z2Z3hAOPDh2zNfZe+wxMHQx01FBt7jl/1wAAgIVrzpJOshniJsXZ29nVt6uORnzfM+k1m9Whxt1rn4GZBAOfF/NX+exlxt9PaQUMAADA4DLjTauRGmQH/bF1NL73njnOjIviORcV63k0RBPcjL3zPgM9wcDoZ9ezwh0kOsb8QDAAAACwg1MMBiLWz9I3j97md6iz+q3xr4pG/LeVxt35rH9PMDD6ZST57laPQ6ykOJnNNAEAAAZ3qsFARP+S+TIo6AgRfjlCPTeZ8d0KY+aujXDX63JoHfsqank6wJh/rzEmAADAycqM81YTdT51PTXl5ttFthv0UZbUZ8Z3a69MqBQMTLbkvqilyqqFYsyTCrsAAACqy4xXrSbq1dT11NaEA+1VAhtDghHq+W0x58sDxzv2YOCqdh3pzgQAAADbO/VgoNQKCiYJBpoa3taa8wSCgQ+KWh5WGPPNHI4NAADgKGTGi1YT9WLqesZSrCQY/exyMe9OdynIjLPMeND891EHAx31HLz0P92yEAAAYHt5937yn09dzxSakGDUJeeZ8axozp9s+byz1nPOTiQYqH6Gf9fXBAAAYLEy4w+tJuoPU9ezJMX19Vtt/JgZP2w954enEAx01HTwJpjFeB/UqBEAAOAkZcYnrQbqk6nrWZLitc/M+NkWz/mo9fMfnVAwcF6znuIY3bIQAACgT9loTl3P0hR7PHy4xc/fCXJOJRiIWF81kBkPstlLYY+x3JkAAABgG+U161PXszS7vv4nHgzcuXXhIZ/LIfYtAAAAOFlNc3o2dR1LtcvrX+4JsWcwcF08bxZn1DPjsjyeA4KB94pw4TcDlAwAAADjyuIuEvsEA804q9s1ziIUiIjIjLcdocCvDhjP5QQAAACclmJPguf7BgNzlBkXxfFcHTjeb4pLE96rVSsAAABMIjP+2j4LfmLBwLPieJ5XGLN9OcGbGnUCAADAZDLj+z3X4R99MBCxts/AkwrjXRWv0VmFMgEAAGA6pxwMRERkxpMaoUAzVhkM3HtLSAAAAJi1zPhbTzDgtnyFjmDg8dQ1AQAAwMEy401HMGDn/ULH6/T/U9cEAAAAVWTGL4qm99XUNc1NZnwsGAAAAOCkZcYroUC/4s4EXicAAABYkiIYsA8DAAAALElmvCwuJ3g2dU0AAADAiDLjWjAAAAAAC5YZz4QCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA4V/ilvYw30ZUiAAAAABJRU5ErkJggg=='
+ });
+
+ // get an image for testing (just tap enter key)
+ $(document).keypress(function (e) {
+ if (e.keyCode === 13) {
+ console.log($('#wPaint').wPaint('image'));
+ }
+ });
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/static/js/wpaint/test/upload.php b/static/js/wpaint/test/upload.php
new file mode 100644
index 0000000..f0187b5
--- /dev/null
+++ b/static/js/wpaint/test/upload.php
@@ -0,0 +1,11 @@
+<?php
+
+$image = imagecreatefrompng($_POST['image']);
+$id = uniqid();
+
+imagealphablending($image, false);
+imagesavealpha($image, true);
+imagepng($image, 'uploads/wPaint-' . $id . '.png');
+
+// return image path
+echo '{"img": "/test/uploads/wPaint-' . $id . '.png"}';
diff --git a/static/js/wpaint/test/uploads/test1.png b/static/js/wpaint/test/uploads/test1.png
new file mode 100644
index 0000000..a0c6511
--- /dev/null
+++ b/static/js/wpaint/test/uploads/test1.png
Binary files differ
diff --git a/static/js/wpaint/test/uploads/test2.png b/static/js/wpaint/test/uploads/test2.png
new file mode 100644
index 0000000..68c25e0
--- /dev/null
+++ b/static/js/wpaint/test/uploads/test2.png
Binary files differ
diff --git a/static/js/wpaint/test/uploads/test3.png b/static/js/wpaint/test/uploads/test3.png
new file mode 100644
index 0000000..c92d3cc
--- /dev/null
+++ b/static/js/wpaint/test/uploads/test3.png
Binary files differ
diff --git a/static/js/wpaint/test/uploads/wPaint.png b/static/js/wpaint/test/uploads/wPaint.png
new file mode 100644
index 0000000..c19ab7f
--- /dev/null
+++ b/static/js/wpaint/test/uploads/wPaint.png
Binary files differ
diff --git a/static/js/wpaint/wPaint.jquery.json b/static/js/wpaint/wPaint.jquery.json
new file mode 100644
index 0000000..ab42ec5
--- /dev/null
+++ b/static/js/wpaint/wPaint.jquery.json
@@ -0,0 +1,38 @@
+{
+ "name": "wPaint",
+ "title": "wPaint jQuery Paint Plugin",
+ "description": "A jQuery paint plugin for a simple drawing surface that you can easily pop into your pages, similar to the basic windows paint program.",
+ "keywords": [
+ "websanova",
+ "wPaint",
+ "paint",
+ "canvas",
+ "html5"
+ ],
+ "version": "2.5.0",
+ "author": {
+ "name": "Websanova",
+ "email": "rob@websanova.com",
+ "url": "http://websanova.com"
+ },
+ "maintainers": [
+ {
+ "name": "Websanova",
+ "email": "rob@websanova.com",
+ "url": "http://websanova.com"
+ }
+ ],
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "https://github.com/websanova/wPaint#license"
+ }
+ ],
+ "bugs": "https://github.com/websanova/wPaint/issues",
+ "homepage": "http://wpaint.websanova.com",
+ "docs": "https://github.com/websanova/wPaint#wpaintjs",
+ "download": "https://github.com/websanova/wPaint/tags",
+ "dependencies": {
+ "jquery": ">=1.5"
+ }
+}
diff --git a/static/js/wpaint/wPaint.min.css b/static/js/wpaint/wPaint.min.css
new file mode 100644
index 0000000..29de08b
--- /dev/null
+++ b/static/js/wpaint/wPaint.min.css
@@ -0,0 +1,66 @@
+.wPaint-menu{position:absolute !important;display:inline-block;*display:inline;zoom:1;line-height:0;z-index:99}
+.wPaint-menu-behind{z-index:98}
+.wPaint-menu-holder{position:relative;margin:0 1px 1px 0}
+.wPaint-menu-handle{display:inline-block;*display:inline;zoom:1}
+.wPaint-menu-icon{position:relative;vertical-align:top}
+.wPaint-menu-icon-img{position:relative;display:inline-block;*display:inline;zoom:1;background-repeat:no-repeat;overflow:hidden}
+.wPaint-menu-select-holder{position:absolute;left:1px;z-index:10;overflow:hidden}
+.wPaint-menu-select{position:relative;text-align:center;overflow-y:scroll;z-index:100}
+.wPaint-menu-select-option.first{border-top:0}
+.wPaint-menu-alignment-horizontal .wPaint-menu-icon{display:inline-block;*display:inline;zoom:1}
+.wPaint-menu-alignment-vertical .wPaint-menu-icon{display:block}
+.wPaint-status{position:absolute;display:none;right:0;bottom:0}
+.wPaint-modal-bg{position:absolute;left:0;top:0;width:100%;height:100%}
+.wPaint-modal{position:absolute;display:inline-block;*display:inline;zoom:1}
+.wPaint-modal-holder{display:inline-block;*display:inline;zoom:1;overflow:hidden}
+.wPaint-modal-content{overflow-y:scroll;width:100%;height:100%}
+.wPaint-modal-close{position:absolute}
+.wPaint-text-input{margin:0;padding:0;outline-width:0;word-wrap:break-word;overflow:hidden}
+.wPaint-modal-img-holder{line-height:0}
+.wPaint-modal-img{display:inline-block;*display:inline;zoom:1}
+.wPaint-menu-holder{border-style:solid;border-width:1px;-webkit-box-shadow:3px 3px 5px #555;box-shadow:3px 3px 5px #555}
+.wPaint-menu-handle{cursor:pointer}
+.wPaint-menu-icon{border-style:solid;border-width:1px;cursor:pointer}
+.wPaint-menu-icon.disabled{cursor:default}
+.wPaint-menu-icon.disabled .wPaint-menu-icon-img{opacity:.3;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";filter:alpha(opacity=30)}
+.wPaint-menu-icon-img{font-family:verdana;font-weight:bold;text-align:center}
+.wPaint-menu-select-holder{border-style:solid;border-width:1px;-webkit-box-shadow:1px 1px 2px #666;box-shadow:1px 1px 2px #666}
+.wPaint-menu-select{font-family:verdana;text-align:center}
+.wPaint-menu-select-option{border-top-style:solid;border-top-width:1px;cursor:pointer}
+.wPaint-menu-icon-select-img{background-repeat:no-repeat}
+.wPaint-menu-icon-group-arrow{position:absolute;right:1px;bottom:1px}
+.wPaint-menu-alignment-horizontal .wPaint-menu-handle{border-right-style:solid;border-right-width:1px}
+.wPaint-menu-alignment-vertical .wPaint-menu-handle{border-bottom-style:solid;border-bottom-width:1px}
+.wPaint-status{font-size:10px;font-family:verdana;line-height:10px;height:10px;background-color:#3a3a3a;color:#f0f0f0;padding:5px;opacity:.5;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";filter:alpha(opacity=50)}
+.wPaint-modal-bg{background-color:#3a3a3a;opacity:.8;-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";filter:alpha(opacity=80)}
+.wPaint-modal-holder{height:100px;-webkit-box-shadow:3px 3px 5px #555;box-shadow:3px 3px 5px #555;-webkit-border-radius:5px;border-radius:5px;border-style:solid;border-width:2px;cursor:default}
+.wPaint-modal-close{right:-7px;top:-7px;-webkit-border-radius:10px;border-radius:10px;font-size:8px;line-height:14px;padding:0 4px;font-weight:bold;border-style:solid;border-width:2px;cursor:pointer}
+.wPaint-text-input{border:dotted #00f 1px;background:none}
+.wPaint-modal-img-holder{border:solid #333 1px;-webkit-border-radius:5px;border-radius:5px;margin:3px;padding:2px;cursor:pointer}
+.wPaint-modal-img{width:100px;-webkit-border-radius:4px;border-radius:4px;margin-bottom:0}
+.wPaint-theme-standard .wPaint-menu-holder{-webkit-border-radius:7px;border-radius:7px}
+.wPaint-theme-standard .wPaint-menu-select-holder{-webkit-border-radius:5px;border-radius:5px}
+.wPaint-theme-standard .wPaint-menu-icon{-webkit-border-radius:7px;border-radius:7px}
+.wPaint-theme-standard .wPaint-menu-icon-img{margin:6px 5px 5px 6px;width:18px;height:18px;line-height:18px;font-size:12px}
+.wPaint-theme-standard .wPaint-menu-colorpicker .wPaint-menu-icon-img{margin:3px 2px 2px 3px;width:24px;height:24px;-webkit-border-radius:5px;border-radius:5px}
+.wPaint-theme-standard .wPaint-menu-icon-group .wPaint-menu-select-option{padding:4px}
+.wPaint-theme-standard .wPaint-menu-icon-group-arrow{width:5px;height:3px;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAADCAYAAABbNsX4AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK6wAACusBgosNWgAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOC8xMS8xMyj8hykAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAKElEQVQImV3IwQ0AMAyDQKerspZ3pa9IVXmdGMB8nbbzjrYTNWoA1xeQ3RPyxUyE/gAAAABJRU5ErkJggg==")}
+.wPaint-theme-standard .wPaint-menu-select{line-height:10px;font-size:10px;max-height:136px}
+.wPaint-theme-standard .wPaint-menu-select-option{max-width:50px;padding:4px 7px}
+.wPaint-theme-standard .wPaint-menu-icon-select-img{width:18px;height:18px}
+.wPaint-theme-standard .wPaint-menu-alignment-horizontal.wPaint-menu-nohandle .wPaint-menu-holder{padding-left:4px}
+.wPaint-theme-standard .wPaint-menu-alignment-horizontal .wPaint-menu-icon{margin:4px 5px 4px 0}
+.wPaint-theme-standard .wPaint-menu-alignment-horizontal .wPaint-menu-handle{width:30px;height:39px;margin-right:5px;border-top-left-radius:7px;border-bottom-left-radius:7px}
+.wPaint-theme-standard .wPaint-menu-alignment-vertical.wPaint-menu-nohandle .wPaint-menu-holder{padding-top:4px}
+.wPaint-theme-standard .wPaint-menu-alignment-vertical .wPaint-menu-icon{margin:0 4px 5px 4px}
+.wPaint-theme-standard .wPaint-menu-alignment-vertical .wPaint-menu-handle{width:39px;height:30px;margin-bottom:5px;border-top-left-radius:7px;border-top-right-radius:7px}
+.wPaint-theme-classic .wPaint-menu-holder{border-color:#dadada;background-color:#f0f0f0}
+.wPaint-theme-classic .wPaint-menu-handle{background-color:#dadada;-webkit-box-shadow:inset 1px 1px 3px #fff;box-shadow:inset 1px 1px 3px #fff;border-color:#dadada}
+.wPaint-theme-classic .wPaint-menu-icon{border-color:#b9b9b9;background-color:#b9b9b9;-webkit-box-shadow:inset 2px 2px 3px #eee,1px 1px 2px #666;box-shadow:inset 2px 2px 3px #eee,1px 1px 2px #666}
+.wPaint-theme-classic .wPaint-menu-icon.hover,.wPaint-theme-classic .wPaint-menu-icon.active{border-color:#9cf;background-color:#acf}
+.wPaint-theme-classic .wPaint-menu-icon-img{color:#696969}
+.wPaint-theme-classic .wPaint-menu-select-holder{border-color:#cacaca}
+.wPaint-theme-classic .wPaint-menu-select{color:#494949}
+.wPaint-theme-classic .wPaint-menu-select-option{-webkit-box-shadow:inset 2px 2px 3px #fff;box-shadow:inset 2px 2px 3px #fff;border-top-color:#cacaca;background-color:#f0f0f0}
+.wPaint-theme-classic .wPaint-menu-select-option:hover{-webkit-box-shadow:inset 1px 1px 1px #fff;box-shadow:inset 1px 1px 1px #fff;background-color:#9cf;color:#f0f0f0}
+.wPaint-theme-classic .wPaint-modal-close,.wPaint-theme-classic .wPaint-modal-holder{border-color:#3a3a3a;background-color:#f0f0f0}
diff --git a/static/js/wpaint/wPaint.min.js b/static/js/wpaint/wPaint.min.js
new file mode 100644
index 0000000..3ea04e6
--- /dev/null
+++ b/static/js/wpaint/wPaint.min.js
@@ -0,0 +1 @@
+/*! wPaint - v2.5.0 - 2014-03-01 */!function(a){"use strict";function b(b,c){this.$el=a(b),this.options=c,this.init=!1,this.menus={primary:null,active:null,all:{}},this.previousMode=null,this.width=this.$el.width(),this.height=this.$el.height(),this.ctxBgResize=!1,this.ctxResize=!1,this.generate(),this._init()}function c(a,b,c){this.wPaint=a,this.options=c,this.name=b,this.type=a.menus.primary?"secondary":"primary",this.docked=!0,this.dockOffset={left:0,top:0},this.generate()}b.prototype={generate:function(){function b(b){var c=b?b.capitalize():"",d="canvas"+c,e="ctx"+c;return f[d]=document.createElement("canvas"),f[e]=f[d].getContext("2d"),f["$"+d]=a(f[d]),f["$"+d].attr("class","wPaint-canvas"+(b?"-"+b:"")).attr("width",f.width+"px").attr("height",f.height+"px").css({position:"absolute",left:0,top:0}),f.$el.append(f["$"+d]),f["$"+d]}function c(a){a.preventDefault(),a.stopPropagation(),f.draw=!0,a.canvasEvent="down",f._closeSelectBoxes(),f._callShapeFunc.apply(f,[a])}function d(a){f.draw&&(a.canvasEvent="move",f._callShapeFunc.apply(f,[a]))}function e(a){f.draw&&(f.draw=!1,a.canvasEvent="up",f._callShapeFunc.apply(f,[a]))}if(this.init)return this;var f=this;b("bg"),b("").on("mousedown",c).bindMobileEvents(),b("temp").hide(),a(document).on("mousemove",d).on("mousedown",a.proxy(this._closeSelectBoxes,this)).on("mouseup",e),this.setTheme(this.options.theme)},_init:function(){var a=null,b=null;this.init=!0;for(a in this.options)b="set"+a.capitalize(),this[b]&&this[b](this.options[a]);this._fixMenus(),this.menus.primary._getIcon(this.options.mode).trigger("click")},resize:function(){var a=this.getBg(),b=this.getImage();this.width=this.$el.width(),this.height=this.$el.height(),this.canvasBg.width=this.width,this.canvasBg.height=this.height,this.canvas.width=this.width,this.canvas.height=this.height,this.ctxBgResize===!1&&(this.ctxBgResize=!0,this.setBg(a,!0)),this.ctxResize===!1&&(this.ctxResize=!0,this.setImage(b,"",!0,!0))},setTheme:function(a){var b,c;for(a=a.split(" "),this.$el.attr("class",(this.$el.attr("class")||"").replace(/wPaint-theme-.+\s|wPaint-theme-.+$/,"")),b=0,c=a.length;c>b;b++)this.$el.addClass("wPaint-theme-"+a[b])},setMode:function(a){this.setCursor(a),this.previousMode=this.options.mode,this.options.mode=a},setImage:function(b,c,d,e){function f(){var a=1,b=0,f=0,j=0,k=0,l=h.width,m=h.height;d||((h.width>g.width||h.height>g.height||g.options.imageStretch)&&(b=g.width/h.width,f=g.height/h.height,a=f>b?b:f,l=h.width*a,m=h.height*a),j=(g.width-l)/2,k=(g.height-m)/2),i.clearRect(0,0,g.width,g.height),i.drawImage(h,j,k,l,m),g[c+"Resize"]=!1,e||g._addUndo()}if(!b)return!0;var g=this,h=null,i="";c="ctx"+(c||"").capitalize(),i=this[c],window.rgbHex(b)?(i.clearRect(0,0,this.width,this.height),i.fillStyle=b,i.rect(0,0,this.width,this.height),i.fill()):(h=new Image,h.src=b.toString(),a(h).load(f))},setBg:function(a,b){return a?void this.setImage(a,"bg",b,!0):!0},setCursor:function(b){b=a.fn.wPaint.cursors[b]||a.fn.wPaint.cursors["default"],this.$el.css("cursor",'url("'+this.options.path+b.path+'") '+b.left+" "+b.top+", default")},setMenuOrientation:function(b){a.each(this.menus.all,function(a,c){c.options.aligment=b,c.setAlignment(b)})},getImage:function(b){var c=document.createElement("canvas"),d=c.getContext("2d");return b=b===!1?!1:!0,a(c).css({display:"none",position:"absolute",left:0,top:0}).attr("width",this.width).attr("height",this.height),b&&d.drawImage(this.canvasBg,0,0),d.drawImage(this.canvas,0,0),c.toDataURL()},getBg:function(){return this.canvasBg.toDataURL()},_displayStatus:function(b){var c=this;this.$status||(this.$status=a('<div class="wPaint-status"></div>'),this.$el.append(this.$status)),this.$status.html(b),clearTimeout(this.displayStatusTimer),this.$status.fadeIn(500,function(){c.displayStatusTimer=setTimeout(function(){c.$status.fadeOut(500)},1500)})},_showModal:function(a){function b(){d.remove(),e.remove(),c._createModal(a)}var c=this,d=this.$el.children(".wPaint-modal-bg"),e=this.$el.children(".wPaint-modal");d.length?e.fadeOut(500,b):this._createModal(a)},_createModal:function(b){function c(){f.fadeOut(500,d)}function d(){e.remove(),f.remove()}b=a('<div class="wPaint-modal-content"></div>').append(b.children());var e=a('<div class="wPaint-modal-bg"></div>'),f=a('<div class="wPaint-modal"></div>'),g=a('<div class="wPaint-modal-holder"></div>'),h=a('<div class="wPaint-modal-close">X</div>');h.on("click",c),f.append(g.append(b)).append(h),this.$el.append(e).append(f),f.css({left:this.$el.outerWidth()/2-f.outerWidth(!0)/2,top:this.$el.outerHeight()/2-f.outerHeight(!0)/2}),f.fadeIn(500)},_createMenu:function(a,b){return b=b||{},b.alignment=this.options.menuOrientation,b.handle=this.options.menuHandle,new c(this,a,b)},_fixMenus:function(){function b(b,d){var e=a(d),f=e.clone();f.appendTo(c.$el),f.outerHeight()===f.get(0).scrollHeight&&e.css({overflowY:"auto"}),f.remove()}var c=this,d=null;for(var e in this.menus.all)d=c.menus.all[e].$menu.find(".wPaint-menu-select-holder"),d.length&&d.children().each(b)},_closeSelectBoxes:function(a){var b,c;for(b in this.menus.all)c=this.menus.all[b].$menuHolder.children(".wPaint-menu-icon-select"),a&&(c=c.not(".wPaint-menu-icon-name-"+a.name)),c.children(".wPaint-menu-select-holder").hide()},_callShapeFunc:function(a){var b=this.$canvas.offset(),c=a.canvasEvent.capitalize(),d="_draw"+this.options.mode.capitalize()+c;a.pageX=Math.floor(a.pageX-b.left),a.pageY=Math.floor(a.pageY-b.top),this[d]&&this[d].apply(this,[a]),this.options["draw"+c]&&this.options["_draw"+c].apply(this,[a]),"Down"===c&&this.options.onShapeDown?this.options.onShapeDown.apply(this,[a]):"Move"===c&&this.options.onShapeMove?this.options.onShapeMove.apply(this,[a]):"Up"===c&&this.options.onShapeUp&&this.options.onShapeUp.apply(this,[a])},_stopPropagation:function(a){a.stopPropagation()},_drawShapeDown:function(a){this.$canvasTemp.css({left:a.PageX,top:a.PageY}).attr("width",0).attr("height",0).show(),this.canvasTempLeftOriginal=a.pageX,this.canvasTempTopOriginal=a.pageY},_drawShapeMove:function(b,c){var d=this.canvasTempLeftOriginal,e=this.canvasTempTopOriginal;c=c||2,b.left=b.pageX<d?b.pageX:d,b.top=b.pageY<e?b.pageY:e,b.width=Math.abs(b.pageX-d),b.height=Math.abs(b.pageY-e),b.x=this.options.lineWidth/2*c,b.y=this.options.lineWidth/2*c,b.w=b.width-this.options.lineWidth*c,b.h=b.height-this.options.lineWidth*c,a(this.canvasTemp).css({left:b.left,top:b.top}).attr("width",b.width).attr("height",b.height),this.canvasTempLeftNew=b.left,this.canvasTempTopNew=b.top,c=c||2,this.ctxTemp.fillStyle=this.options.fillStyle,this.ctxTemp.strokeStyle=this.options.strokeStyle,this.ctxTemp.lineWidth=this.options.lineWidth*c},_drawShapeUp:function(){this.ctx.drawImage(this.canvasTemp,this.canvasTempLeftNew,this.canvasTempTopNew),this.$canvasTemp.hide()},_drawDropperDown:function(a){var b={x:a.pageX,y:a.pageY},c=this._getPixel(this.ctx,b),d=null;d="rgba("+[c.r,c.g,c.b,c.a].join(",")+")",this.options[this.dropper]=d,this.menus.active._getIcon(this.dropper).wColorPicker("color",d)},_drawDropperUp:function(){this.setMode(this.previousMode)},_getPixel:function(a,b){var c=a.getImageData(0,0,this.width,this.height),d=c.data,e=4*(b.y*c.width+b.x);return{r:d[e],g:d[e+1],b:d[e+2],a:d[e+3]}}},c.prototype={generate:function(){this.$menu=a('<div class="wPaint-menu"></div>'),this.$menuHolder=a('<div class="wPaint-menu-holder wPaint-menu-name-'+this.name+'"></div>'),this.options.handle?this.$menuHandle=this._createHandle():this.$menu.addClass("wPaint-menu-nohandle"),"primary"===this.type?(this.wPaint.menus.primary=this,this.setOffsetLeft(this.options.offsetLeft),this.setOffsetTop(this.options.offsetTop)):"secondary"===this.type&&this.$menu.hide(),this.$menu.append(this.$menuHolder.append(this.$menuHandle)),this.reset(),this.wPaint.$el.append(this.$menu),this.setAlignment(this.options.alignment)},reset:function(){function b(a){d._appendItem(a)}var c,d=this,e=a.fn.wPaint.menus[this.name];for(c in e.items)this.$menuHolder.children(".wPaint-menu-icon-name-"+c).length||(e.items[c].name=c,e.items[c].img=d.wPaint.options.path+(e.items[c].img||e.img),b(e.items[c]))},_appendItem:function(a){var b=this["_createIcon"+a.icon.capitalize()](a);a.after?this.$menuHolder.children(".wPaint-menu-icon-name-"+a.after).after(b):this.$menuHolder.append(b)},setOffsetLeft:function(a){this.$menu.css({left:a})},setOffsetTop:function(a){this.$menu.css({top:a})},setAlignment:function(a){var b=this.$menu.css("left");this.$menu.attr("class",this.$menu.attr("class").replace(/wPaint-menu-alignment-.+\s|wPaint-menu-alignment-.+$/,"")),this.$menu.addClass("wPaint-menu-alignment-"+a),this.$menu.width("auto").css("left",-1e4),this.$menu.width(this.$menu.width()).css("left",b),"secondary"===this.type&&("horizontal"===this.options.alignment?this.dockOffset.top=this.wPaint.menus.primary.$menu.outerHeight(!0):this.dockOffset.left=this.wPaint.menus.primary.$menu.outerWidth(!0))},_createHandle:function(){function b(){e.docked=!1,e._setDrag()}function c(){a.each(e.$menu.data("ui-draggable").snapElements,function(a,b){var c=e.$menu.offset(),d=e.wPaint.menus.primary.$menu.offset();e.dockOffset.left=c.left-d.left,e.dockOffset.top=c.top-d.top,e.docked=b.snapping}),e._setDrag()}function d(){e._setIndex()}var e=this,f=a('<div class="wPaint-menu-handle"></div>');return this.$menu.draggable({handle:f}),"secondary"===this.type&&(this.$menu.draggable("option","snap",this.wPaint.menus.primary.$menu),this.$menu.draggable("option","start",b),this.$menu.draggable("option","stop",c),this.$menu.draggable("option","drag",d)),f.bindMobileEvents(),f},_createIconBase:function(b){function c(b){var c=a(b.currentTarget);c.siblings(".hover").removeClass("hover"),c.hasClass("disabled")||c.addClass("hover")}function d(b){a(b.currentTarget).removeClass("hover")}function e(){f.wPaint.menus.active=f}var f=this,g=a('<div class="wPaint-menu-icon wPaint-menu-icon-name-'+b.name+'"></div>'),h=a('<div class="wPaint-menu-icon-img"></div>'),i=h.realWidth(null,null,this.wPaint.$el);return g.attr("title",b.title).on("mousedown",a.proxy(this.wPaint._closeSelectBoxes,this.wPaint,b)).on("mouseenter",c).on("mouseleave",d).on("click",e),a.isNumeric(b.index)&&h.css({backgroundImage:"url("+b.img+")",backgroundPosition:-i*b.index+"px 0px"}),g.append(h)},_createIconGroup:function(b){function c(){h.children(".wPaint-menu-select-holder").is(":visible")||b.callback.apply(f.wPaint,[])}function d(){h.addClass("active").siblings(".active").removeClass("active")}function e(){h.attr("title",b.title).off("click.setIcon").on("click.setIcon",c),h.children(".wPaint-menu-icon-img").css(g),b.callback.apply(f.wPaint,[])}var f=this,g={backgroundImage:"url("+b.img+")"},h=this.$menuHolder.children(".wPaint-menu-icon-group-"+b.group),i=h.length,j=null,k=null,l=null,m=0;return i||(h=this._createIconBase(b).addClass("wPaint-menu-icon-group wPaint-menu-icon-group-"+b.group).on("click.setIcon",c).on("mousedown",a.proxy(this._iconClick,this))),m=h.children(".wPaint-menu-icon-img").realWidth(null,null,this.wPaint.$el),g.backgroundPosition=-m*b.index+"px center",j=h.children(".wPaint-menu-select-holder"),j.length||(j=this._createSelectBox(h),j.children().on("click",d)),l=a('<div class="wPaint-menu-icon-select-img"></div>').attr("title",b.title).css(g),k=this._createSelectOption(j,l).addClass("wPaint-menu-icon-name-"+b.name).on("click",e),b.after&&j.children(".wPaint-menu-select").children(".wPaint-menu-icon-name-"+b.after).after(k),i?void 0:h},_createIconGeneric:function(a){return this._createIconActivate(a)},_createIconActivate:function(a){function b(b){"generic"!==a.icon&&c._iconClick(b),a.callback.apply(c.wPaint,[b])}if(a.group)return this._createIconGroup(a);var c=this,d=this._createIconBase(a);return d.on("click",b),d},_isIconDisabled:function(a){return this.$menuHolder.children(".wPaint-menu-icon-name-"+a).hasClass("disabled")},_setIconDisabled:function(a,b){var c=this.$menuHolder.children(".wPaint-menu-icon-name-"+a);b?c.addClass("disabled").removeClass("hover"):c.removeClass("disabled")},_getIcon:function(a){return this.$menuHolder.children(".wPaint-menu-icon-name-"+a)},_iconClick:function(b){var c=a(b.currentTarget),d=this.wPaint.menus.all;for(var e in d)d[e]&&"secondary"===d[e].type&&d[e].$menu.hide();c.siblings(".active").removeClass("active"),c.hasClass("disabled")||c.addClass("active")},_createIconToggle:function(a){function b(){d.toggleClass("active"),a.callback.apply(c.wPaint,[d.hasClass("active")])}var c=this,d=this._createIconBase(a);return d.on("click",b),d},_createIconSelect:function(b){function c(c){h.children(".wPaint-menu-icon-img").html(a(c.currentTarget).html()),b.callback.apply(g.wPaint,[a(c.currentTarget).html()])}var d,e,f,g=this,h=this._createIconBase(b),i=this._createSelectBox(h);for(d=0,e=b.range.length;e>d;d++)f=this._createSelectOption(i,b.range[d]),f.on("click",c),b.useRange&&f.css(b.name,b.range[d]);return h},_createSelectBox:function(b){function c(a){a.stopPropagation(),g.hide()}function d(){i=setTimeout(function(){g.toggle()},200)}function e(){clearTimeout(i)}function f(){g.toggle()}var g=a('<div class="wPaint-menu-select-holder"></div>'),h=a('<div class="wPaint-menu-select"></div>'),i=null;return g.on("mousedown mouseup",this.wPaint._stopPropagation).on("click",c).hide(),g.css("horizontal"===this.options.alignment?{left:0,top:b.children(".wPaint-menu-icon-img").realHeight("outer",!0,this.wPaint.$el)}:{left:b.children(".wPaint-menu-icon-img").realWidth("outer",!0,this.wPaint.$el),top:0}),b.addClass("wPaint-menu-icon-select").append('<div class="wPaint-menu-icon-group-arrow"></div>').append(g.append(h)),b.hasClass("wPaint-menu-icon-group")?b.on("mousedown",d).on("mouseup",e):b.on("click",f),g},_createSelectOption:function(b,c){var d=b.children(".wPaint-menu-select"),e=a('<div class="wPaint-menu-select-option"></div>').append(c);return d.children().length||e.addClass("first"),d.append(e),e},_setSelectValue:function(a,b){this._getIcon(a).children(".wPaint-menu-icon-img").html(b)},_createIconColorPicker:function(a){function b(){"dropper"===e.wPaint.options.mode&&e.wPaint.setMode(e.wPaint.previousMode)}function c(b){a.callback.apply(e.wPaint,[b])}function d(){f.trigger("click"),e.wPaint.dropper=a.name,e.wPaint.setMode("dropper")}var e=this,f=this._createIconBase(a);return f.on("click",b).addClass("wPaint-menu-colorpicker").wColorPicker({mode:"click",generateButton:!1,dropperButton:!0,onSelect:c,onDropper:d}),f},_setColorPickerValue:function(a,b){this._getIcon(a).children(".wPaint-menu-icon-img").css("backgroundColor",b)},_createIconMenu:function(a){function b(){c.wPaint.setCursor(a.name);var b=c.wPaint.menus.all[a.name];b.$menu.toggle(),c.handle?b._setDrag():b._setPosition()}var c=this,d=this._createIconActivate(a);return d.on("click",b),d},_setDrag:function(){var b=this.$menu,c=null,d=null;b.is(":visible")&&(this.docked&&(c=d=a.proxy(this._setPosition,this),this._setPosition()),this.wPaint.menus.primary.$menu.draggable("option","drag",c),this.wPaint.menus.primary.$menu.draggable("option","stop",d))},_setPosition:function(){var a=this.wPaint.menus.primary.$menu.position();this.$menu.css({left:a.left+this.dockOffset.left,top:a.top+this.dockOffset.top})},_setIndex:function(){var a=this.wPaint.menus.primary.$menu.offset(),b=this.$menu.offset();b.top<a.top||b.left<a.left?this.$menu.addClass("wPaint-menu-behind"):this.$menu.removeClass("wPaint-menu-behind")}},a.support.canvas=document.createElement("canvas").getContext,a.fn.wPaint=function(c,d){function e(){return a.support.canvas?a.proxy(f,this)():(a(this).html("Browser does not support HTML5 canvas, please upgrade to a more modern browser."),!1)}function f(){var d=a.data(this,"wPaint");return d||(d=new b(this,a.extend(!0,{},c)),a.data(this,"wPaint",d)),d}function g(){var b=a.data(this,"wPaint");b&&(b[c]?b[c].apply(b,[d]):void 0!==d?(b[i]&&b[i].apply(b,[d]),b.options[c]&&(b.options[c]=d)):h.push(b[i]?b[i].apply(b,[d]):b.options[c]?b.options[c]:void 0))}if("string"==typeof c){var h=[],i=(d?"set":"get")+c.charAt(0).toUpperCase()+c.substring(1);return this.each(g),h.length?1===h.length?h[0]:h:this}return c=a.extend({},a.fn.wPaint.defaults,c),c.lineWidth=parseInt(c.lineWidth,10),c.fontSize=parseInt(c.fontSize,10),this.each(e)},a.fn.wPaint.extend=function(a,d){function e(c){if(d[c]){var e=b.prototype[c],f=a[c];d[c]=function(){e.apply(this,arguments),f.apply(this,arguments)}}else d[c]=a[c]}var f;d="menu"===d?c.prototype:b.prototype;for(f in a)e(f)},a.fn.wPaint.menus={},a.fn.wPaint.cursors={},a.fn.wPaint.defaults={path:"/",theme:"standard classic",autoScaleImage:!0,autoCenterImage:!0,menuHandle:!0,menuOrientation:"horizontal",menuOffsetLeft:5,menuOffsetTop:5,bg:null,image:null,imageStretch:!1,onShapeDown:null,onShapeMove:null,onShapeUp:null}}(jQuery),function(){String.prototype.capitalize||(String.prototype.capitalize=function(){return this.slice(0,1).toUpperCase()+this.slice(1)})}(),function(a){a.fn.realWidth=function(b,c,d){var e=null,f=null,g=null;return b="inner"===b||"outer"===b?b:"",g=""===b?"width":b+"Width",c=c===!0?!0:!1,f=a(this).clone().css({position:"absolute",left:-1e4}).appendTo(d||"body"),e=c?f[g](c):f[g](),f.remove(),e},a.fn.realHeight=function(b,c,d){var e=null,f=null,g=null;return b="inner"===b||"outer"===b?b:"",g=""===b?"height":b+"Height",c=c===!0?!0:!1,f=a(this).clone().css({position:"absolute",left:-1e4}).appendTo(d||"body"),e=c?f[g](c):f[g](),f.remove(),e},a.fn.bindMobileEvents=function(){a(this).on("touchstart touchmove touchend touchcancel",function(){var a=event.changedTouches||event.originalEvent.targetTouches,b=a[0],c="";switch(event.type){case"touchstart":c="mousedown";break;case"touchmove":c="mousemove",event.preventDefault();break;case"touchend":c="mouseup";break;default:return}var d=document.createEvent("MouseEvent");d.initMouseEvent(c,!0,!0,window,1,b.screenX,b.screenY,b.clientX,b.clientY,!1,!1,!1,!1,0,null),b.target.dispatchEvent(d)})}}(jQuery); \ No newline at end of file
diff --git a/static/meta/bbs.png b/static/meta/bbs.png
new file mode 100644
index 0000000..2ce11b3
--- /dev/null
+++ b/static/meta/bbs.png
Binary files differ
diff --git a/static/meta/faq_1.png b/static/meta/faq_1.png
new file mode 100644
index 0000000..0932873
--- /dev/null
+++ b/static/meta/faq_1.png
Binary files differ
diff --git a/static/meta/faq_2.png b/static/meta/faq_2.png
new file mode 100644
index 0000000..0e101be
--- /dev/null
+++ b/static/meta/faq_2.png
Binary files differ
diff --git a/static/meta/faq_3.png b/static/meta/faq_3.png
new file mode 100644
index 0000000..dd4e657
--- /dev/null
+++ b/static/meta/faq_3.png
Binary files differ
diff --git a/static/meta/ib.png b/static/meta/ib.png
new file mode 100644
index 0000000..7f52460
--- /dev/null
+++ b/static/meta/ib.png
Binary files differ
diff --git a/static/meta/portada_6.jpg b/static/meta/portada_6.jpg
new file mode 100644
index 0000000..3aaff38
--- /dev/null
+++ b/static/meta/portada_6.jpg
Binary files differ
diff --git a/static/meta/portada_7.jpg b/static/meta/portada_7.jpg
new file mode 100644
index 0000000..3f9ed25
--- /dev/null
+++ b/static/meta/portada_7.jpg
Binary files differ
diff --git a/static/meta/portada_8.jpg b/static/meta/portada_8.jpg
new file mode 100644
index 0000000..c28ef87
--- /dev/null
+++ b/static/meta/portada_8.jpg
Binary files differ
diff --git a/static/meta/portada_asp.gif b/static/meta/portada_asp.gif
new file mode 100644
index 0000000..94c1e83
--- /dev/null
+++ b/static/meta/portada_asp.gif
Binary files differ
diff --git a/static/meta/portada_cap1.jpg b/static/meta/portada_cap1.jpg
new file mode 100644
index 0000000..3a980cb
--- /dev/null
+++ b/static/meta/portada_cap1.jpg
Binary files differ
diff --git a/static/meta/portada_orig5.jpg b/static/meta/portada_orig5.jpg
new file mode 100644
index 0000000..5c4e98b
--- /dev/null
+++ b/static/meta/portada_orig5.jpg
Binary files differ
diff --git a/static/meta/portada_toesca.jpg b/static/meta/portada_toesca.jpg
new file mode 100644
index 0000000..0d1c36a
--- /dev/null
+++ b/static/meta/portada_toesca.jpg
Binary files differ
diff --git a/static/meta/portadaphil.jpg b/static/meta/portadaphil.jpg
new file mode 100644
index 0000000..0d9af00
--- /dev/null
+++ b/static/meta/portadaphil.jpg
Binary files differ
diff --git a/static/meta/primeraportada.png b/static/meta/primeraportada.png
new file mode 100644
index 0000000..f4db57b
--- /dev/null
+++ b/static/meta/primeraportada.png
Binary files differ
diff --git a/static/meta/sanvalentin2013.jpg b/static/meta/sanvalentin2013.jpg
new file mode 100644
index 0000000..2596642
--- /dev/null
+++ b/static/meta/sanvalentin2013.jpg
Binary files differ
diff --git a/static/meta/welcome.gif b/static/meta/welcome.gif
new file mode 100644
index 0000000..4eeb392
--- /dev/null
+++ b/static/meta/welcome.gif
Binary files differ
diff --git a/static/meta/welcome.jpg b/static/meta/welcome.jpg
new file mode 100644
index 0000000..ae9f0d2
--- /dev/null
+++ b/static/meta/welcome.jpg
Binary files differ
diff --git a/static/mime/epub.png b/static/mime/epub.png
new file mode 100644
index 0000000..b6800ea
--- /dev/null
+++ b/static/mime/epub.png
Binary files differ
diff --git a/static/mime/epub_small.png b/static/mime/epub_small.png
new file mode 100644
index 0000000..71da41c
--- /dev/null
+++ b/static/mime/epub_small.png
Binary files differ
diff --git a/static/mime/mod.png b/static/mime/mod.png
new file mode 100644
index 0000000..b519172
--- /dev/null
+++ b/static/mime/mod.png
Binary files differ
diff --git a/static/mime/mod_small.png b/static/mime/mod_small.png
new file mode 100644
index 0000000..16887f8
--- /dev/null
+++ b/static/mime/mod_small.png
Binary files differ
diff --git a/static/mime/pdf.png b/static/mime/pdf.png
new file mode 100644
index 0000000..0c0a98a
--- /dev/null
+++ b/static/mime/pdf.png
Binary files differ
diff --git a/static/mime/pdf_small.png b/static/mime/pdf_small.png
new file mode 100644
index 0000000..9af8b84
--- /dev/null
+++ b/static/mime/pdf_small.png
Binary files differ
diff --git a/static/mime/s3m.png b/static/mime/s3m.png
new file mode 100644
index 0000000..ab14689
--- /dev/null
+++ b/static/mime/s3m.png
Binary files differ
diff --git a/static/mime/s3m_small.png b/static/mime/s3m_small.png
new file mode 100644
index 0000000..81da112
--- /dev/null
+++ b/static/mime/s3m_small.png
Binary files differ
diff --git a/static/mime/swf.png b/static/mime/swf.png
new file mode 100644
index 0000000..75c60bb
--- /dev/null
+++ b/static/mime/swf.png
Binary files differ
diff --git a/static/mime/swf_small.png b/static/mime/swf_small.png
new file mode 100644
index 0000000..f6fa215
--- /dev/null
+++ b/static/mime/swf_small.png
Binary files differ
diff --git a/static/mime/torrent.png b/static/mime/torrent.png
new file mode 100644
index 0000000..c580646
--- /dev/null
+++ b/static/mime/torrent.png
Binary files differ
diff --git a/static/mime/torrent_small.png b/static/mime/torrent_small.png
new file mode 100644
index 0000000..a939e12
--- /dev/null
+++ b/static/mime/torrent_small.png
Binary files differ
diff --git a/static/mime/xm.png b/static/mime/xm.png
new file mode 100644
index 0000000..b053172
--- /dev/null
+++ b/static/mime/xm.png
Binary files differ
diff --git a/static/mime/xm_small.png b/static/mime/xm_small.png
new file mode 100644
index 0000000..2510de7
--- /dev/null
+++ b/static/mime/xm_small.png
Binary files differ