Today I am presenting a (yet) small but usefull framework to use in ajax clients that I build and use …
What is Maquina?
Maquina is a petri net runtime implementation for Javascript and other languages like AS3 and java (work in progress).
Why do I need a state machine ?
Finite state machines have long been used as an organizing principle for designing and implementing complex behavior in event-driven programs, such as network adapters and compilers. Now, programmable Web browsers have opened a new event-driven environment to a new generation of applications. Browser-based applications, popularized by Ajax, are becoming more complex. Designers and implementers can benefit from the discipline and structure that finite state machines offer. In this article, you, learn how to use a finite state machine to design complex behavior for a simple Web widget — an animated tooltip that fades into and out of view. (read more = http://www.ibm.com/developerworks/library/wa-finitemach1/ ).
How it Works…
This plugin controls the lifecycle of an input form. To implement it, the changes described below, should be done in the existing application.
1 - Add Scripting libraries…
<!– Maquina Core –>
<script type=”text/javascript” src=”../../maquina.js”></script>
<script type=”text/javascript” src=”../../plugins/form/plugin.js”></script>
<!– this example uses prototype lib –>
<script type=”text/javascript” src=”http://www.prototypejs.org/assets/2008/1/25/prototype-.6.0.2.js”></script>
(*) yes, we use prototype.
2 - Create a form in HTML …
<div class=”widget_form”>
<div id=”form1_flash_state” ></div>
<form id=’form1_form’ name=’form1_form’ >
<h3>Maquina Form Test</h3>
<div id=”form1_widget_message_top” class=”widget_message”></div>
<label for=”fullname”>FullName</label>
<input type=”text” name=”fullname” id=”fullname”
onkeyup=”maquina.plugins.form.handleFormEvent(’form1′,’change’)”/>
<br /><br />
<label for=”Description”>Description</label>
<input type=”text” name=”description” id=”description”
oneyup=”maquina.plugins.form.handleFormEvent(’form1′,’change’)”/>
<br /><br />
<label for=”Age”>Age</label>
<select name=”age”
onchange=“maquina.plugins.form.handleFormEvent(’form1′,’change’)” >
<option value=”20-30″>20-30</option>
<option value=”30-40″>30-40</option>
</select>
<br /><br />
<div id=”form1_widget_message_footer” class=”widget_message”></div>
<br />
<div id=”form1_widget_button_bar” class=”widget_button_bar”></div>
</form>
</div>
(*) The tags with “class=widget_message” show validation and app messages.
(**) Note that there is no button bar in the form neither action property in the form tag. Everything is going to be managed by the plugin.
(***) Note in bold are the triggers to the dirty state. Include this on every single input element that is going to trigger a change of state.
3 - Initialize the form….
<script type=”text/javascript”>
var base_url = “http://localhost/maquina/ports/javascript/1.0/src/trunk/examples”;
/* Initialize
* execute this function when ever you want to inititalize the state machine
**/
function initialize()
{
try {
//(Optional) Just a loggin function included in maquina
consolelog(”initialize form1″);
//This is to insert the button bar in the placeholder
maquina.plugins.form.renderFormCommandBar(”form1″);
//Create a context (model) that the state machine is going to use.
var context1 = [];
context1["graph"] = new maquina.plugins.form.graph(); //this is the default behaviour
context1["ajax"] = [];
context1.ajax["url"] = “form_plugin_backend.php”; //Put here the action url
maquina.createStateMachine(”form1″, context1);
} catch(e) {
console.error(”Error at initialize! : ” + e.message);
}
}
//Trigger this on page Load
window.onload = function() {
consolelog(”initialize()”);
initialize();
}
</script>
4 - (Oprtional) you can use your own validation function in javascript…
function validate_miform(context){
var form = context["elements"]["form"];
// You can retrieve any value stored in the context.
ar projID = context["projID"];
var divID = context["divID"];
var err = new Array();
err['haserrors'] = false;
if(ifEmpty($(’notes_0′).value))
{
//Append your error message to the correct tag (see error model below)
err['top'] = ‘You must type a Note to Save Overall Status ‘;
err['haserrors'] = true;
}
if(ifEmpty($(’status_0′).value))
{
err['footer'] = “You must assign an Overall Status to save Overall Status Notes”;
err['haserrors'] = true;
}
if (err['haserrors'] == true){
err['result'] = ‘failure’;
} else {
err['result'] = ’success’;
}
return err;
}
(*) You can customize also the type of message displayed on each place. By adding prefixes ( “error:” , “alert:” or nothing “” ) you can change the images associated to the error message.
Error (Inform) model …
(**) This model should be created in the validation function. Also in this function you can choose where to display the messages.
Important: to execute this function before submitting the data you just need to do this on step 3…
context[“validation”] = validate_miform;
5 - What to do at the server side… (in php)
function server_side_processs_XXXXX($div,$projID)
{
[..]
//Example - Form Submit Response
$result['flag'] = ’success’;
$result['widget_message'] = ‘Settings Succesfully saved’;
$result['errors']['top'] = ”;
$result['errors']['footer'] = ‘Changes succesfully saved!’;
echo json_encode($result) ;
}
(*) You just need to build a custom message in an array with the format descripbed above. ‘widget_message’ = messages are going to be displayed in the button bar. Top and footer in the divs with those names.
The message that should be json encoded so don’t forget. ho add this (again in php)…
header(’Content-type: application/json’);
(**) flags :
Result: the word “success” or “failure”
Message: any message to be displayed. You can embed html here.
Conclusions…
This is the first thing tutorial I create for this framework , I will be upgrading it and uploading new stuff about this…
by Leandro Milmanda Perez