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

I'm trying to get my PERL-CGI-DBI program to be a bit more userfriendly. I've begun to venture into the presumably ugly land of javascript.

What I'm trying to accomplish is:
To have a series of textboxes with data from my database in them, and when I change one, the DB automaticlly updates without having to hit 'submit'.

I got close to solving it using the onChange parameter in my input field...calling a javascript function, but i was unable to call my perl function that updates the DB from inside the javascript function. confused?

Is it possible to call a perl function from onChange?
or is it possible to call a perl function from within a javascript function
or is there a completely different way to do this that I havn't thought of?

any help is greatly appreciated

Replies are listed 'Best First'.
Re: How to make a friendly UI
by AgentM (Curate) on May 03, 2001 at 05:56 UTC
    In order to use server side perl scripts, you need to have the form submitted. This can be automated with JavaScript, but....

    The question is whether you really want to do this. Web developers tend to stay away from JavaScript for a number of reasons.

    • different browsers differ greatly in expected Jscript objects. This means that most likely, you will never have a fully cross-Jscript-capable interface. While EczemaScript has been a worthy attempt in perhaps the right direction, but even the world's most popular browser is skimpy on compatibility.
    • Many browsers do not support JavaScript or many users prefer to have it off- even if it's just to avoid annoying pop-up ads. I am one of this breed. I doubt that I'm alone.
    • JavaScript tends to be...well- annoying. One sees it alot sliding buttons or switching colors. This is all fine and well in the land of non-JScript-capable browsers, just as long the links are not of the JScript clicking variety. This is functionality which I believe is the correct domain of JScript- non-crucial tasks only. If I switch off JScript, I still can navigate the site perfectly fine.
    Of course, you may argue that you're web app is used only in a limited pool of computers all of which support X, Y, and Z and will work great with whatever you cough up. That's nice, but as soon as the company Dilbert sees that he could work at home and he can't use your app because of JavaScript errors. OR the company wishes to move or sell or copy the app to a different circle of users, all of which have NO Jscript or use a different browser. Bad news and one that is actually easily avoidable...just use a recent version of HTML.

    If you find that you your web application would be better represented using objects or states, then look into jellybean or CGI::Application, not to mention everything2 and a slur of proprietary web object servers.

    If you're looking for TRUE interactivity, you're not looking for web-based apps. In that case, you'd be looking at actual GUI implementations which your customer may benefit from. Try Tk for a cross-platform solution. Web searches on any of these topics will get you off to a strong start. Good luck!

    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
Re: How to make a friendly UI
by dws (Chancellor) on May 03, 2001 at 05:23 UTC
    Are you really sure you want to be that friendly? The cost of that friendliness may be high, with at least one difficult edge case.

    I assume that you don't want to automagically post the form on every keystroke within a field, since responsiveness would become decidedly unfriendly.

    If that assumption is true, you need to trigger on transition out of a field (or into another one). That opens you up to the edge case of no transition, such as the user typing into a field, then doing something like hitting the "Back" button or typing in a URL. There's no onClick event to capture to trigger you examining fields for changes. Would a resonable user believe that the database should have changed in a case like this?

    The nice thing about an explicit "Submit" is that it's unambiguous, with no edge cases.

Re: How to make a friendly UI
by tinman (Curate) on May 03, 2001 at 05:24 UTC

    As far as I know, there isn't a way to call a Perl function (I assume you mean a CGI script) directly from the client in the way that you ask.. You could do some trickery with etc, etc, but I don't think that's what you mean...

    The only solution that I can see is to have the possible combinations of database select boxes highlighted.. ie: build a data structure within your client side javascript code..

    I've seen what you ask being done inside applets (but applets are difficult to venture into for other reasons, not least being that its not Javascript, but Java :o)

    Umm, as I see it, the problem here is that Javascript is intended to be executed at the client side, and to have it fetch stuff from a remote server is not a really good thing to be doing, even if its possible (which in some cases, it may not be).. A CGI script is a server side deal, so it should and does fetch stuff from a remote database..

    So, if you really want this functionality present through Javascript, build an indexed array within your HTML page (a Javascript array) that has the relevant combinations..and write the display logic in Javascript as well... you can generate all of this through a server side CGI script...

    But I'd personally recommend that you think of an alternative means of getting the functionality you desire.. HTML isn't a local-machine GUI paradigm, its slightly different, and the interfaces that you build should take that into account..
    my <$0.02 ;o)

Re: How to make a friendly UI
by olly (Scribe) on May 03, 2001 at 15:34 UTC
    Well I don't know how to do it with standard html, but I believe you could use macromedia flash for it. There is a trial version over at macromedia and the help files explain more about letting flash interact with cgi's and databases.

    Imagination is more important then knowledge -Einstein-

      FWIW, there is Perl::Flash if you want to use flash. Yes - you can code your flash swf files in perl now.
      use signature; signature(" So long\nAlfie");
