Exercise 3 AJAXEX3 Using Asynchronous Processing

Visual LANSA Framework

Exercise 3: AJAXEX3 – Using Asynchronous Processing 

AJAX Page AJAXEX3.HTM

AJAX Function AJAXEX3

The Steps

 

  • Copy and paste the DHTML-JavaScript code in AJAX Page AJAXEX3.HTM using NOTEPAD and save it into your Framework private working folder as an AJAX page file named AJAXEX3.HTM.
  • Copy and paste the AJAX function code in AJAX Function AJAXEX3 into an RDMLX function named AJAXEX3 into your VL-IDE. Compile RDML function AJAXEX3 so that it is executable on your web server.
  • In business object AJAX, snap AJAX page file AJAXEX3.HTM and AJAX function AJAXEX3 into your Framework as the command handler to be associated with command AJAXEX3 like this:

 

 

  • Save, restart and execute your Framework in a web browser. Select application ‘AJAX Examples’ and then select business object AJAX. This should execute the default command AJAXEX1. Click on the AJAXEX3 tab to execute the AJAXEX3 command:

 

 

This AJAX example is designed to demonstrate the asynchronous nature of AJAX processing.

It is updating the zip codes associated with people. As you change zip codes and press Enter or tab your change will be sent to the server for processing. While this is happening you can update other zip codes.

Try this sequence:

  • Click on the first zip code and select it.
  • Then type “1”, Tab ->, “2”, Tab ->, “3”, Tab ->, etc as fast as you can.

The display should look like this:

 

 

As you make each change and press the tab -> key, your change is sent to the server for immediate validation. You can then keep making changes while the server handles this request.     

In a real application you are more likely to be entering order lines (say) and the changes you make are updated immediately into the server database.

You should review the JavaScript/DHTML code in AJAXEX3.HTM and the RDML code in AJAX function AJAXEX3 until you understand the basics of what it is doing and how it is doing it. 

 

AJAX Page AJAXEX3.HTM

 

<HTML> 

<HEAD id='HEAD_Tag'> 

<link rel='stylesheet' type='text/css' href='vf_vs001.css' >    

<script> 

/* ======================================================================== */ 

/* ======================== Handle Page Initialization ==================== */ 

/* ======================================================================== */ 

function VF_AJAX_Initialize() 

   /* Insert the variable style sheet (ie: XP, WIN, WEB style) into this page */ 

   { 

      var objLink  = document.createElement("LINK"); 

      objLink.rel  = "stylesheet"; objLink.type = "text/css";  

  objLink.href = STYLESHEET(); 

      document.getElementById("HEAD_Tag").insertAdjacentElement("afterBegin",objLink);  

   } 

    

   /* Finished */ 

   return; 

}  

/* ======================================================================== */ 

/* ======================== Handle Page Execution ========================= */ 

/* ======================================================================== */ 

function VF_AJAX_Execute() 

  /* Request that the server makes up 10 example name/address/zipcode details */ 

  SENDREQUEST(window,"","LOAD10","",LOAD10_response);   

  /* Finished */ 

  return; 

}  

/* ======================================================================== */ 

/* ======================= Handle Page Termination ======================== */ 

/* ======================================================================== */ 

function VF_AJAX_Terminate() 

  return; 

}  

/* -------------------------------------------------------- */ 

/* Rationalized virtual clipboard access to name space AJAX */  

/* -------------------------------------------------------- */ 

function Put(val,np2,np3,inst) {AVSAVEVALUE(val,"AJAX",np2,np3,inst);} 

function GetA(np2,np3,inst)    {return(AVRESTOREAVALUE("","AJAX",np2,np3,inst));} 

function GetN(np2,np3,inst)    {return(AVRESTORENVALUE(0,"AJAX",np2,np3,inst));} 

/* ---------------------------------- */ 

/* Handle server responding to LOAD10 */ 

/* ---------------------------------- */ 

