/* * UI * functions, intialization */ // initialization of ui $(function() { // #alphabet $('#alphabet').html(ALPHABET.substr(0,ALPHABET.length-1)); // #regex $('#regex').change(function() { checkLength(this, "#parseButton"); }); $('#regex').keypress(function(event) { return getKey(event, ALPHABETS); }); $('#regex').mouseout(function() { checkLength(this, "#parseButton"); }); // #parseButton $('#parseButton').click(function() { uiParse(); alphabetEditable=false; }); // #word $('#word').change(function() { checkLength(this, "#checkButton"); }); $('#word').keypress(function(event) { return graphMoveByInput(event, ALPHABET); }); $('#word').mouseout(function() { checkLength(this, "#checkButton"); }); // #checkButton $('#checkButton').click(function() { uiSimulate(); }); // #graphit $('#graphit').change(function() { graphit = this.checked; }); // #reloadButton $('#reloadButton').click(function() { window.location.reload(); }); // #descButton $('#descButton').click(function() { $('#desc').toggle(); }); // in place edit of alphabet $('body').click(function() { if (alphabetEdit) { ALPHABET = $('#alphabetInput').attr('value').replace(/\s/g,'').replace(/%/g, '').replace(/\*/g, ''); ALPHABET = ALPHABET.replace(/\(/g, '').replace(/\)/g, '').replace(/\|/g, '')+STOPSYMBOL; ALPHABETS = ALPHABET+SPECIALS; $('#alphabetInput').remove(); $('#alphabet').html(''+ALPHABET.substr(0, ALPHABET.length-1)+''); alphabetEdit = false; } }); $('#alphabet').dblclick(function() { if (alphabetEditable) { alphabetEdit = true; $(this).html(''); $('#alphabetInput').click(function(event) { event.stopPropagation(); }); } }); // tooltips $('*.help').tooltip({showBody: " - "}); }); // Enable/disable if input length is > 0. function checkLength(el, bId) { if (graphit && (el.id == 'word')) return; if(el.value.length > 0) { enable(bId); } else { disable(bId); }; }; // Enable/disable a enabled/disabled form item. function enable(id) { $(id).removeAttr("disabled"); }; function disable(id) { $(id).attr("disabled","disabled"); }; // UI messages. function graph_inprogress() { $('#checkMessage').html('...'); $('#checkMessage').removeClass('success'); $('#checkMessage').removeClass('failure'); $('#word').removeClass('success'); $('#word').removeClass('failure'); $('#word').addClass('inprogress'); window.g.mover.attr({fill: 'yellow'});//'#ffff88'}); }; function graph_success() { $('#checkMessage').html('Word accepted'); $('#checkMessage').removeClass('failure'); $('#checkMessage').addClass('success'); $('#word').removeClass('failure'); $('#word').removeClass('inprogress'); $('#word').addClass('success'); $('#checkMessage').effect("highlight", {}, 1000); if(graphit) { window.g.mover.attr({fill: 'green'});//'#cdeb8b'}); } }; function graph_failure() { $('#checkMessage').html('Word not accepted'); $('#checkMessage').removeClass('success'); $('#checkMessage').addClass('failure'); $('#word').removeClass('success'); $('#word').removeClass('inprogress'); $('#word').addClass('failure'); $('#checkMessage').effect("highlight", {}, 1000); window.g.mover.animate({fill: 'red'});//'#b02b2c'}, 250); }; // Call of RegexParser.parse() from UI. function uiParse() { var regex = $('#regex').attr('value'); if (regex.match(/\*(\(|\))*\*/)) { alert("Supernumerous * symbol(s), please correct regular expression."); return; } disable('#graphit'); var parser = new RegexParser(); nfa = parser.parse($('#regex').attr('value')); $('#parseMessage').html('Parse: '+parser.getErrorMessage()); if (parser.getErrorMessage() != 'Ok') { $('#parseMessage').removeClass('success'); $('#parseMessage').addClass('failure'); $('#regex').addClass('failure'); } else { $('#parseMessage').removeClass('failure'); $('#regex').removeClass('failure'); $('#parseMessage').addClass('success'); $('#regex').addClass('success'); enable('#word'); var dfa = new Nfa2Dfa(nfa); var ttable = dfa.convert(); disable('#regex'); disable('#parseButton'); if(!graphit) return; window.g = graph(); disable('#checkButton'); }; $('#parseMessage').effect("highlight", {}, 1000); // preparing graph movements window.gCurrentState = g.nodes[0]; window.gPrevStates = []; gPrevStates.push(gCurrentState); window.inSameState = []; window.failedInputs = []; window.gPrevState = gCurrentState; g.mover = g.paper.circle( gCurrentState.node[1][0].cx.baseVal.value, gCurrentState.node[1][0].cy.baseVal.value, 30 ).attr({fill:'#ffff88', stroke: '#ccc', 'stroke-width': 4, opacity: 0.5}); graph_inprogress(); }; // Call of NfaSimulator.simulate() from UI. function uiSimulate() { var simulator = new NfaSimulator(nfa); var check = simulator.simulate($('#word').attr('value')); if (!check) { graph_failure(); } else { graph_success(); }; }; // Filter input. function getKey(e, set) { var key = String.fromCharCode(e.which); if (e.which == 13) return true; if (set.indexOf(key) >= 0 || e.which == 8) { return true; }; return false; }; // Moving inside the graph by input symbols. function graphMoveByInput(e) { if (lock) { if (failedInputs) { lock = false; } else { //var w = $('#word').attr('value'); //$('#word').attr('value', w.substr(0, w.length-1)); lock = false; return false; } } else { lock = true; } // no graph if(!graphit) return; // we are at the beginning if (!gCurrentState || !gPrevState) { gPrevStates.push(g.nodes[0]); gPrevState = g.nodes[0]; gCurrentState = g.nodes[0]; }; // backspace if (e.which == 8) { // step over failed inputs. if (window.failedInputs.length > 0) { if(window.failedInputs.length == 1) { if (ttable[gCurrentState.name].isFinal) { graph_success(); } else { graph_inprogress(); }; }; window.failedInputs.pop(); return; } // no state change if (window.inSameState.length > 0) { var mx = g.mover.attr('cx'); var my = g.mover.attr('cy'); var ll = g.paper.path('M'+mx+','+my+' '+mx+','+(my-25)+'Z').attr({stroke: 0}); window.setTimeout(function() { g.mover.animateAlong(ll, 250, "bounce"); }, 250); window.inSameState.pop(); if (ttable[window.gCurrentState.name].isFinal) { graph_success(); } else { graph_inprogress(); } return; } // go back one state window.gPrevState = gPrevStates.pop(); if (!window.gPrevState) return; // none of word left window.setTimeout(function() { if (!window.gPrevState) return; // none of word left g.mover.animate({cx:gPrevState.node[1][0].cx.baseVal.value, cy:gPrevState.node[1][0].cy.baseVal.value}, 250); lock = false; }, 250); window.gCurrentState = gPrevState; if (ttable[window.gCurrentState.name].isFinal) { graph_success(); } else { graph_inprogress(); }; return; }; // getting input var key = String.fromCharCode(e.which); var gNextState = g.graphNodeByName[window.ttable[window.gCurrentState.name][key]]; graph_inprogress(); // --> failure if (!gNextState) { window.failedInputs.push(true); graph_failure(); return; }; // no state change if(gNextState.name == gCurrentState.name) { window.setTimeout(function() { g.mover.animateAlong(gCurrentState.node[4], 350);lock = false; }, 125); window.inSameState.push(true); if (ttable[window.gCurrentState.name].isFinal) { graph_success(); } else { graph_inprogress(); }; return; } else { // state change var theConn; for (var c in g.connections) { if ((window.gCurrentState.name == g.connections[c].name1) && (gNextState.name == g.connections[c].name2)) { theConn = g.connections[c]; break; }; }; var x = gCurrentState.node[1][0].cx.baseVal.value; var y = gCurrentState.node[1][0].cy.baseVal.value; line = g.paper.path( 'M'+x+gCurrentState.node[1][0].r.baseVal.value+','+y+' '+theConn.line.attr('path').toString().substring(1) +'L'+(gNextState.node[1][0].cx.baseVal.value)+','+gNextState.node[1][0].cy.baseVal.value ).attr({stroke:'none'}); (function(g, line) { setTimeout(function() { g.mover.animateAlong(line, 250); lock = false; return line; }, 250); })(g, line); }; window.gPrevStates.push(gCurrentState); window.gPrevState = gCurrentState; window.gCurrentState = gNextState; if (ttable[window.gCurrentState.name].isFinal) { graph_success(); }; };