Re: How to make a friendly UI
by thpfft (Chaplain) on May 03, 2001 at 18:19 UTC

    You have two options, i think.

    1. dump data from your script into javascript variables and include javascript code on the page itself that will select from it to update the value of some boxes when other boxes are changed. You get this sometimes on very structured sites where lots of subcategorisation is required. there are no server-side processes after the initial page-building step. You tend to get large pages this way, because of all the permutations that need to be considered, and you'll need a reasonable command of javascript.

    2. make repeated cgi calls. if you want to get data from the server based on user input, you have to go through the usual 'send data, receive data' process, and that means you have to refresh the page. If you wanted things to unfold in friendly way then you could do something with frames or pop-up windows, but you face the prospect of building and debugging a system with interdependent javascript, perl and frame targetting. ugly.

    Two other considerations i'd like to mention.

    Firstly, neither of these approaches will work well without strictly controlled and relatively simple input. perhaps you were just glossing over the details, but this sort of thing will only work reliably with drop-down lists or checkboxes (ie, fields where the values are defined in advance) rather than text fields or textboxes, where typos abound. They also offer onClick or onSelect methods (?terminology?) that are more reliable than onChange, which rather unhelpfully requires you to tab _out_ of the field to trigger the script.

    Secondly, what's wrong with refreshing the page? i can see cases where you want to let people choose subcategories on a complex form without hassle, but if the form is that complicated, are you sure you wouldn't be better off building a simpler one? Given that the goal is friendliness, you'll get better results from clear language and consistent behaviour than from gui cleverness. imho.

      Thank you all for your comments.

      The user base for the project is fairly small, and controlled, so I have no worries about browser javascript conflicts.
      I would have worries about putting all the infromation into javascript variables, and doing more jscript coding. I think it might slow things down, and speed is a critical factor.
      The push for a more friendly UI is comming from the users that are used to 'filemakerPro' type interaction, where everthing is editable all the time. I've stuck with the web medium because some users will access parts of the information from outside the company, and it seems to be easier to code.
      I have a feeling I will revert back the the 'submit' type form, and try to incorporate a more complex screen layout with frames, so that information viewing can happen at the same time as information viewing.

      Thanks to everyone.<br. david
Re: How to make a friendly UI
by asiufy (Monk) on May 03, 2001 at 05:45 UTC
    An easier solution would be to, once the user is done editing all the textboxes, he should just close the window, or exit it, and the changes will be commited to the database. To do that, you have to place an "onload=script.cgi" on the BODY tag of your HTML, "script.cgi" being the one that actually writes this data to the DB.

    I suggest you place a javascript confirmation alert before you actually write the data, just in case...
Re: How to make a friendly UI
by franknmonk (Monk) on May 03, 2001 at 22:14 UTC
    An older trick is to set up the pages with an invisible frameset. Meaning 2 rows or cols, one * and the other width/height 0. Then all calls to the scripts will be done in this invisble frame... -Franknmonk
      what does this buy me? I'm not sure i understand the significance of this. d
        You can have the javascript actions call the perl script in the invisible frame, so the perl script will run 'invisibly'
Re: How to make a friendly UI
by sierrathedog04 (Hermit) on May 03, 2001 at 21:24 UTC
    If you have a small number of users, and you don't mind requiring them to have ActiveState Perl (which is free) installed, then you can use ActiveState's PerlScript component which enables you to freely call Perl subroutines from an onChange event. You can find out more about Perlscript here.
Re: How to make a friendly UI
by thraxil (Prior) on May 04, 2001 at 08:20 UTC
    "Is it possible to call a perl function from onChange? or is it possible to call a perl function from within a javascript function or is there a completely different way to do this that I havn't thought of?"

    you "call" a cgi script by sending an HTTP request. so you can't really call a specific perl function directly from javascript. the best you can do is put whatever functionality you wanted from the function into its own perl script and send requests for that.

    normally, if your browser sends an HTTP request, it will load the page it gets as a response into the browser, replacing the current page. you can get around this by having your perl script send back non-parsed headers. (see the documentation for the CGI module for info on how to do that). the other option is the hidden frame trick mentioned earlier.

    on the javascript end of things, you'd want to have it change the url of the current document to the url of the nph perl script, plus as many fields as necessary passed as GET variables.

    ie, you'd probably have something similar to:

    <input type="text" name="foo" onblur="updateField("foo",this.value)" />

    where the javascript function updateField has been defined as something like:

    function updateField(field,value) { var newurl = " +d=" + field + "&value=" + value; document.location.href = newurl; }

    this is all off the top of my head, so there are probably some things i forgot. obviously, you would also need to pass along something akin to the primary key for the record so the script knows which one to update. plus you'd have to be careful to url encode everything you pass in the url, etc, etc.

    all in all, the benefit probably isn't worth the work it would take to get it all to work.

    anders pearson // digital samurai
    personal/pgp  //  
    weblog       //
      Yes, all this is very much correct. I have had the dubious pleasure of doing a fair amount of this sort of thing via the hidden frame. A couple of important points to be on the look-out for:
      1. If you are expecting this to function as a "function" call, (i.e. returning a value, and/or halting execution of the calling process (javascript) untill returning) you are pretty much SOL. The loading of the cgi script in the hidden frame can be thought of as occuring in a different 'thread' if you will. In order to wait untill the return of the perl function (i.e., wait for the completion of the execution of the cgi, and download/render in your browser) you'd have to go into some horrible hokey javascript which gets vaguley reminiscent of programming in old-school basic with goto-line-numbers and the like... ugh, at the thought.
      2. in the javascript provided above, (which I understand is off-the-cuff... I merely point this out so that others avoid the potential pitfalls)
        <- document.location.href = newurl; -> parent.**hiddenJSframesNameHere**.document.location.href = newurl;
        or else you'll be reloading your own frame which is exactly what you wanted to avoid! and please, PLEASE use the javascript function escape(...) when constructing that get-string... like:
        var newurl = "" + escape(field) + "&value=" + escape(v +alue);
        (escape performs URI-escaping... for similar stuff in perl, look at URI::Escape)

      --a (hopefuly) helpful perl web-junky