function LOAD10_response(strFunction,strRequest,strPayload,objObject,flagFatalError,strFatalMessage) 

  var inst = 0; 

  /* Handle a fatal error in the server function */  

  if (flagFatalError) { alert(strFatalMessage); SETBUSY(false); return; }   

   

  /* Otherwise load the tabe with the 10 results and display to the user */ 

  for (inst = 1; inst <= 10; inst++) 

  { 

     var objTR        = TBODY_Tag.rows(inst - 1);  

 var objTDName    = objTR.children(0); 

 var objTDAddress = objTR.children(1); 

 var objINZipCode = objTR.children(2).children(0); 

     var objTDStatus  = objTR.children(3); 

 

     objTDName.innerText    = GetA("EX3","NAME",inst);  

     objTDAddress.innerText = GetA("EX3","ADDRESS",inst);  

     objINZipCode.value     = GetN("EX3","ZIPCODE",inst).toString();  

     objINZipCode.__validatedvalue = objINZipCode.value;  

     objTDStatus.innerText  = " Loaded from Server ";  

     objTDStatus.style.backgroundColor = "palegreen";  

          

  } 

 

  /* Hide the message panel and show the table panel */ 

 

  DIV_Message.style.visibility = "hidden"; DIV_Message.style.display    = "none";  

  DIV_Table.style.visibility   = "visible"; DIV_Table.style.display      = "inline";  

 

  /* Drop busy status */ 

  SETBUSY(false);  

   

  /* Finished */ 

  return; 

/* ------------------------------------------------------------ */ 

/* Handle key press in TBODY and tabbing to next input zip code */ 

/* ------------------------------------------------------------ */ 

function NextZipCode(objINZipCode) 

  var intNext = parseInt(objINZipCode.__Instance,10) + 1;  

  if (intNext > 10) intNext = 1;  

  var objNextINPUT = document.getElementById("IN" + intNext.toString());  

  if (objNextINPUT != null) objNextINPUT.focus(); 

 

