Wednesday, 28 October 2020

Javascript callbacks in asp pages

I've looked at this How-do-i-return-the-response-from-an-asynchronous-call and at why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron , but what I'm trying to do doesn't work.

Since some of our users use IE, it seems that we would have to rely on callbacks.

The background to this question comes from a previous post. Legacy code used VBscript's MsgBox, but now the same functionality must be ported to Javascript.

To provide context, there is a bunch of buttons on a toolbar (hence toolbar.asp) such as "New", "Update", "Delete". The user can navigate to certain parts of the system and for instance create a "New" record for a particular resource/person. The details and functionality are shown on the main part of the screen (hence main.asp). The system was originally written about 15 years ago (or more). When the user clicks "Update" on the toolbar.asp, it depends which screen the main.asp was showing. Parts of dovalidation() in main.asp can be swopped (as in a script is fetched from the database) and inserted into dovalidation() depending on what & where the user is. So some parts are still in Visual Basic 6, but it seems that they are trying to replace the VBscript with Javascript.

So the user is on a specific screen and clicks Update (the toolbar.asp's doupdate() is called). This doupdate() does a number of checks on the date and other variables and the calls the main.asp's dovalidation(). Depending on where the user finds himself, dovalidation looks different. In quite a few cases as in the specific example that I am talking about, there used to be a MsgBox in the VBscript code which gave the user a choice depending on the validation done up to that point. However, that VBscript should now be replaced by Javascript. It seems my boss doesn't want to use the normal window.confirm, because she wants to be able to customise the buttons.

VBscript's MsgBox blocked further execution, but now using a jquery confirm doesn't have the same results, because it is non-blocking.

If the validation occurs in such a way that the user is provided with the confirm dialog, and the user clicks on 'Cancel' then the next page should not be shown, but at present, whether the user clicks on 'Cancel' or not, the next page is shown after a couple of seconds. At the end of the doupdate() function there is: parentMain.screenform.submit(); Could that be part of why my callbacks don't work?

In a toolbar.asp file, this is called in the doupdate() funtion:

//... Other code that determines variables, fringe scenarios etc.
//... 

// Then dovalidation() (in which the blocking MsgBox used to be) is called:

var sErr = parentMain.dovalidation();
        if (sErr != ""){
            return;
        }


//Then the rest of the code which is executed irrespective of the jquery confirm.

//do update
    try {
        parentMain.document.all("Updating").value = "YES"
        parentMain.document.body.scrollTop = 0
        parentMain.document.body.scroll = 'no'
        parentMain.ShowBusy();
        document.getElementById("sysBusy").value = "true";
        //parentMain.document.all("clockFrame").style.display = "block";
    } catch(e) {
        return (e)
    }

    //do check for resource tag
    if (sScreenType.toUpperCase() == "RESOURCE TABLE") {
        if (lResource == "0") {
            parentMain.document.all("sysresource").value = lDetailResource
        }
        //alert("looping for resource tag");
        var sField = ""
        var sCheck = "Resource Tag"
        if (!(sScreen == "Resource")) {
            /*********************************************************************/
            /** loop through the fields and update resouce tag if empty - submit**/
            /*********************************************************************/
            var elements = parentMain.document.getElementById("screenform").elements;

            for (var i = 0, element; element = elements[i++];) {
               if ((element.name).indexOf(sCheck) > 0) {
                    var sValue = element.value
                    if (sValue.length == 0) {
                        element.value = lDetailResource
                    }
                }
                if ((element.tagName.toUpperCase()) == "SELECT") {
                    if (element.disabled == true) {
                        element.disabled = false;
                    }
                }
            }
        }
        
    }
  
    //submit screen

    parentMain.screenform.submit(); //<-- Could this be part of the problem?
    
    }

In the main.asp file the dovalidation function resides. A part of the dovalidation function is swapped out depending on the situation. That is marked between the //################

