KeithCraigo.com My site about RIA development

27Oct/080

Spry, Javascript and Perl

Recently I developed an application using the following

  • Adobe's Spry technology to retrieve the data from an xml file
  • javascript to manage the data
  • perl script to process the data

Why didn't I just build the whole darn thing in Perl, PHP, ASP or some other programming language that could take care of it by itself.
In short these technologies were not available when I was given the project.

I know! hard to believe that in this day and age that a modern company would not make these technologies available, there are a whole bunch of reasons why, IP restrictions, budget constraints, lack of manpower due to restructuring, but a lot of times it's to restrict the amount of one off applications from being built, it's far better to standardize because when the person who developed the application is no longer available and something goes wrong, who are you going to call for support?

But one off's are necessary sometimes and I was looking for a reason to try out the Spry library anyways and this was the perfect opportunity. So what I did was design the web interface to be able to use any technology on the backend whether it be perl, php, java, c#, asp whatever, all I had to do was change one line and I'm done.

As with anything in life theres' always more than one way to get something done, this is just the way that I used.

My form is just a list of xml values retrieved by a Spry XMLDataSet, each row of data contains a checkbox that when clicked will remove a value from an array, when unchecked it will put the data back in the array, the array is what gets passed to the backend script.

Here's the structure of the xml file: myBooks.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<books>
<book>
<title>Book 1</title>
<isbn>12345-98765</isbn>
<auth>whoever</auth>
</book>
<book>
<title>Book 2</title>
<isbn>98765-12345</isbn>
<auth>whoevers brother</auth>
</book>
<book>
<title>Book 3</title>
<isbn>9876578654</isbn>
<auth>whoevers other brother</auth>
</book>

</books>

Now in reality if your books are technical books there will more than likely be more than one author and in that case you may want to use the Master/Detail approach but I chose to keep things simple for now, since this post is about passing javascript values to a backend script mixed with a little instruction on how to use Spry.

<!-- don't forget to include the Spry Library //-->

<script type="text/javascript" src="js/spry/xpath.js"></script>
<script type="text/javascript" src="js/spry/SpryData.js"></script>

<script type="text/javascript">
<!--
<!-- Main Menu //-->
var ds1 = new Spry.Data.XMLDataSet("data/myBooks.xml", "books/book");

var myBooks = new Array();

//I found the Array.prototype.findIndex on http://www.guyfromchennai.com/?m=200602
//Use prototype to add functionality to the native Array object.

Array.prototype.findIndex = function(value){
// alert("Value: " + value);

var notFound ="";
for(var i=0;i<this.length;i++){
// alert("Compare: " + value +"----"+this[i]);
if(this[i]==value)
{
return i;
}
}
return notFound;
};

// For this to work properly we need to populate the myBooks array with all the isbns'

function init(notificationType, notifier, data)
{
if(notificationType != "onPostLoad"){return;}
var data = ds1.getData();
// Get all rows
//alert("Init: " + data[0]["isbn"]
for(var i=0;i< data.length;i++){

myBooks[i]=data[i]["isbn"];
}

}
ds1.addObserver(init);

//Here's the function to insert and extract data from the array:

function manageData(ctrl, book_isbn){
//alert("Book: " + book_isbn);
//check the state of the checkbox

if (ctrl.checked){

// were removing
//alert("Deleting: " + book_isbn);
idx = myBooks.findIndex(book_isbn);
myBooks.splice(idx,1);

} else {

// must be a new book, were adding
//alert("Adding: " + book_isbn);
myBooks.push(book_isbn);
}

// reset for good measure

idx='';
book_isbn='';

}

// This gets called by a button being clicked on my form.

function giveMeTheGoods(){
// We could send with get through the Querystring
//but eventually we will run into the character limitation of the Querstring.
//so I chose to use the post method.

//alert("Sending: " + myBooks);
document.mySelections.method='post';
// plugin your processing script here
document.mySelections.action='/cgi-bin/processMyBooks.cgi';
document.mySelections.dstransfer.value=myBooks;
document.mySelections.submit();

}

</script>

<!-- setup the form //-->
<form name="mySelections" id="mySelections">

<table name="mySelections_table">

<tr spry:region="ds1" spry:setrow="ds1">

<th>Delete</th>
<th>Title</th>
<th>ISBN</th>
<th>Author</th>
</tr>
<tr>
<td><input type="checkbox" name="isbn" value="{isbn}" onClick=" manageData(this, '{isbn}');" /></td>
<td>{title}</td>
<td>{isbn}</td>
<td>{auth}</td>
</tr>
</table>

<input type="hidden" name="dstransfer"/>

<input type='button" value="Process" onClick="giveMeTheGoods();"/>
</form>

Here's the output:

jstoperlform-300x103


Ok, you can read the code to find out how this works and I've sprinkled some alert boxes through out the code to show what is happening during execution, just uncomment, but basically here's what happens,

  1. When the user selects the check box the isbn is removed from the myBooks array, that was initially populated inside the Spry.XMLDataSet observer "init".
  2. When the user deselects the check box the isbn is added back to the myBooks array.
  3. When the user clicks the Process button the function givMeTheGoods() is called and this is where we populate the hidden input field dstransfer and pass it to our perl script or whatever language you prefer. I'll leave the script up to you.

Hope this is helpful

- Keith

P.S. For large datasets you may want to find an alternative method for loading the data, such as only retrieving a limited number of records from a database at a time. The application I modeled this tutorial after presently retrieves over 7000 records and is quite slow in loading, but once loaded the lag time is not that bad. I don't have access to any other data storage methods such as a database so this is how it has to be for now.

For the time when you are not available because you've moved on to something bigger and better, PLEASE! document your code for developers and leave detailed instructions in easy to understand language for your end user about your application. Most of your users will never ever look at the code, the statement that the code is self documenting is not going to cut it!


Creative Commons License

Comments (0) Trackbacks (0)

No comments yet.


Leave a comment


No trackbacks yet.