PDA

View Full Version : code trouble


usa_hodson
03-20-2005, 08:56 PM
I just can't find the problem in this code. The button is released and the onRelease function is called (see comments). Then this same onRelease function calls from within it a function within a php file for login purposes - this works and the result handler has the data returned to it. Within this result handler the doneworksheet1 function is called (this function resides in a different php file which I have tested and works). The function is successfully called, but nothing is returned to the appropriate result handler (none of the trace statements are executed.

The function should return one record from the database (the SQL statements and PHP is fine), but it doesn't, and I've been puzzled by it for several hours.



//Variable declaration
v_worksheet1 = "";


//done worksheet1 is called from within the 'validate_login_student_Result function
//Create a result handler for 'doneworksheet1()'
function doneworksheet1_Result(rsData){
trace("Got result \""+rsData+"\" of type "+typeof (rsData));
trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){
trace("Worksheet done!");
v_worksheet1 = "done";
} else {
trace("Worksheet not done!");
v_worksheet1 = "go";
}
}



//Create a result handler for student login validation
function validate_login_student_Result(rsData){
//trace(rsData); //Checks we have a result when testing
if(rsData.length>0){
v_firstname = rsData.getItemAt(0).firstname;
v_score = rsData.getItemAt(0).score;
v_target = rsData.getItemAt(0).targetscore;
v_pcomplete = rsData.getItemAt(0).pcomplete;
v_group = rsData.getItemAt(0).group;
trace("The group: "+rsData.getItemAt(0).group);
//We call these remoting functions immediately to populate the doneworksheet variables
//thus making it simple to know when a worksheet has already been completed.
student.doneworksheet1(v_username);
trace("Made first call");
student.doneworksheet2(v_username);
trace("Made second call");
student.doneworksheet3(v_username);
trace("Made third call");
student.doneworksheet4(v_username);
trace("Made fourth call");
student.doneworksheet5(v_username);
trace("Made fifth call");
student.doneworksheet6(v_username);
trace("Made sixth call");
_root.gotoAndPlay(15);
} else {
login_error._alpha = 100;
login_verify._alpha = 0;
}
}


//These staements are within an onRelease function for a button on the main timeline
switch (v_account) {
case "student" :
login_verify._alpha = 100;
//Call the validation procedure and pass parameters:
login.validate_login_student(v_username, v_password, v_school);
break;
//Another case statement is here
}



Thankyou for your help in advance...

James.

subHero
03-20-2005, 09:03 PM
hmm, at first glance:
student.doneworksheet1(v_username);

where does v_username reside (scope)?

and do you really get a populated resultset for the login-call?

usa_hodson
03-20-2005, 09:13 PM
Thanks for the reply,

I hadn't included all of the code above that actually resides within the relevant frame. The v_username variable is declared prior to using it and the value within it is derived from the login function. Up to there everything works - in fact I'm not having any problems with the login procedure...

To get a better idea of what works so far:

http://www.getwithit.info/enterprise

school = Finham Park
username = andy
password = password
radiobutton = student

This project is part of a freeware attempt to build a financial management learning course for english schools.

Thank you for any more help that could be offered,

James.

subHero
03-20-2005, 09:31 PM
sorry for looking dumb, but:
which trace-actions dont execute? the ones in validate_login_student or in doneworksheet?

it is really difficult get a grip on the problem, since you are only posting snippets, so other questions pop up like:
do you use NetService (as1) or Service (as2) to do the remoting calls?
does this only occur in the ide-testexport or in flash-embedded html?
what does the netdebugger say (!) ?

basically: i don't see any flaws with the code you posted which leaves me under the impression that there must be another source for your problem.

but i still figure... ;)

usa_hodson
03-20-2005, 09:38 PM
Yeah, sorry for the confusion - I'll paste the whole deal to give a better idea of what is going on. All of this code is placed on frame 10 of the movie which contains the components for the login procedure - as can be seen by visiting the link given.

The trace actions which don't execute are those within doneworksheet1...


// ************************************************** ******************************
// Include files necessary for Remoting debugging and coding
// ************************************************** ******************************
#include "NetDebug.as"
#include "NetServices.as"

import mx.controls.Alert;

