diff options
author | bai | 2019-03-29 02:14:43 +0000 |
---|---|---|
committer | bai | 2019-03-29 02:14:43 +0000 |
commit | 95dfe14528663923ca2a88ec928f1d8d9df2402b (patch) | |
tree | 5bc88d1466957f1aa39043b056bde5c439648022 /static/js | |
download | weabot-95dfe14528663923ca2a88ec928f1d8d9df2402b.tar.gz weabot-95dfe14528663923ca2a88ec928f1d8d9df2402b.tar.xz weabot-95dfe14528663923ca2a88ec928f1d8d9df2402b.zip |
Init
Diffstat (limited to 'static/js')
84 files changed, 22645 insertions, 0 deletions
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&©&&(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&painttmp=.png" + // という文字列を返します。 + // + // NEOでは、responseに文字列"painttmp="が含まれる場合は + // <PARAM>で指定されたurl_exitを無視して、このURLにジャンプします。 + var responseURL = request.response.replace(/&/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&painttmp=.png" + // という文字列を返します。 + // + // NEOでは、responseに文字列"painttmp="が含まれる場合は + // <PARAM>で指定されたurl_exitを無視して、このURLにジャンプします。 + var responseURL = request.response.replace(/&/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 ", + "投稿": "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": "©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": "©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 .. OJSƂēǂݍłADȏ palette_selfy() Ăяoĉ.
+ var selfv=new Array(); var selfytag=new Array(); //Ȃ.
+
+//ݒ ------------------------------------------------------------
+// selfv[*] ́Aꂼ̐ݒɂƁA̋@\̃{^\Ȃł܂.
+
+// +-l̂Ƃ
+var pnum = 10; // +- ̃ftHgl
+selfv[0] = 'size=3 style="text-align:right">'; // l^O(type=text)̒g
+
+
+// pbgXg.
+// ..evf̒̐F́A1Ȃ瑼13F͂̐FɁ2ʂ肩玩擾A
+var psx = 0; // 0:ʓx+x. 1:Fz.
+
+// ʓx+xɂƂ̐F. (ݒ肷ꍇ́A11̐F \n ŋ)
+var pdefs = new Array(
+ '#ffffff',
+ '#ffe6e6','#ffece6','#fff3e6','#fff9e6','#ffffe6',
+ '#f3ffe6','#e6fff3','#e6f3ff','#ffe6ff','#eeddbb',
+''); // Ƃ̗vf̓XLbv.
+
+// FŏzƂ̐F. (ݒ肷ꍇ́A11̐F \n ŋ)
+var pdefx = new Array(
+ '#ffffff',
+ '#ffe6e6','#ffcccc','#ff9999','#e6cccc','#e69999',
+ '#cc9999','#cc6666','#996666','#993333','#660000',
+''); // Ƃ̗vf̓XLbv.
+
+
+// ftHg̃pbgJ[ (ԍŏɃAvbgɂł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';
+
+
+// TvJ[
+ // \pbg̃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] = ' '; // tHg
+selfv[2] = 'style="font-size:xx-small; background-color:$FONT;"';
+ // tHg^O̒g(u$FONTv:16i@RGBFAmɓKp鑮́3)
+ // c color, style="color" style="background", style="background-color")
+
+ // 艺 ">"(^O) Ă //
+
+// pbg̑I{^(type=radio)^O̒g
+selfv[3] = 'style="border-width:0;" title="ftHg̃pbg">'; // ftHgF
+selfv[4] = 'style="border-width:0;" title="̃pbggB\n`FbNĂƂɂɉƁA`FbNOA\nFzAʓx+xpbgɁB(1Ԃ̐F{F)">'; // I
+
+
+// {^(type=button)^O̒g
+selfv[5] = 'value="H" title="Fpbg (1Ԃ̐F{F)">'; // F
+selfv[6] = 'value="S" title="ʓxpbg (1Ԃ̐F{F)">'; // ʓx
+selfv[7] = 'value="B" title="xpbg (1Ԃ̐F{F)">\n'; // x
+selfv[8] = 'value="o" title="ɍ̃pbgۑ">'; // Z[u
+selfv[9] = 'value="x" title="̃pbgftHgɖ߂"><br>\n'; // ftHg
+
+selfv[10] = 'value="H+" title="pbgŜ̐F{">'; // F+
+selfv[11] = 'value="H-" title="pbgŜ̐F|">'; // F-
+selfv[12] = 'value="S+" title="pbgŜ̍ʓx{">'; // ʓx+
+selfv[13] = 'value="S-" title="pbgŜ̍ʓx|">'; // ʓx-
+selfv[14] = 'value="B+" title="pbgŜ̖x{">\n'; // x+
+selfv[15] = 'value="B-" title="pbgŜ̖x|">\n'; // x-
+selfv[16] = 'value="RGB+" title="pbgŜRGB{"><br>\n'; // RGB+
+selfv[17] = 'value="RGB-" title="pbgŜRGB|"><br>\n'; // RGB-
+
+
+// Of[V̂Ƃ
+selfv[18] = 'style="border-width:0;" title="2_ɃOf[V (1Ԃ̐F14Ԃ̐F)" checked>2'; // 2_
+selfv[19] = 'style="border-width:0;" title="3_ɃOf[V (1ԁA8ԁA14Ԃ̐F)">3'; // 3_
+selfv[20] = 'style="border-width:0;" title="4_ɃOf[V (1A6A10A14Ԃ̐F)">4<br>\n'; // 4_
+selfv[21] = 'value="RGB" title="RGBŃOf[V">\n'; // RGB?
+selfv[22] = 'value="+HSB" title="+HSBŃOf[V (F{)">\n'; // +HSB
+selfv[23] = 'value="-HSB" title="-HSBŃOf[V (F|)"><br>\n'; // -HSB
+
+
+// ljE폜
+selfv[24] = 'value="+" title="pbglj܂">'; // lj
+selfv[25] = 'value="-" title="I𒆂̃pbg폜܂">\n'; // 폜
+
+
+// Z[uEI[gZ[u
+selfv[26] = 'checked title="Ƀ`FbNĂƁAFύXƂA\n@ŕۑpbgɃpbgZ[u܂B\nۑKp̂́A\n@`FbNĂpbg瑼̃pbgɈړƂA\n@`FbNĂpbgH/S/B{^ƂA\n@2̂ƂłBTv̐Fς܂B\nAɃ`FbNĂȂĂA\n@蓮ŃZ[u{^Apbgɕۑ܂B">'; // Z[u
+selfv[27] = 'value="O" title="̑Ŝ̃pbgNbL[ɕۑ"><br>\n'; // Z[u
+
+
+// ftHg̃pbg F360ɂ邩Aʓx++x-- ɂ邩
+selfv[28] = 'style="border-width:0;" title="ftHg̃pbǵAFŏz">H<sup>o</sup>'; // H
+selfv[29] = 'style="border-width:0;" title="ftHg̃pbǵAʓx{Ax|ŃXg">+S-B'; // +S-B
+selfv[30] = 'value="X" title="Ŝ̃pbgftHgɖ߂"><br>\n'; // ftHg
+
+
+// UPLOAD / DOWNLOAD
+selfv[31] = 'value="" size=8 title="pbgf[^B\nEAbv[hƂ́Aɓ\tĂB\nE_E[hƂ́AɃf[^o͂܂B\n@ [J̃eLXgɂłۑĂB\npbgf[^́A\n pals = new Array(\'#FFFFFF\',\'#B47575\\n#888888\\n...\');\n@̂悤ɁAJS̔z`ŏ܂B">\n'; //
+selfv[32] = 'value="" title="pbgf[^Abv[h">'; //
+selfv[33] = 'value="" title="Ƀpbgf[^_E[h"><br>\n'; //
+
+
+// ̃pbge[u͂łA\[XƂ^OƂ (form^O͏_)
+// tH[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';
+
+// tH[̊_1 (ʂ̃pbg ` Ŝ HSBARGB +- Ƃ)
+selfytag[1] = '<div style="text-align:right; padding:5;">\n';
+
+// tH[̊_2 (Ŝ HSBARGB +- Ƃ ` Of[V)
+selfytag[2] = '</div>\n<div style="text-align:right; padding:0 5 5 5;"">\nGradation';
+
+// tH[̊_3 (Of[V ` pbg̒ljE폜{^)
+selfytag[3] = '</div>\n<div style="text-align:right; padding:0 5 0 5;"">\nPalette';
+
+// tH[̊_4 (pbg̒ljE폜{^ ` Z[u{^)
+selfytag[4] = '\nSave';
+
+// tH[̊_5 (Z[u{^ ` Default H++/+S-B ǂ炩)
+selfytag[5] = '</div>\n<div style="text-align:right; padding:3 5 2 5;"">\nDefault';
+
+// tH[̊_6 (Default H++/+S-B ǂ炩 ` pbg̃Abv/_E[h)
+selfytag[6] = '</div>\n<div style="text-align:right; padding:0 5 0 5;">\nUpdata ';
+
+// tH[I
+selfytag[7] = '</div>\n</div>\n</td></form></tr></table>\n';
+//ݒ肨 ------------------------------------------------------
+
+
+// l (ƂŎgl)
+var d = document;
+var pon,pno; // radio`FbNH / `FbNpbgNO.
+var qon,qno,qmo; // buttonvbVH / vbVpbgNO.
+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; }
+
+
+// -------------------------------------------------------------------------
+// HSBRGB vZ. l0`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));
+}
+
+
+// RGBHSB vZ. l0`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));
+}
+
+
+// RGB16RGB10 \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);
+}
+
+
+// 1016i@
+function format16(n){
+ n = Number(n).toString(16);
+ if(n.length<2){ n='0'+n; }
+ return(n);
+}
+
+
+
+
+// -------------------------------------------------------------------------
+// pbg ( q=1:Avbgpbgɏo͂Ȃ. lst=1:ŏ̂Ƃ
+function rady(p,q,lst){
+ var d = document;
+ var df = d.forms.palepale;
+
+ // ftHgpbg
+ 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); }// HXg
+ else{ cs = sb_list(p,n); } // +S-B Xg
+
+ 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')));
+ }
+}
+
+
+// HXg
+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 Xg
+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/BXgAbv
+function onplus(p,m){
+ var d = document;
+ var df = d.forms.palepale;
+ var n = Number(df.num.value); //+-
+ if(pon==1 && pno==p){ poncheck(); }
+
+ // ÂƂ
+ 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')));
+}
+
+
+// ŜH/S/BvX}CiX
+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')));
+}
+
+
+// ŜRGBvX}CiX
+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')));
+}
+
+
+// Of[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
+ }
+ // pbg̐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')));
+}
+
+
+// -------------------------------------------------------------------------
+// pbg̃TvJ[
+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;
+}
+
+
+// pbg̃Xg
+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); //Tv
+
+ // 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;
+}
+
+
+// `FbNAtHgJ[̃Tvύ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; }
+ }
+ }
+}
+
+
+// checkO
+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; }
+ }
+}
+
+
+// ȑÕpbgۑ
+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); }
+ }
+ }
+}
+
+
+// pbgZ[u
+function savy(p){
+ var d = document;
+ pals[p] = String(d.paintbbs.getColors());
+ checkin(p);
+ pcookset(1);
+ pon=1; pno=p;
+}
+
+
+// pbgftHg
+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); }
+}
+
+
+// pbglj
+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);
+ }
+}
+
+
+// pbg폜
+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();
+}
+
+
+// pbgftHg
+function def_list(){
+ var okd = confirm("Ŝ̃pbgftHgɖ߂܂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); }
+ }
+ }
+}
+
+
+// ftHg h_sb ̃tH[̃`FbN. HɃ`FbNĂȂ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;
+}
+
+
+// pbgf[^ Abv[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); }
+ }
+ }
+}
+
+
+// pbgf[^ _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; }
+}
+
+
+// Ŝ̃pbgNbL[Ƀ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();
+}
+
+
+// Ŝ̃pbgNbL[烍[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[ZNg̒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[ZNg
+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; //pbgw肪Ƃ
+
+ // browzer
+ if(brwz!=1 && brwz!=2){ return; }
+
+ // pbgƃpbgNbL[
+ 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> </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');
+ }
+ // pbgXg
+ if(pdefs||pdefx) d.write('<div id="palelist">\n'+palette_list(1)+'</div>\n');
+
+ // Ŝ 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[ZNg
+ 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
+
+ // ljE폜
+ 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[uEI[gZ[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
+
+ // ftHg
+ 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":"CAte 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 Binary files differnew file mode 100644 index 0000000..dfb0f3e --- /dev/null +++ b/static/js/wpaint/demo/img/facebook-icon.png diff --git a/static/js/wpaint/demo/img/favicon.ico b/static/js/wpaint/demo/img/favicon.ico Binary files differnew file mode 100644 index 0000000..9bd6326 --- /dev/null +++ b/static/js/wpaint/demo/img/favicon.ico diff --git a/static/js/wpaint/demo/img/forkme_right_darkblue.png b/static/js/wpaint/demo/img/forkme_right_darkblue.png Binary files differnew file mode 100644 index 0000000..146ef8a --- /dev/null +++ b/static/js/wpaint/demo/img/forkme_right_darkblue.png diff --git a/static/js/wpaint/demo/img/github-icon.png b/static/js/wpaint/demo/img/github-icon.png Binary files differnew file mode 100644 index 0000000..a28067c --- /dev/null +++ b/static/js/wpaint/demo/img/github-icon.png diff --git a/static/js/wpaint/demo/img/googleplus-icon.png b/static/js/wpaint/demo/img/googleplus-icon.png Binary files differnew file mode 100644 index 0000000..6567f6e --- /dev/null +++ b/static/js/wpaint/demo/img/googleplus-icon.png diff --git a/static/js/wpaint/demo/img/linkedin-icon.png b/static/js/wpaint/demo/img/linkedin-icon.png Binary files differnew file mode 100644 index 0000000..a2628e7 --- /dev/null +++ b/static/js/wpaint/demo/img/linkedin-icon.png diff --git a/static/js/wpaint/demo/img/rss-icon.png b/static/js/wpaint/demo/img/rss-icon.png Binary files differnew file mode 100644 index 0000000..faae141 --- /dev/null +++ b/static/js/wpaint/demo/img/rss-icon.png diff --git a/static/js/wpaint/demo/img/stumbleupon-icon.png b/static/js/wpaint/demo/img/stumbleupon-icon.png Binary files differnew file mode 100644 index 0000000..5e82ea8 --- /dev/null +++ b/static/js/wpaint/demo/img/stumbleupon-icon.png diff --git a/static/js/wpaint/demo/img/twitter-icon.png b/static/js/wpaint/demo/img/twitter-icon.png Binary files differnew file mode 100644 index 0000000..499ca0c --- /dev/null +++ b/static/js/wpaint/demo/img/twitter-icon.png 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 Binary files differnew file mode 100644 index 0000000..a5bd0f6 --- /dev/null +++ b/static/js/wpaint/demo/img/websanova-logo-small-full-black.png diff --git a/static/js/wpaint/demo/img/youtube-icon.png b/static/js/wpaint/demo/img/youtube-icon.png Binary files differnew file mode 100644 index 0000000..e697406 --- /dev/null +++ b/static/js/wpaint/demo/img/youtube-icon.png 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 Binary files differnew file mode 100644 index 0000000..cda4bde --- /dev/null +++ b/static/js/wpaint/plugins/file/img/icons-menu-main-file.png 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 Binary files differnew file mode 100644 index 0000000..b6757ad --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-bucket.png diff --git a/static/js/wpaint/plugins/main/img/cursor-crosshair.png b/static/js/wpaint/plugins/main/img/cursor-crosshair.png Binary files differnew file mode 100644 index 0000000..362e069 --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-crosshair.png diff --git a/static/js/wpaint/plugins/main/img/cursor-dropper.png b/static/js/wpaint/plugins/main/img/cursor-dropper.png Binary files differnew file mode 100644 index 0000000..e8396d1 --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-dropper.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser1.png b/static/js/wpaint/plugins/main/img/cursor-eraser1.png Binary files differnew file mode 100644 index 0000000..1a25ec5 --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser1.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser10.png b/static/js/wpaint/plugins/main/img/cursor-eraser10.png Binary files differnew file mode 100644 index 0000000..5f5d83f --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser10.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser2.png b/static/js/wpaint/plugins/main/img/cursor-eraser2.png Binary files differnew file mode 100644 index 0000000..d15f875 --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser2.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser3.png b/static/js/wpaint/plugins/main/img/cursor-eraser3.png Binary files differnew file mode 100644 index 0000000..c81814d --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser3.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser4.png b/static/js/wpaint/plugins/main/img/cursor-eraser4.png Binary files differnew file mode 100644 index 0000000..c512bfc --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser4.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser5.png b/static/js/wpaint/plugins/main/img/cursor-eraser5.png Binary files differnew file mode 100644 index 0000000..fff0873 --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser5.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser6.png b/static/js/wpaint/plugins/main/img/cursor-eraser6.png Binary files differnew file mode 100644 index 0000000..d413f05 --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser6.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser7.png b/static/js/wpaint/plugins/main/img/cursor-eraser7.png Binary files differnew file mode 100644 index 0000000..52876a5 --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser7.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser8.png b/static/js/wpaint/plugins/main/img/cursor-eraser8.png Binary files differnew file mode 100644 index 0000000..6c1577b --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser8.png diff --git a/static/js/wpaint/plugins/main/img/cursor-eraser9.png b/static/js/wpaint/plugins/main/img/cursor-eraser9.png Binary files differnew file mode 100644 index 0000000..4441a3e --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-eraser9.png diff --git a/static/js/wpaint/plugins/main/img/cursor-pencil.png b/static/js/wpaint/plugins/main/img/cursor-pencil.png Binary files differnew file mode 100644 index 0000000..d54322d --- /dev/null +++ b/static/js/wpaint/plugins/main/img/cursor-pencil.png diff --git a/static/js/wpaint/plugins/main/img/icon-group-arrow.png b/static/js/wpaint/plugins/main/img/icon-group-arrow.png Binary files differnew file mode 100644 index 0000000..ff501ac --- /dev/null +++ b/static/js/wpaint/plugins/main/img/icon-group-arrow.png diff --git a/static/js/wpaint/plugins/main/img/icons-menu-main.png b/static/js/wpaint/plugins/main/img/icons-menu-main.png Binary files differnew file mode 100644 index 0000000..4b1a90b --- /dev/null +++ b/static/js/wpaint/plugins/main/img/icons-menu-main.png 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 Binary files differnew file mode 100644 index 0000000..b2cb874 --- /dev/null +++ b/static/js/wpaint/plugins/shapes/img/icons-menu-main-shapes.png 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 Binary files differnew file mode 100644 index 0000000..d7bed8c --- /dev/null +++ b/static/js/wpaint/plugins/text/img/icons-menu-text.png 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 Binary files differnew file mode 100644 index 0000000..a0c6511 --- /dev/null +++ b/static/js/wpaint/test/uploads/test1.png diff --git a/static/js/wpaint/test/uploads/test2.png b/static/js/wpaint/test/uploads/test2.png Binary files differnew file mode 100644 index 0000000..68c25e0 --- /dev/null +++ b/static/js/wpaint/test/uploads/test2.png diff --git a/static/js/wpaint/test/uploads/test3.png b/static/js/wpaint/test/uploads/test3.png Binary files differnew file mode 100644 index 0000000..c92d3cc --- /dev/null +++ b/static/js/wpaint/test/uploads/test3.png diff --git a/static/js/wpaint/test/uploads/wPaint.png b/static/js/wpaint/test/uploads/wPaint.png Binary files differnew file mode 100644 index 0000000..c19ab7f --- /dev/null +++ b/static/js/wpaint/test/uploads/wPaint.png 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 |