throop has asked for the wisdom of the Perl Monks concerning the following question:

Brethren,

From a webpage form, how do I save a javascript variable's state as a CGI::param?

Background: I'm coding a set of cgi-bin tools using CGI::Session. The pages display an indentured datastructure (read in from XML::Simple::XMLin). 'Folders' —parts of the datastructure—are hidden / exposed by clicking on icons. The icons are <IMG> tags with onclick methods that call a javascript function, toggleFolder.

In turn, toggleFolder toggles a javascript variable – folder.style.display – between 'block' and 'none'.

The problem: This is all working fine. But when the user reloads the page, (i.e, POSTs a 'submit' to save his inputs) the state information for all the folders is lost. The javascript variables aren't immediately accessible to the CGI::param variables. So the page comes back up with all the folders closed and the user has to click repeatedly to get back to the state before the Submit.

My question: How do I copy the value of a javascript variable (like folder.style.display) over to a CGI::param variable? Do I do it within the javascript (within the function definition of toggleFolder)? or from Perl?

Is there a module that I should be looking at to do this?

(I'm reasonable Perl programmer, but a novice at javascript. I'm refactoring / adapting someone else's code.)

thanks
throop

Replies are listed 'Best First'.
Re: CGI: Saving javascript variables
by jZed (Prior) on Oct 31, 2007 at 19:52 UTC
    One way: create a hidden field in the form and put in the folder.style information. If you have a lot of fields, send it as a JSON string. Then on the server side, use JSON or JSON::Syck to turn that string into a Perl data structure and voila - your JS variables are in your CGI script.
      Thanks...

      I'm still having trouble understanding. You say
          > create a hidden field in the form and put in the folder.style information.
      I'm still confused about how to grab the folder.style.display information. I guess I'm looking for a Perl function that does something like

      param("folder_$id") = grabFromJavascript('folder.style.display', $id) +;
      or, I guess more likely, a Javascript snippet that does something like
      pushToCgiParam(id, folder.style.display)
      or is it an html form that calls a javascript function, like
      <input type="hidden" name="folder_12" value=folderStatus(12) />

      throop

        There are only four ways I know for JavaScript to inform Perl about anything: 1) as a querystring on a GET request, 2) as a field in a form sent as a POST request, 3) as either GET or POST on an AJAX request, 4) by having JavaScript write to a cookie and then having Perl retrieve the cookie.

        You'd have to explain your overall goal for me to know which of those is best for you. I'm just answering the part of the question about sending something JavaScript knows to a Perl script.

        In a hidden field you could do something like these:
        <input type="hidden" name="folder_opts" id="folder_opts"> <script type="text/javascript"> document.getElementById('folder_opts').value = '{"f1":' + fi_value + ',"f2":' + f2_value + '}'; </script>
        Then on the Perl side, you'd read the folder_opts param, turn it into a Perl hash with one of the JSON modules.

        I'm think the cookie way is the best choice for you.

        • on page load read cookies for folder.style.display info for each folder;
        • when style.display is changing write this info into cookie;

        So this is pure Javascript solution.

Re: CGI: Saving javascript variables
by Crackers2 (Parson) on Oct 31, 2007 at 20:27 UTC

    Another way: Use AJAX to update the variable on the server whenever it's toggled.

    The downside is that you generate more traffic, and if you don't properly code it you may slow down the user experience

    The advantage is that the state will be updated on the server even if the user never submits the form, for example if they just close the browser intending to come back later. You also don't have to send the state along with every single link or form on the page.

Re: CGI: Saving javascript variables
by aquarium (Curate) on Oct 31, 2007 at 21:20 UTC
    also you may like to take a look at implementing the form ajax style, i.e. provide your own Submit handler, instead of using the html form Submit..which does a page refresh.
    crossbrowser toolkits for this kind of work in both pure javascript or perl-javascript are becoming more abundant by the day.
    the hardest line to type correctly is: stty erase ^H