function doSomething(){}
MENU = new ContextMenu();
MENU.hideBuiltInItems();
Functioned = new ContextMenuItem("This movie is copyrighted by GetWithIt web services.", doSomething);
MENU.customItems.push(Functioned);
_root.menu = MENU;

// ************************************************** ******************************
// Remoting settings - allow connection to the php files and database
// ************************************************** ******************************
NetServices.setDefaultGatewayUrl("http://www.getwithit.info/enterprise/gateway.php");
conn = NetServices.createGatewayConnection("http://www.getwithit.info/enterprise/gateway.php");
login = conn.getService("login", this); //connects to the login php file
student = conn.getService("student", this); //connects to the student php file
teacher = conn.getService("teacher", this); //connects to the teacher php file

// ************************************************** ******************************
// Initial variables
// ************************************************** ******************************
v_firstname = ""; //stores the user's first name for display in program.
v_score = 0; //Holds the score for processing before putting to the database.
v_target = 0; //Holds the target score for the simulation to display in program.
v_pcomplete = 0; //Holds the percentage complete status of the course for display.
v_account = ""; //The type of user that is logged in - student or teacher.
v_username = ""; //The user's username is held to facilitate database calls.
v_password = ""; //The password is held to validate the login process.
v_school = ""; //The school name is held to restrict access to other school's records.
v_surname = ""; //There is currently no reason to store the surname - strictly for future expansion.
v_email = ""; //Teacher's email is held to send support emails without need to type own address.
v_group = ""; //Group is held to retrieve correct feedback and retrieve correct users for statistics.
v_worksheet1 = ""; //
v_worksheet2 = ""; //Worksheet variable stores whether a worksheet has been completed or not
v_worksheet3 = ""; //for a specific student during the worksheet pre-execute procedure
v_worksheet4 = ""; //which occurs on the click of one of the activity buttons.
v_worksheet5 = ""; //
v_worksheet6 = ""; //
v_wage = 0; //Used during the calculation and display of the wage in the simulation.
v_balance = 850; //
v_cheque_balance = 350; //Used in the initialisation of the simulation,
v_savings_balance = 500;//initial values are the same for everyone.
v_credit_balance = 0; //
v_page = 1; //Holds the page value for the current place in the simulation before passing to database.
v_tax_credit = 22; //
v_internet_refund = 15; //
v_dividends = 4; //These dictate the values paid into the accounts for each week of the
v_savings_interest = 1; //simulation. They are the same for everyone, therefore it makes more
v_birthday = 50; //sense in terms of the programs speed to have the values reside in
v_lottery = 15; //variables within the program, rather than in the database.
v_bonus = 20; //
v_chinterest = 1; //
v_bills1 = 0; //
v_bills2 = 0; //
v_usual1 = 0; //Hold the values to calculate what order bills are being paid in - therefore allowing
v_usual2 = 0; //the program to dynamically adjust the price of bills and expenses.
v_extras1 = 0; //
v_extras2 = 0; //
v_billtype = ""; // Holds the type of bill to be paid.
v_currentBill = 0; //Holds the identification number of the current bill for sending to the database.
bill_name_array = new Array(); //An array to hold the bill names for display in the simulation.
user_name_array = new Array(); //An array to hold usernames for display within the statistics area.
v_myStatus = 0; // Allows the getBill() function in student php to be used in two different ways.
v_paid = false; //Determiner for whether a bill has been paid in the simulation.
v_bankaccount = "cheque"; // The default bank account to pass to the database.
v_scoremax1 = 10; //
v_scoremax2 = 10; //Hold the max score value for the payments in section of the simualtion.
v_scoremax3 = 10; //
v_scoremax4 = 10; //
v_must_pay = new Array(); //An array to hold the bills that haven't been paid for the notices section.
v_switcher = 0; //Allows the Bill retrieving handlers to process more than one type of request.
v_preswitch = 0; //Adds an extra part to the getallbills functions under certain conditions.
v_bill = new Object(); //A custom object to hold details about a single bill.
myData = new Object(); //A custom object to hold details about bill consequences.
v_week = 0; //Holds the current week number for the simulation.
v_score_array = new Array(); //An array to contain a list of scores from the database.

//************************************************** *******************************
//Define results handlers
//************************************************** *******************************

