var logger; $(document).ready(function(){ var lock = false; var nihon_text; var nihon_title; var mousedown = false; var state; var uncheck_after_capture = true; var canvas_agreement = false; //// init logger logger = new Logger; //// START DRAWING on segment $(".segment").mousedown(function(event){ if(lock) return; switch(event.which){ case 1: state = segment_toggle($(this)); break; case 3: state = segment_toggle($(this), 0); break; default: return; } mousedown = true; return false; }); //// START DRAWING on box or between $(".vertex, #box").mousedown(function(event){ if(lock) return; switch(event.which){ case 1: state = 1; break; case 3: state = 0; break; default: return; } mousedown = true; return false; }); //// DRAWING by dragging $(".segment").mouseover(function(){ if(lock || !mousedown) return; segment_toggle($(this), state); return false; }); //// STOP DRAWING $("body").mouseup(function(){ if( !mousedown ) return; mousedown = false; logger.dump(); return false; }); //// context menu appearing while drawing fix $(document).on("contextmenu", ".segment, .vertex, #box", function(e){ return lock; }); //// HIDE LINES SWITCH $("#hide_lines").change(function(){ if($(this).is(":checked")){ $(".segment").css("visibility","hidden").css("cursor","default"); $(".v_pass").css("visibility","hidden"); $(".h_pass").css("visibility","hidden"); $(".vertex.zero").css("visibility","hidden"); lock = true; }else{ $(".segment").css("visibility","visible").css("cursor","pointer"); $(".v_pass").css("visibility","visible"); $(".h_pass").css("visibility","visible"); $(".vertex.zero").css("visibility","visible"); lock = false; } }); //// NIHONGO NO TEKISUTO $("#nihon").mouseover(function(){ if( !nihon_text ){ nihon_text = $(this).text(); nihon_title = $(this).attr("title") $(this).css("width", $(this).width()+"px"); //.css("height", $(this).height()+"px"); // fix width and height } $(this).text(nihon_title).attr("title", "").addClass("nihonlatin"); }); $("#nihon").mouseout(function(){ $(this).text(nihon_text).attr("title", nihon_title).removeClass("nihonlatin"); }); //// SAVING IMAGE (canvas method) $("#to_canvas").click(function(){ if(canvas_agreement || window.confirm("Save as PNG image.\nThis is experimental! The final image can be different and not very beautiful. For best results, use Google Chrome browser.\nDon't forget to rename file to something.png\n\nDo You wish to continue?")){ canvas_agreement = true; }else return; if( !$("#hide_lines").is(":checked") ) uncheck_after_capture = true; else uncheck_after_capture = false; $("#hide_lines").prop('checked', true).trigger("change"); html2canvas($("#box"),{ onrendered: function(canvas){ if(uncheck_after_capture) $("#hide_lines").prop('checked', false).trigger("change"); var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); window.location.href=image; } }); }); }); function segment_toggle(e, to_state, notlog){ if( typeof notlog === "undefined" ) notlog = false; if( !e.length ) console.error("ELEMENT of SEGMENT to be toggled NOT FOUND"); // element test // get current value state = get_number_of_bridges(e); // compute new_state new_state = state+1; if(new_state > 2) new_state=0; if( typeof to_state !== "undefined" && to_state >= 0 && to_state <=2 ) new_state=to_state; // TOGGLE process (change CSS class) $("div", e).removeClass("s0 s1 s2"); $("div", e).addClass("s"+new_state); // get id's of touching vertexes var id_p = parse_id($(e).attr('id')); var r2=id_p[1]; var c2=id_p[2]; if(id_p[0]=="v") r2++; if(id_p[0]=="h") c2++; // update touching vertexes vertex_update(id_p[1], id_p[2]); vertex_update(r2, c2); // log the change and test for unwanted tresholding (and fix it) // // if logging wanted if there are at least 2 items in log // | logger.log process (returns true if logged new segment toggle) | if not ereasing by drawing // | | | | if( !notlog && logger.log($(e).attr('id'), state, new_state) && typeof logger.get(1) !== "undefined" && to_state !=0 ){ var p0 = parse_id(logger.get(0).id); var p1 = parse_id(logger.get(1).id); if( typeof logger.get(2) !== "undefined" ) var p2 = parse_id(logger.get(2).id); do{ //// testing last two (should be parallel, on the same Y, with distance |1|) if( p0[0] != p1[0] ) break; //different orientations if( p0[0] == "h" ){ var x=1; var y=2; }else{ var x=2; var y=1; } if( p0[y] != p1[y] ) break; //parallel, but not on the same Y if( Math.abs(p0[x]-p1[x]) != 1 ) break; //distance not |1| // FOUND PARALLEL var moveto_r = ( p0[x] > p1[x] ) ? p1[x] : p1[x]*1-1; var moveto_c = ( typeof p2 === "undefined" || p2[y] <= p1[y] ) ? p1[y] : p1[y]*1+1; if(p1[0] == "h"){ var moveto_dir = "v"; }else{ var moveto_dir = "h"; var h = moveto_r; moveto_r = moveto_c; moveto_c = h; } var moveto_id = moveto_dir+"s_r"+moveto_r+"c"+moveto_c; var oldValue = get_number_of_bridges($("#"+moveto_id)); //console.log("=== restoring ["+logger.get(1).id+"] to value "+logger.get(1).oldValue); segment_toggle($("#"+logger.get(1).id), logger.get(1).oldValue, true); // restore 1 //console.log("=== correcting ["+moveto_id+"] to value "+state); segment_toggle($("#"+moveto_id), to_state, true); // toggle corrected logger.update(1, moveto_id, oldValue, state); }while(false); } // return new value return new_state; } function vertex_update(r, c){ var id="r"+r+"c"+c; if($("#"+id).length){ $("#"+id).removeClass("v_pass h_pass zero"); $("#"+id+" div").removeClass("s0 s1 s2"); var n = get_number_of_bridges( $("#vs_r"+(r-1)+"c"+c) ); var e = get_number_of_bridges( $("#hs_r"+r+"c"+c) ); var s = get_number_of_bridges( $("#vs_r"+r+"c"+c) ); var w = get_number_of_bridges( $("#hs_r"+r+"c"+(c-1)) ); var sum = n+e+s+w; $("#"+id).html("
"+sum); if(n==0 && s==0 && e==w && e!=0){ $("#"+id).addClass("h_pass"); $("#"+id+" div").addClass("s"+e); } if(e==0 && w==0 && n==s && n!=0){ $("#"+id).addClass("v_pass"); $("#"+id+" div").addClass("s"+n); } if(sum == 0) $("#"+id).addClass("zero"); } } function get_number_of_bridges(e){ var ret=0; if( e.length && $("div", e).hasClass("s1") ) var ret=1; if( e.length && $("div", e).hasClass("s2") ) var ret=2; return ret; } function parse_id(id){ if( typeof id === "undefined" ) console.error("PARSE_ID undefined ID"); var p = id.match(/(([vh])s_)?r(\d+)c(\d+)/i); return [p[2], parseInt(p[3]), parseInt(p[4])]; } /************* LOGGER **************/ var Logger = function(){ this.logs = []; }; Logger.prototype = { log: function(id, oldValue, newValue){ if( typeof this.logs[0] !== "undefined" && this.logs[0].id == id ) return false; this.logs.unshift(new LoggerRecord(id, oldValue, newValue) ); while( this.logs.length > 3 ) this.logs.pop(); /*for(a=0; a<=3; a++){ if( typeof this.logs[a] != "undefined" ){ $("#id_"+a).html(this.logs[a].id); $("#old_"+a).html(this.logs[a].oldValue); $("#new_"+a).html(this.logs[a].newValue); }else{ $("#id_"+a).html("—"); $("#old_"+a).html("—"); $("#new_"+a).html("—"); } }*/ return true; }, update: function(position, id, oldValue, newValue){ this.logs[position] = new LoggerRecord(id, oldValue, newValue); }, dump: function(){ this.logs.length = 0; }, get: function(number){ if(number < 0 || number > 2) return null; return this.logs[number]; }, } var LoggerRecord = function(id, oldValue, newValue){ this.id = id; this.oldValue = oldValue; this.newValue = newValue; }