Computing: Website and Database Programming

Using Javascript to run a Perl CGI script.



One of the disadvantages of Perl CGI in comparison with Javascript is, that Perl runs on the server (whereas Javascript runs in the user's browser). This means, that for any action to be taken, data is sent to the webserver and back, what on one side may lead to a high bandwidth on the server and on the other may slow down the application and possibly make the user wait before they get the result. In some cases, such data traffic is completely senseless and nothing else than wasted resources. This is in particular true, if the user enters invalid data into a web form; instead of running the task, that the script should execute, the invalid data travels to the server and the Perl script has nothing to send back than an error message. That's why it is common to check form data with Javascript and sending the data only to the Perl script if it is valid.

Another limitation of CGI scripts concern the location of the output they generate. Normally, writing a webpage with Perl will replace the content of the page, from where the script was called, by the new, generated content. There is a simple trick to make the script do its output into a new browser tab: use the target property in conjunction with the action property of the form tag. Example:
<form id="form1" name="form1" method="post" action="/cgi-bin/myscript.pl" target="_blank">

This may be ok, if the application is intended to be run once or twice, but even in this case, opening a new window would be preferable. Javascript may be used to direct the output of a Perl script to a new window, that may have a given size, thus the possibility to display it on top of the original window. This way to proceed is in particular a good solution if the script generates a formatted message, if it generates another form (for example a user-selection-dependent data input form), or if the script does something without generating any answer, because, even if Perl doesn't write anything to the page, the actual content of the page will be replaced and in this case a blank page will be opened. Opening a new (blank) window (or better with some message like "Thank you", or "Successfully done") looks lots nicer than the whole browser window being empty.

Checking the validity of form data.

Given a web form with one or more input fields (in particular text fields) and a submit button. Instead of sending user input to the CGI script, each time when the button is pushed, it's better praxis to intercept the data by a Javascript script, that validates it (in particular, checks if the user entered any value) and sends the data to the Perl script only if it is valid; if this is not the case, Javascript may for example display a short error message. To do this, we add an onSubmit event to the form tag. This will trigger an action, when the button has been pushed and the form data is ready to be sent to the Perl script. The action consists in making a Javascript script return a Boolean value. If it is true, the data is actually sent; if it is false, no action is taken. Here how the form tag on the main page of my AnimalDB application looks like:
<form id="form1" method="post" name="form1" action="/cgi-bin/animaldb/display.pl" onSubmit="return(checkinput());">

The form has a text field, where the user can enter an animal name to display the information of or "*" to display the list of all animals in the database, and a submit button to call the Perl script that generates the display. By setting the action associated with the onSubmit event to return();, submit is only done if the return() method returns "true". And this value actually is the return value of a Javascript function, that I called "checkinput()". This function may be directly inserted in the <header> part of the HTML page or, as in my case, included from an external file by the following line in the page header:
<script src="/animaldb/animaldb.js" type="text/javascript"></script>

The script does an elementary validity check of the text field content, just looking if it is filled in and if it doesn't contain any single or double quotes (avoiding all trouble with the SQL statement, that will be generated to retrieve the animal information from the database). Note, that with this elementary input check, it is mandatory that the Perl script checks the form data for dangerous characters (in particular "<") in order to protect against cross-site scripting. Here the Javascript code of my checkinput() function:

function checkinput () {
    var ok = false;
    if (document.getElementById) {
        var input = document.getElementById("animal").value;
        if (input == "") {
            alert('Bitte, Tiernamen oder das Wort "Liste" eingeben!');
        }
        else {
            var pattern = /['"]/g;
            var res = pattern.test(input);
            if (res) {
                alert('Der Tiername darf weder Apostroph noch Anführungszeichen enthalten!');
            }
            else {
                ok = true;
            }
        }
    }
    return ok;
}

If the text filed contains valid data, the Boolean value "true" is returned (and the form is submitted to the Perl script); if it is empty or contains a quote, an error message is displayed (and the Perl script will not be called).

Opening a new browser window.

Whereas using Javascript to check form data is a very common praxis, opening a new window for the output of a CGI script is rarely necessary. In my software evaluation application, I have 5 icons, that the user can click to rate some Windows application with a score between "awful" and "amazing". Clicking on an icon should call a Perl script (with the rating score as parameter), that increments a counter in a database. In a first approach, I called the script directly (using a link, associated with the rating images) and I wanted it just doing the database update, without generating any output to the webpage. This does not work! Calling a CGI script always replaces the actual browser window content with the script output, and if the script doesn't generate any output, you get an empty page. My idea was then to display a "thank you" message, but I wanted to display it in a small pop-up window, similar to a message box in desktop applications. Not possible with Perl! And that's where Javascript may be helpful: Associating the buttons with a Javascript function, that can open a new browser window thanks to the window.open method, with the output of the Perl script as content.

Calling a Javascript function, when an object (here an image, being part of a table) is clicked, may be implemented as follows:

<td style="border: 1px solid #000000">
    <a href="javascript:softrating('svnzip', 1)"><img src="./res/rating1.jpg" alt="Your personal rating: Awful" title="Your personal rating: Awful"></a>
</td>

The five rating images are associated with a Javascript-link; the corresponding function, that I included in the <header part of the HTML page, being called with the parameters, needed by the Perl script, here, the code of the application actually being rated and the rating score, corresponding to the icon clicked by the user.

Here my Javascript function, as included in the web page header:

<script language="javascript" type="text/javascript">
<!--
   function softrating(app, rating) {
      window.open('/cgi-bin/softrating.pl?app=' + app + '&rating=' + rating, '', 'width=300, height=150, top=300 left=300 toolbar=no,
         location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no');
   }
//-->
</script>

The first parameter of the window.open method is the webpage to open (respectively, as here, the output of my Perl CGI script), the following ones define the size and position of the window on the screen and other window properties. The variables "app" and "rating" contain the values retrieved as function parameters from the form and they are passed as parameters to the CGI script, by appending them with a "?" to the script URL.



If you find this text helpful, please, support me and this website by signing my guestbook.