//Create a result handler for 'doneworksheet1()'
function doneworksheet1_Result(rsData){
trace("Got result \""+rsData+"\" of type "+typeof (rsData));
trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){ //rsData is the number of rows from the MySQL query
trace("Worksheet done!");
v_worksheet1 = "done";
} else {
trace("Worksheet not done!");
v_worksheet1 = "go";
}
}

//Create a result handler for 'doneworksheet2()'
function doneworksheet2_Result(rsData){
//trace("Got result \""+rsData+"\" of type "+typeof (rsData));
//trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){ //rsData is the number of rows from the MySQL query
//trace("Worksheet done!");
v_worksheet2 = "done";
} else {
//trace("Worksheet not done!");
v_worksheet2 = "go";
}
}
//Create a result handler for 'doneworksheet3()'
function doneworksheet3_Result(rsData){
//trace("Got result \""+rsData+"\" of type "+typeof (rsData));
//trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){ //rsData is the number of rows from the MySQL query
//trace("Worksheet done!");
v_worksheet3 = "done";
} else {
//trace("Worksheet not done!");
v_worksheet3 = "go";
}
}
//Create a result handler for 'doneworksheet4()'
function doneworksheet4_Result(rsData){
//trace("Got result \""+rsData+"\" of type "+typeof (rsData));
//trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){ //rsData is the number of rows from the MySQL query
//trace("Worksheet done!");
v_worksheet4 = "done";
} else {
//trace("Worksheet not done!");
v_worksheet4 = "go";
}
}
//Create a result handler for 'doneworksheet5()'
function doneworksheet5_Result(rsData){
//trace("Got result \""+rsData+"\" of type "+typeof (rsData));
//trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){ //rsData is the number of rows from the MySQL query
//trace("Worksheet done!");
v_worksheet5 = "done";
} else {
//trace("Worksheet not done!");
v_worksheet5 = "go";
}
}
//Create a result handler for 'doneworksheet6()'
function doneworksheet6_Result(rsData){
//trace("Got result \""+rsData+"\" of type "+typeof (rsData));
//trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){ //rsData is the number of rows from the MySQL query
//trace("Worksheet done!");
v_worksheet6 = "done";
} else {
//trace("Worksheet not done!");
v_worksheet6 = "go";
}
}

//Create a result handler for student login validation
function validate_login_student_Result(rsData){
//trace(rsData); //Checks we have a result when testing
if(rsData.length>0){
v_firstname = rsData.getItemAt(0).firstname;
v_score = rsData.getItemAt(0).score;
v_target = rsData.getItemAt(0).targetscore;
v_pcomplete = rsData.getItemAt(0).pcomplete;
v_group = rsData.getItemAt(0).group;
trace("The group: "+rsData.getItemAt(0).group);
//We call these remoting functions immediately to populate the doneworksheet variables
//thus making it simple to know when a worksheet has already been completed.
student.doneworksheet1(v_username);
trace("Made first call");
student.doneworksheet2(v_username);
trace("Made second call");
student.doneworksheet3(v_username);
trace("Made third call");
student.doneworksheet4(v_username);
trace("Made fourth call");
student.doneworksheet5(v_username);
trace("Made fifth call");
student.doneworksheet6(v_username);
trace("Made sixth call");
_root.gotoAndPlay(15);
} else {
login_error._alpha = 100;
login_verify._alpha = 0;
}
}

//Create a result handler for teacher login validation
function validate_login_teacher_Result(rsData){
//trace(rsData); //Checks we have a result when testing
if(rsData.length>0){
v_firstname = rsData.getItemAt(0).firstname;
v_surname = rsData.getItemAt(0).surname;
v_email = rsData.getItemAt(0).email;
//trace("The firstname: "+rsData.getItemAt(0).firstname);
_root.gotoAndPlay(65);
} else {
login_error._alpha = 100;
login_verify._alpha = 0;
}
}

