console
const bulb = document.getElementById("bulb");
const status = document.getElementById("status");
function StateMachine(config) {
const machine = { ...config };
if (!machine.initial) {
machine.initial = {};
}
if (!machine.initial.action) {
machine.initial.action = () => { }
}
machine.value = machine.initial.value;
machine.initial.action();
machine.states = machine.states || [];
machine.transfer = (curState = { value: "" }, event) => {
let nextState = curState;
for (let i = 0; i < machine.states.length; i++) {
if (machine.states[i].name === event && machine.states[i].from === curState.value) {
nextState.value = machine.states[i].to || "";
machine.value = nextState.value;
nextState.action = machine.states[i].action || function () { };
nextState.action();
break;
}
}
return nextState;
}
return machine;
}
function light() {
bulb.className = "light";
status.innerText = "on";
}
function dark() {
bulb.className = "dark";
status.innerText = "off";
}
const fsm = new StateMachine({
initial: {
value: "off",
action: function () {
bulb.className = "dark";
status.innerText = "off";
}
},
states: [
{ name: "turnOn", from: "off", to: "on", action: light },
{ name: "turnOff", from: "on", to: "off", action: dark },
]
});
const { initial } = fsm;
let curState = { ...initial };
function turnOnClick() {
curState = fsm.transfer(curState, "turnOn");
console.log(fsm.value);
}
function turnOffClick() {
curState = fsm.transfer(curState, "turnOff");
console.log(fsm.value);
}
<div id="bulb">
<div></div>
<div></div>
<div></div>
</div>
<br>
<button onclick="turnOnClick()">turnOn</button>
<button onclick="turnOffClick()">turnOff</button>
<div>status:
<span id="status"></span>
</div>
.dark>div:first-child, .light>div:first-child{
width: 50px;
height: 50px;
border-radius: 50%;
overflow: hidden;
background: #ccc;
}
.dark>div:nth-child(2), .light>div:nth-child(2){
width: 18px;
height: 30px;
border-radius: 50%;
margin-left: 15px;
margin-top: -18px;
background: #ccc;
}
.dark>div:nth-child(3), .light>div:nth-child(3){
width: 15px;
height: 15px;
border-radius: 50%;
margin-left: 16.5px;
margin-top: -10px;
background: #ccc;
}
.light>div:first-child, .light>div:nth-child(2){
background: #fbff03;
}
.light>div:nth-child(3){
background: #333;
}