function TBODY_onkeydown() 

  /* Ignore if not valid, or not enter or ab key */ 

  if ((event.keyCode != 13) && (event.keyCode != 9)) return;  

  if (typeof(event.srcElement.__validatedvalue) == "undefined") return;  

 

  /* Extract the INPUT field involved, ignore if not zip code or not changed */  

  { 

     var objINZipCode = event.srcElement; 

 /* If unchanged do nothing */ 

     if (objINZipCode.__validatedvalue == objINZipCode.value )  

 {  

    if (event.keyCode == 13) NextZipCode(objINZipCode);  

 } 

 else 

 {  

        while (objINZipCode.value.length < 5) objINZipCode.value = "0" + objINZipCode.value;  

        var floatNumber = parseFloat(objINZipCode.value);  

     /* var intInstance = parseInt(objINZipCode.__Instance,10); */

        var intInstance = parseInt(objINZipCode.getAttribute("__Instance"),10);  

        if (isNaN(floatNumber)) { alert("Invalid number entered"); return; } 

        /* reaching here means a zip code that has been changed, so send validation request */ 

        { 

           var objTDStatus = objINZipCode.parentElement.nextSibling;  

       objTDStatus.innerText  = " Validating at Server ";  

           objTDStatus.style.backgroundColor = "gold";  

        objINZipCode.contentEditable  = false; 

        Put(floatNumber,"EX3","ZIPCODE",intInstance);    

SENDREQUEST(window,"","VALIDATE",intInstance.toString(),VALIDATE_response,objINZipCode);     

if (event.keyCode == 13) NextZipCode(objINZipCode);  

 }   

  }  

 

  /* Finished */ 

  return; 

/* ------------------------------------ */ 

/* Handle server responding to VALIDATE */ 

/* ------------------------------------ */ 

function VALIDATE_response(strFunction,strRequest,strPayload,objINZipCode,flagFatalError,strFatalMessage) 

  var objTDStatus = objINZipCode.parentElement.nextSibling;  

 

  /* Handle a fatal error in the server function */  

  if (flagFatalError) { alert(strFatalMessage); return; }   

 

  objINZipCode.contentEditable = true; 

 

  if (GetA("EX3","RESPONSE") == "OK") 

  {  

     objINZipCode.__validatedvalue = objINZipCode.value;   

     objTDStatus.innerText  = " Validated and Updated by Server ";  

     objTDStatus.style.backgroundColor = "springgreen";  

  } 

  else 

  { 

     objTDStatus.innerText  = " Validation by Server failed - " + GetA("EX3","MESSAGE") + " ";  

     objTDStatus.style.backgroundColor = "tomato";  

  }  

 

  /* Zap the object reference */  

   objINZipCode = null; 

 

</script> 

 

</HEAD> 

<BODY id='BODY_Tag'> 

<br/><br/><br/> 

<P align='center'>High Volume Update</p> 

<div id='DIV_Message'> 

<P align='center'>Loading ... please wait</p> 

</div> 

<div id='DIV_Table' style='visibility:hidden;display:none;'> 

<table> 

<thead> 

<tr> 

<th>Name</th><th>Address</th><th>Zip Code</th><th>Status</th></tr> 

</thead> 

<tbody id='TBODY_Tag' onkeydown='TBODY_onkeydown();'> 

<tr><td></td> <td> </td> <td><input id='IN1'  type='text' maxlength=5' __Instance=1></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN2'  type='text' maxlength=5' __Instance=2></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN3'  type='text' maxlength=5' __Instance=3></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN4'  type='text' maxlength=5' __Instance=4></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN5'  type='text' maxlength=5' __Instance=5></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN6'  type='text' maxlength=5' __Instance=6></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN7'  type='text' maxlength=5' __Instance=7></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN8'  type='text' maxlength=5' __Instance=8></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN9'  type='text' maxlength=5' __Instance=9></td><td> </td></tr> 

<tr><td></td> <td> </td> <td><input id='IN10' type='text' maxlength=5' __Instance=10></td><td> </td></tr> 

</tbody> 

</table> 

</div> 

</BODY> 

</HTML> 

 

 

AJAX Function AJAXEX3

* This is just a simple RDMLX function. 

* It is NOT a WAM. 

* It is driven by the virtual clipboard 

 

Function Options(*DIRECT *HEAVYUSAGE) 

 

* Define local fields 

 

Define Field(#REQUEST) Reffld(#STD_OBJ) 

Define Field(#PAYLOAD) Reffld(#STD_TEXTL) 

Define Field(#INSTANCE) Type(*DEC) Length(7) Decimals(0) 

 

* Get the action and paylaod Javascript supplied .... 

 

Execute Subroutine(GETA) With_Parms(SYSTEM REQUEST 1 #REQUEST) 

Execute Subroutine(GETA) With_Parms(SYSTEM PAYLOAD 1 #PAYLOAD) 

 

* Now switch on the requested action 

 

Case Of_Field(#REQUEST) 

 

* Load 10 sample entries 

 

When Value_Is(= LOAD10) 

Execute Subroutine(Load10) 

 

* Validate a zip code 

 

When Value_Is(= VALIDATE) 

Execute Subroutine(VALIDATE) 

 

* Handle a bad request 

 

Otherwise 

Abort Msgid(DCM9899) Msgf(DC@M01) Msgdta(('Unknown request ' + #REQUEST + ' received by ' + *FUNCTION)) 

 

Endcase 

 

* Finished 

 

Return 

 

* ===================================================== 

* Request handling subroutines 

* ===================================================== 

 

Subroutine Name(Validate) 

 

* The paylaod contains the instance number of the zip code 

* that is to be validated by this request, so get it as a number 

 

#Instance := #Payload.AsNumber() 

 

* Now get the zip code number associated with the instance 

 

Execute Subroutine(GetN) With_Parms(EX3 ZipCode #Instance #Std_Num) 

 

* Now validate the zip code and give response codes and error messages 

 

Case (#Std_Num) 

 

When (< 123) 

 

Execute Subroutine(PutA) With_Parms(EX3 Response 1 ER) 

Execute Subroutine(PutA) With_Parms(EX3 Message 1 ('Zip code ' + #Std_Num.AsString() + ' is less than 123')) 

 

When (> 77777) 

 

Execute Subroutine(PutA) With_Parms(EX3 Response 1 ER) 

Execute Subroutine(PutA) With_Parms(EX3 Message 1 ('Zip code ' + #Std_Num.AsString() + ' is greater than 77777')) 

 

Otherwise 

 

Execute Subroutine(PutA) With_Parms(EX3 Response 1 OK) 

 

Endcase 

 

Endroutine 

 

Subroutine Name(Load10) 

#Instance := 0 

Execute Subroutine(Add) With_Parms('Fred Bloggs' '121 Smith St' 32627) 

Execute Subroutine(Add) With_Parms('Mark Bloggs' '121 Smith St' 32627) 

Execute Subroutine(Add) With_Parms('Bill Bloggs' '121 Smith St' 32627) 

Execute Subroutine(Add) With_Parms('John Doe' '11 Jones St' 40210) 

Execute Subroutine(Add) With_Parms('Susan Doe' '11 Jones St' 40210) 

Execute Subroutine(Add) With_Parms('Junior Doe' '11 Jones St' 40210) 

Execute Subroutine(Add) With_Parms('John Handcock' '15 Wash Road' 40314) 

Execute Subroutine(Add) With_Parms('Helen Handcock' '15 Wash Road' 6314) 

Execute Subroutine(Add) With_Parms('Fred Handcock' '15 Wash Road' 60314) 

Execute Subroutine(Add) With_Parms('Mark Smith' '151 Teller Avenue' 60315) 

Endroutine 

 

Subroutine Name(Add) Parms((#Std_text *received) (#Std_textl *received) (#std_num *received)) 

#Instance += 1 

Execute Subroutine(PutA) With_Parms(EX3 Name #Instance #Std_Text) 

Execute Subroutine(PutA) With_Parms(EX3 Address #Instance #Std_Textl) 

Execute Subroutine(PutN) With_Parms(EX3 ZipCode #Instance #Std_Num) 

Endroutine 

 

* ===================================================== 

* Rationalized subroutines for virtual clipboard access 

* ===================================================== 

 

* ===================================================== 

* Rationalized subroutines for virtual clipboard access 

* ===================================================== 

 

Subroutine Name(PUTA) Parms((#NP2 *RECEIVED) (#NP3 *RECEIVED) (#INST *RECEIVED) (#AVAL *RECEIVED)) 

Define Field(#NP2) Type(*CHAR) Length(28) 

Define Field(#NP3) Type(*CHAR) Length(24) 

Define Field(#INST) Type(*DEC) Length(7) Decimals(0) 

Define Field(#AVAL) Type(*CHAR) Length(256) 

Use Builtin(VF_SAVEAVALUE) With_Args(#AVAL AJAX #NP2 #NP3 #INST) 

Endroutine 

 

Subroutine Name(PUTN) Parms((#NP2 *RECEIVED) (#NP3 *RECEIVED) (#INST *RECEIVED) (#NVAL *RECEIVED)) 

Define Field(#NVAL) Type(*DEC) Length(30) Decimals(9) 

Use Builtin(VF_SAVENVALUE) With_Args(#NVAL AJAX #NP2 #NP3 #INST) 

Endroutine 

 

Subroutine Name(GETA) Parms((#NP2 *RECEIVED) (#NP3 *RECEIVED) (#INST *RECEIVED) (#AVAL *RETURNED)) 

Use Builtin(VF_RESTOREAVALUE) With_Args(' ' AJAX #NP2 #NP3 #INST) To_Get(#AVAL) 

Endroutine 

 

Subroutine Name(GETN) Parms((#NP2 *RECEIVED) (#NP3 *RECEIVED) (#INST *RECEIVED) (#NVAL *RETURNED)) 

Use Builtin(VF_RESTORENVALUE) With_Args(0 AJAX #NP2 #NP3 #INST) To_Get(#NVAL) 

Endroutine