//define the result handler for 'getSchools'
getSchools_Result = function(rsData){
//trace(rsData) //tests for reply from php file
cant = rsData.length //number of data to insert
loginSchoolChooser.removeAll() //clear loading message
//Pass data to the combobox
for(var i=0; i<cant; i++){ //Loops through results
loginSchoolChooser.addItem(rsData.getItemAt(i).sna mes)
}
}
//Create a result handler for createbalance()
createbalance_Result = function(rsData){
if (rsData != "error") {
v_cheque_balance = simulation.cheque_balance_text1.text = 350;
v_savings_balance = simulation.savings_balance_text1.text = 500;
v_credit_balance = simulation.credit_balance_text1.text = 0;
v_balance = simulation.init_balance_text1.text = 850;
} else {
Alert.show("Unable to create a connection to the database", Alert.OK);
student.createbalance(v_username);
}
}

//************************************************** ***********************



//************************************************** *******************************
//Some functions
//************************************************** *******************************

function clearFields(){ //Clears the text fields in the user admin teacher section.
user_admin_mc.admin_username.text = "";
user_admin_mc.admin_password.text = "";
user_admin_mc.admin_firstname.text = "";
user_admin_mc.admin_surname.text = "";
user_admin_mc.admin_target_score.text = "";
}

function randRange(min:Number, max:Number):Number { //Calculates a random number
var randomNum:Number = Math.round(Math.random()*(max-min))+min; //within a set range
return randomNum; //and returns it to the variable 'randomNum'.
}

function donesim (){ //A function to direct student to the correct section of the simulation.
student.getpage(v_username); //Fetches the current page from the database
switch (rsData.getItemAt(0).page){ //Outlines a process for each page number.
case "1":
//Attempt to create a new entry for the user for the simulation - will not work
//if the user has already started.
student.createbalance(v_username, v_group);
_parent.simulation1.gotoAndStop(2);
break;
case "2":
_parent.simulation1.gotoAndStop(3);
break;
case "3":
_parent.simulation1.gotoAndStop(4);
break;
case "4": //The start of week 2 requires wage calculation and current balances.
_parent.simulation2.gotoAndStop(2);
student.getbalance(v_username);
simulation2.init_balance_text2.text = rsData.getItemAt(0).balance;
simulation2.cheque_balance_text2.text = rsData.getItemAt(0).balcheque;
simulation2.savings_balance_text2.text = rsData.getItemAt(0).balsavings;
simulation2.credit_balance_text2.text = rsData.getItemAt(0).balcredit;
break;
case "5": //The start of week 2 requires wage calculation and current balances.
_parent.simulation2.gotoAndStop(2);
student.getbalance(v_username);
simulation2.init_balance_text2.text = rsData.getItemAt(0).balance;
simulation2.cheque_balance_text2.text = rsData.getItemAt(0).balcheque;
simulation2.savings_balance_text2.text = rsData.getItemAt(0).balsavings;
simulation2.credit_balance_text2.text = rsData.getItemAt(0).balcredit;
break;
case "6": //Page 6 requires the consequences to be loaded into the notes section.
_parent.simulation2.gotoAndStop(3);
v_week = 1; //We want to load the consequences for week 1.
student.getallbills1(v_username, 1); //Get the bills for that week.
v_must_pay.splice(0); //Empty the array before adding new items.
for (i = 0; i < rsData.length; i++){ //Put all bills that haven't been paid
if (rsData.getItemAt(i).consequence != 0){ // into the myData object along with
myData.Bill = bill_name_array[i].billname; //the consequences description.
myData.consequence = rsData.getItemAt(i).consequence;
v_must_pay.push(myData); //Push the object into the array at the next space.
}
}
for (i = 0; i < v_must_pay.length; i++){ //Add details of consequence to the
student.getconsequence(v_must_pay[i].consequence); //myData object.
v_must_pay[i].Details = rsData.getItemAt(i).details;
v_must_pay[i].Account = rsData.getItemAt(i).account;
v_must_pay[i].Cost = rsData.getItemAt(i).finance;
}
noticesGrid.dataProvider = v_must_pay; //Make the array a data provider for the notices grid
break;
case "7":
_parent.simulation2.gotoAndStop(4);
break;
case "8":
_parent.simulation2.gotoAndStop(5);
break;
case "9": //Load consequences as for case '6'
_parent.simulation2.gotoAndStop(6);
v_week = 2;
student.getallbills1(v_username, 2);
v_must_pay.splice(0);
for (i = 0; i < rsData.length; i++){
if (rsData.getItemAt(i).consequence != 0){
myData.Bill = bill_name_array[i].billname;
myData.consequence = rsData.getItemAt(i).consequence;
v_must_pay.push(myData);
}
}
for (i = 0; i < v_must_pay.length; i++){
student.getconsequence(v_must_pay[i].consequence);
v_must_pay[i].Details = rsData.getItemAt(i).details;
v_must_pay[i].Account = rsData.getItemAt(i).account;
v_must_pay[i].Cost = rsData.getItemAt(i).finance;
}
noticesGrid2.dataProvider = v_must_pay;
break;
case "10": //Show a relieving notice to the user!!!
Alert.show("You've finished the simulation!", Alert.OK);
break;
}
}