function dovalidation() {
msErr = "";
         
//#################
if (msErr.length == 0) {

var vEffectiveDate="";
var vLastRunDate="";
var sStatus="";
var vMsg="";
var sResponse="";
vEffectiveDate = document.getElementById("Smoke.Effective Date").value;
vLastRunDate = document.getElementById("Smoke.Last Run Date").value;
sStatus  = document.getElementById("Smoke.Calc Status").value;
vMsg = "";
if ((sStatus).length == 0  ){
    sStatus = "SUCCESFUL";
    //document.getElementById("Smoke.Calc Status").value= sStatus;
}
if ((vEffectiveDate).length > 0  ){
    if (!isDate(vEffectiveDate)  ){
        vMsg = vMsg+"[Effective Date] Is not a date." + ";\r\n";
    } else if (  moment( toDate(vEffectiveDate)).isBefore(toDate(vLastRunDate)) ){
        vMsg = vMsg+"[Effective Date] cannot be on/before "+vLastRunDate+"." + ";\r\n";
    }
}
if (sStatus.toUpperCase() != "SUCCESFUL") {
    $.confirm({
        title:  "Confirmation",
        columnClass: 'col-md-6 col-md-offset-3', 
        content:"Forecast calculation still busy. Results might not be accurate. Continue?",
        buttons: {
            confirm: function() {
                sResponse= "1";
                vMsg = "Response 1";                
                processMessage(); // <--- added this
            },
            cancel: function() {
                sResponse= "2";
                vMsg = "Response 2";                
                // Moved code here, as it needs to execute when Cancel is clicked
                $.alert({
                    title: "INFORMATION",
                    columnClass: 'col-md-6 col-md-offset-3',
                    content: "Screen will refresh. Please click on Update to try again.",
                    // Code that should execute when alert is closed:
                    onAction: function () {
                        document.getElementById("Smoke.Calc Status").value= "REFRESH";
                        msErr = "ABORT";
                        processMessage(); // <--- added this
                    }
                });
            },
        }
    });
} else { // <-- added
    processMessage();
}

function processMessage() {
    // Moved code in a function, as it should only execute after confirm/alert is closed 
    if (vMsg != "") {
        $.alert({
            title: 'Validation Message',
            columnClass: 'col-md-6 col-md-offset-3',    
            content: vMsg,
        });
        msErr = "ERROR";
        
    }
  }
 }                     
//#################
          
return msErr;   
}

So I think my problem lies with msErr being returned long before the user has had chance to decide which button on the confirm dialog to choose. If I don't set breakpoints and click on the confirm's cancel then I do see that the alerts are shown, but the page is not refreshed (document.getElementById("Smoke.Calc Status").value= "REFRESH";) and the next page is shown. I think this comes from the sErr == "" in the toolbar.asp file and then the program flow just continues.

Anycase, I tried using callbacks, but the situation hasn't changed.

Here is what I tried to do:

parentMain.dovalidation(function(result){
    if (result != ""){
        return;
    }
    });

In main.asp the dovalidation function:

function dovalidation(callback) {
 msErr = "";
         
//#################
if (msErr.length == 0) {

    var vEffectiveDate="";
    var vLastRunDate="";
    var sStatus="";
    var vMsg="";
    var sResponse="";
    vEffectiveDate = document.getElementById("Smoke.Effective Date").value;
    vLastRunDate = document.getElementById("Smoke.Last Run Date").value;
    sStatus  = document.getElementById("Smoke.Calc Status").value;
    vMsg = "";
    if ((sStatus).length == 0  ){
        sStatus = "SUCCESFUL";
        document.getElementById("Smoke.Calc Status").value= sStatus;
    }
    if ((vEffectiveDate).length > 0  ){
        if (!isDate(vEffectiveDate)  ){
            vMsg = vMsg+"[Effective Date] Is not a date." + ";\r\n";
        } else if (  moment( toDate(vEffectiveDate)).isBefore(toDate(vLastRunDate)) ){
            vMsg = vMsg+"[Effective Date] cannot be on/before "+vLastRunDate+"." + ";\r\n";
        }
    }
    if (sStatus.toUpperCase() != "SUCCESFUL") {
        $.confirm({
            title:  "Confirmation",
            columnClass: 'col-md-6 col-md-offset-3', 
            content:"Forecast calculation still busy. Results might not be accurate. Continue?",
            buttons: {
                confirm: function() {
                    sResponse= 1;
                    vMsg = "Response 1";
                    processMessage(); // <--- added this
                },
                cancel: function() {
                    sResponse= 2;
                    vMsg = "Response 2";
                    // Moved code here, as it needs to execute when Cancel is clicked
                    $.alert({
                        title: "INFORMATION",
                        columnClass: 'col-md-6 col-md-offset-3',
                        content: "Screen will refresh. Please click on Update to try again.",
                        // Code that should execute when alert is closed:
                        onAction: function () {
                            document.getElementById("Smoke.Calc Status").value= "REFRESH";
                            msErr = "ABORT";
                            processMessage(); // <--- added this
                        }
                    });
                },
            }
        });
    } else { // <-- added
        processMessage();
    }
    
    function processMessage() {
        // Moved code in a function, as it should only execute after confirm/alert is closed 
        if (vMsg != "") {
            $.alert({
                title: 'Validation Message',
                columnClass: 'col-md-6 col-md-offset-3',    
                content: vMsg,
            });
            msErr = "ERROR";
        }
    }
}
//#################         
callback(msErr);   
} 

So, it isn't working as it should, and I don't know what I've done wrong, but I suppose I haven't used the callbacks correctly. Does it make a difference that it is in two different files? This has to work given that the parts between the //######### are swopped.

I would appreciate any feedback and guidance.



from Javascript callbacks in asp pages

No comments:

Post a Comment