<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>iFSM in action! a simple calculator managed with a FSM</title>
<script type="text/javascript" src="../extlib/jquery.min.js"></script>
<script type="text/javascript" src="../extlib/jquery.dotimeout.js"></script>
<script type="text/javascript" src="../extlib/jquery.attrchange.js"></script>
<script type="text/javascript" src="../iFSM.js"></script>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<style type="text/css">
html {
font-family: Helvetica, Arial, sans-serif;
}
body {
padding: 0 20px;
}
button {
margin: 2px 2px;
font-size: 20px;
border: 1px solid #333;
width: 70px;
text-shadow: 0 -1px 0 #333;
border-radius: 5px;
}
button.on {
color: #dfd;
background: #00aa00;
background: -moz-linear-gradient(top, rgba(0, 153, 0, 1) 0%,
rgba(0, 119, 0, 1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(0,
153, 0, 1)), color-stop(100%, rgba(0, 119, 0, 1)));
background: -webkit-linear-gradient(top, rgba(0, 153, 0, 1) 0%,
rgba(0, 119, 0, 1) 100%);
background: -o-linear-gradient(top, rgba(0, 153, 0, 1) 0%,
rgba(0, 119, 0, 1) 100%);
background: -ms-linear-gradient(top, rgba(0, 153, 0, 1) 0%,
rgba(0, 119, 0, 1) 100%);
background: linear-gradient(top, rgba(0, 153, 0, 1) 0%,
rgba(0, 119, 0, 1) 100%);
}
button.off {
color: #fdd;
background: #CC0000;
background: -moz-linear-gradient(top, rgba(204, 0, 0, 1) 0%,
rgba(153, 0, 0, 1) 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(204,
0, 0, 1)), color-stop(100%, rgba(153, 0, 0, 1)));
background: -webkit-linear-gradient(top, rgba(204, 0, 0, 1) 0%,
rgba(153, 0, 0, 1) 100%);
background: -o-linear-gradient(top, rgba(204, 0, 0, 1) 0%,
rgba(153, 0, 0, 1) 100%);
background: -ms-linear-gradient(top, rgba(204, 0, 0, 1) 0%,
rgba(153, 0, 0, 1) 100%);
background: linear-gradient(top, rgba(204, 0, 0, 1) 0%,
rgba(153, 0, 0, 1) 100%);
}
#result {
background-color: #5BB75B;
background-image: linear-gradient(to bottom, #62C462, #51A351);
background-repeat: repeat-x;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
color: #FFFFFF;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
font-size: 20px;
line-height: 25px;
padding: 2px 6px;
width: 200px;
}
</style>
<script type="text/javascript" id="iFSMscript">
var PC_OnBehaviour = {
Operand1 : {
enterState : {
init_function : function() {
this.opts.operand1 = '';
},
},
setOperand : {
next_state : 'Operand1Filled',
propagate_event : true,
},
setCommaOperand : {
next_state : 'Operand1WithCommaFilled',
propagate_event : 'setOperand',
},
setOperator : {
init_function : function() {
this.opts.operand1 = this.opts.result
},
next_state : 'Operator',
propagate_event : true,
},
},
Operand1Filled : {
setOperand : {
init_function : function(p, e, operand) {
this.opts.operand1 = this.opts.operand1 + operand;
this.myUIObject
.trigger('displayResult', this.opts.operand1);
},
},
setCommaOperand : {
init_function : function(p, e, operand) {
this.opts.operand1 = this.opts.operand1 + operand;
this.myUIObject
.trigger('displayResult', this.opts.operand1);
},
next_state : 'Operand1WithCommaFilled',
},
setOperator : {
next_state : 'Operator',
propagate_event : true,
},
},
Operand1WithCommaFilled : {
setOperand : {
init_function : function(p, e, operand) {
this.opts.operand1 = this.opts.operand1 + operand;
this.myUIObject
.trigger('displayResult', this.opts.operand1);
},
},
setOperator : {
next_state : 'Operator',
propagate_event : true,
},
},
Operator : {
setOperator : {
init_function : function(p, e, operator) {
this.opts.operator = operator;
},
next_state : 'Operand2',
next_state_when : "this.opts.operator != '='",
},
setOperand : {
next_state : 'Operand1',
propagate_event : true,
},
},
Operand2 : {
enterState : {
init_function : function() {
this.opts.operand2 = '';
},
},
setCommaOperand : {
next_state : 'Operand2WithCommaFilled',
propagate_event : 'setOperand',
},
setOperand : {
next_state : 'Operand2Filled',
propagate_event : true,
},
},
Operand2Filled : {
setOperand : {
init_function : function(p, e, operand) {
this.opts.operand2 = this.opts.operand2 + operand;
this.myUIObject
.trigger('displayResult', this.opts.operand2);
},
},
setCommaOperand : {
init_function : function(p, e, operand) {
this.opts.operand2 = this.opts.operand2 + operand;
this.myUIObject
.trigger('displayResult', this.opts.operand2);
},
next_state : 'Operand2WithCommaFilled',
},
setOperator : {
next_state : 'Result',
propagate_event : true,
},
},
Operand2WithCommaFilled : {
setOperand : {
init_function : function(p, e, operand) {
this.opts.operand2 = this.opts.operand2 + operand;
this.myUIObject
.trigger('displayResult', this.opts.operand2);
},
},
setOperator : {
next_state : 'Result',
propagate_event : true,
},
},
Result : {
setOperator : {
init_function : function(p, e, operator) {
this.opts.result = eval(this.opts.operand1
+ this.opts.operator + this.opts.operand2);
this.myUIObject.trigger('displayResult', this.opts.result);
this.opts.operator = operator;
},
next_state : 'ResultDone'
},
},
ResultDone : {
enterState : {
next_state : 'Operand1',
next_state_when : "this.opts.operator == '='",
},
setOperand : {
init_function : function() {
this.opts.operand1 = this.opts.result
},
next_state : 'Operand2',
propagate_event : true,
},
setCommaOperand : 'setOperand',
},
DefaultState : {
start : {
propagate_event : 'seton',
},
displayResult : {
init_function : function(p, e, message) {
this.myUIObject.html(message);
},
},
seton : {
init_function : function() {
this.opts.result = '0';
this.myUIObject.trigger('displayResult', '0');
},
prevent_bubble : true,
next_state : 'Operand1',
},
}
};
var PocketCalculator = {
On : {
enterState : {
init_function : function() {
this.myUIObject.html('computer on');
},
propagate_event : 'seton',
},
delegate_machines : {
delegate_machine_1 : {
submachine : PC_OnBehaviour
},
},
setoff : {
next_state : 'Off'
}
},
Off : {
enterState : {
init_function : function() {
this.myUIObject.html('computer off');
},
},
seton : {
next_state : 'On',
},
},
DefaultState : {
start : {
next_state : 'Off',
},
}
};
var ActionButton = {
DefaultState : {
click : {
init_function : function() {
this.opts.sendto.trigger(this.myUIObject
.attr('data-action'));
},
}
}
};
var OperandButton = {
DefaultState : {
click : {
init_function : function() {
this.opts.sendto.trigger('setOperand', this.myUIObject
.html());
},
}
}
};
var OperandCommaButton = {
DefaultState : {
click : {
init_function : function() {
this.opts.sendto.trigger('setCommaOperand', this.myUIObject
.html());
},
}
}
};
var OperatorButton = {
DefaultState : {
click : {
init_function : function() {
this.opts.sendto.trigger('setOperator', this.myUIObject
.html());
},
}
}
};
$(document).ready(function() {
$("#result").iFSM(PocketCalculator);
$("#controlsbuttons > button").iFSM(ActionButton, {
sendto : $("#result")
});
$("#operandbuttons > button").iFSM(OperandButton, {
sendto : $("#result")
});
$("#operandcommabutton > button").iFSM(OperandCommaButton, {
sendto : $("#result")
});
$("#operatorbuttons > button").iFSM(OperatorButton, {
sendto : $("#result")
});
});
</script>
</head>
<body style="margin: 100px;">
<p>
Example inspired from <a
href="http://en.wikipedia.org/wiki/UML_state_machine">http://en.wikipedia.org/wiki/UML_state_machine</a>
</p>
<p>Click on the "On/C" button, then you can do some simple
calculations...</p>
<section id="infobox">
<h2>Result</h2>
<div id="result"></div>
</section>
<section id="controlsbuttons">
<h2>Controls</h2>
<button class="onoff on" id="ONC" data-action="seton">On/C</button>
<button class="onoff on" id="off" data-action="setoff">Off</button>
</section>
<section id="operandbuttons">
<h2>Keyboard</h2>
<button class="onoff on" id="k7">7</button>
<button class="onoff on" id="k8">8</button>
<button class="onoff on" id="k9">9</button>
<br>
<button class="onoff on" id="k4">4</button>
<button class="onoff on" id="k5">5</button>
<button class="onoff on" id="k6">6</button>
<br>
<button class="onoff on" id="k1">1</button>
<button class="onoff on" id="k2">2</button>
<button class="onoff on" id="k3">3</button>
<br>
<button class="onoff on" id="k0">0</button>
</section>
<section id="operandcommabutton">
<button class="onoff on" id="kcomma">.</button>
</section>
<section id="operatorbuttons">
<h2>Operators</h2>
<button class="onoff on" id="kplus">+</button>
<button class="onoff on" id="kminus">-</button>
<button class="onoff on" id="kdivied">/</button>
<button class="onoff on" id="kmultiply">*</button>
<br>
<button class="onoff on" id="kequal">=</button>
</section>
<pre>
<br><br>
<script>
function escapeHtml(text) {
var map = {
'&' : '&',
'<': '<',
'>' : '>',
'"' : '"',
"'" : '''
};
return text.replace(/[&<>"']/g, function(m) {
return map[m];
});
}
document.write(escapeHtml($('#iFSMscript').html()));
</script>
</pre>
<p>
provided by <a href="http://www.intersel.fr">Intersel</a>
</p>
</body>
</html>
|