//Set the combobox to display a loading message
loginSchoolChooser.addItem("Loading ...")

//////////////////////////////////////////////////////////
// We need to fill the combobox on the login screen with
// a list of schools from the database. We will use the
// results from the 'getSchools' method.
//////////////////////////////////////////////////////////

login.getSchools();

login_submit.onRelease = function(){
//Login system ensures that only registered users can access the
//program.
//Validate entered data for correct formatting
//All errors cause the red error message to appear
//are any fields empty?
v_account = "";
if (login_school_chooser.text == "") {
login_error._alpha = 100;
} else {
if (login_username.text == "") {
login_error._alpha = 100;
} else {
if (login_password.text == "") {
login_error._alpha = 100;
} else {
//Is one of the radio buttons selected?
if (teacher_radio_button.selected == 'false' && student_radio_button.selected == 'false') {
login_error._alpha = 100;
} else {
//if all details have been entered we can prepare to pass them
//to the login validation procedure. Place them into variables:
v_school = loginSchoolChooser.text;
v_username = login_username.text;
v_password = login_password.text;
if (teacher_radio_button.selected) {
v_account = "teacher";
} else {
if (student_radio_button.selected) {
v_account = "student";
}
}
}
//Call services and create result handlers for both student and teacher login
switch (v_account) {
case "student" :
login_verify._alpha = 100;
//Call the validation procedure and pass parameters:
login.validate_login_student(v_username, v_password, v_school);
break;
case "teacher" :
login_verify._alpha = 100;
//Call the validation procedure and pass parameters:
login.validate_login_teacher(v_username, v_password, v_school);
break;
}//end switch
}
}
}
}
// Stop the movie from proceeding past the login screen
stop();


I hope this isn't too confusing (perhaps just to give a rough overview...)

Thanks again

James.

subHero
03-20-2005, 10:10 PM
yeah, rough, thats what it is ;)

again, i'm not seeing any obvious flaws within the actionscript, so i would start excluding other possible sources for the app not behaving as wanted.

what comes to my mind:
login-service works. are you a 100% on the student.php correctly laid out? filename? methodtable? any other included php-code ?
what does the NetDebugger say?
have you tried hardcoding a return value for the doneworksheetX-method to recheck?

usa_hodson
03-20-2005, 10:27 PM
OK - now I'm starting to unravel this...

I just tried removing the calls to the other doneworksheetX functions - thus leaving only the first one. The movie runs fine. However, I need all of them to run at the beginning...

Based on that, do you have any idea what might be happening? My gut feeling would be the $rsData value returned to the movie - would the fact that I'm always returning the same variable from the php file affect things?

Thanks again,

James.

subHero
03-20-2005, 10:44 PM
Based on that, do you have any idea what might be happening? My gut feeling would be the $rsData value returned to the movie - would the fact that I'm always returning the same variable from the php file affect things?


foa and again: when doing remoting in flash, you have to open up the NetconnectionDebugger. it will tell you (near) exactly what is happening on a http-request level. if your service returns false data, it will tell you. if it doesn't return anything, you will see (that nothing is happening;))
so please, check that and tell what you see.

ott:
the variable-names used in php do not affect anything. remoting returns just their contents.

i still strongly suspect something not being absolutely right on the server-side of things. because if the php service-class is faulty, the result-handler does not get triggered (which seems to be your case).

usa_hodson
03-20-2005, 11:03 PM
Well, I'm kicking myself for not having discovered the netConnectonDebugger several weeks ago...

I have a response for all of the doneworksheet methods being called at the same time - as I said, it works perfectly when just one is called...

Status (object #2)
.....code: 256
.....description: "no class named student is known to the gateway"
.....details: "/home/getwithi/public_html/flashservices/app/Executive.php"
.....level: "User Error"
.....line: 217

I have no idea where to start - I have never changed anything within the flashservices folder before...

When the call works it looks like this...

Result (object #2)
.....length: (undefined)
.....mRecordsAvailable: 1
.....serverInfo: (undefined)
.....uniqueID: 1
.....items (object #3)
..........[0] (object #4)
...............__ID__: 0
...............completed: "true"
.....mTitles (object #5)
..........[0]: "completed"
.....views (object #6)
..........No properties


Thanks for all the help - I would have probably thrown my pc out of the window by now...

James.

subHero
03-20-2005, 11:30 PM
you're getting there without having to afford another computer :)

.....description: "no class named student is known to the gateway"

that is typical of a php-typo, just meaning that something is wrong with your ss-class file.

you said it works all right with just one call to the student-class and leaving the php untouched?
then you probably have some serverside variable scope/overwrite issue.
if so, you'd have to post your student-class to let me try to help you.

another thing that just struck me now:
i really can't recall my NetServices-experiencs, since i am doing it all as2 now, but maybe remoting will give you that (fault-message) also if one request to the same class file is still being processed while firing another. i would suggest trying it out first by simply duplicating the "login.validate_login_student(v_username)" command in the button script. if the result is the same as with the multiple doneworksheet-calls, then this would verify my last assumption and you would have to implement some kind of "action-chain".

well, just try, i'm here ;)

usa_hodson
03-20-2005, 11:52 PM
yes - by duplicating the request to the login file the same thing happens...

Which means the problem is to do with the manner in which requests are carried out I suppose...?

I attempted to make a chain of events by placing the next function call at the end of the previous result handler. This works for the first call, but all subsequent calls - despite being called - receive no answer. Any ideas on making a chain of events that'll work?

Thanks,

James.

subHero
03-21-2005, 12:08 AM
I attempted to make a chain of events by placing the next function call at the end of the previous result handler.

but that is basically all you can do to chain the requests. there are more elaborate solutions (like a ServiceRequestManager), of course, but they are functionally the same.


This works for the first call, but all subsequent calls - despite being called - receive no answer.

the question striking me now is: how can all subsequent calls occur, when they should be triggered by the last received result? can you clarify that and your new implementation?

i thought it would look like:
function doneworksheet1_Result(rsData){
trace("Got result ""+rsData+"" of type "+typeof (rsData));
trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){ //rsData is the number of rows from the MySQL query
trace("Worksheet done!");
v_worksheet1 = "done";
} else {
trace("Worksheet not done!");
v_worksheet1 = "go";
}
student.doneworksheet2(v_username);
}

//Create a result handler for 'doneworksheet2()'
function doneworksheet2_Result(rsData){
//trace("Got result ""+rsData+"" of type "+typeof (rsData));
//trace(rsData.length) //tests for reply from php file
if(rsData.getItemAt(0).completed == "true"){ //rsData is the number of rows from the MySQL query
//trace("Worksheet done!");
v_worksheet2 = "done";
} else {
//trace("Worksheet not done!");
v_worksheet2 = "go";
}
student.doneworksheet3(v_username);
}
and so forth..

usa_hodson
03-21-2005, 12:30 AM
That's the code which I am using - and, in fact, it works now, albeit painfully slowly - the result from doneworksheet6 came about 30 seconds after the first call. Technically this doesn't matter a great deal because I can get round it by setting all of the v_worksheetX variables to "done" so that access is denied until all of the calls have executed...

I guess that wraps up the solution unless you have any suggestions on how to make it run faster?

I'd like to thank you one last time for taking the time to help me out with this - it's made my life a whole lot easier (just another 2000 lines of code to go... ;) ).

All the best,

James.

subHero
03-21-2005, 12:49 AM
hmm, suggestions...

at least one that would boost your performance instantly:
try squeezing all the dataretrieval for the doneworksheetX in one remote method (prolly "checkWorksheets") and return the data using an object/array. i guess your lag comes from the serverside data-accumulation...

but that would be just another chapter to a neverending story, because there will always be room for optimiziation.

i am content with knowing i had been useful with some aspects of helping you get further with your application.

best & cheers
-s