Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Simple example of CGI (Perl) + HTML + CSS + Javascript/jQuery + Ajax

by golux (Pilgrim)
on Aug 21, 2013 at 16:23 UTC ( #1050387=CUFP: print w/ replies, xml ) Need Help??

Questions about combining Perl with jQuery keep coming up, so I'm posting this simple example to be able to refer to it later.

Update:   You can see a running example of the code here. What it does -- displays a grid of numbers, letting you click on any number to see its factors, and tells whether the number is prime or composite. You can also click on the button "Server Info" to invoke the Ajax code which shows the local time of the server.

Update 2:   If you add the line var J = jQuery.noConflict(); to the top of the file "pm.js", it will let you change every '$' in the file to 'J'. I usually do that, especially when generating the jQuery/Javascript code directly from the CGI script, as it doesn't force me to escape '$' everywhere.

Here is the CGI (ie. Perl) code "pm.cgi" which runs on the server:

#!/usr/bin/perl -w # # Simple jQuery example to demonstrate: # # CGI (Perl) + HTML + CSS + Javascript/jQuery + Ajax # # 2013-08-21 golux ## ############### ## Libraries ## ############### use strict; use warnings; use CGI qw{ :standard }; use CGI::Carp qw{ fatalsToBrowser }; ################## ## User-defined ## ################## my $jquery = "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min. +js"; my $max = 625; my $ncols = 25; ################## ## Main program ## ################## server_side_ajax(); print_page_header(); print_html_head_section(); print_html_body_section(); ################# ## Subroutines ## ################# sub print_page_header { # Print the HTML header (don't forget TWO newlines!) print "Content-type: text/html\n\n"; } sub print_html_head_section { # Include stylesheet 'pm.css', jQuery library, # and javascript 'pm.js' in the <head> of the HTML. ## print "<head>\n"; print "<link rel='stylesheet' type='text/css' href='pm.css'>\n"; print "<script src='$jquery' type='text/javascript'></script>\n"; print "<script src='pm.js' type='text/javascript'></script>\n"; print "</head>\n"; } sub print_html_body_section { # Create HTML body and show values from 1 - $max ($ncols per row) print "<body>\n"; print "<center>\n"; print "<h1>Click any number to see its factors</h1>\n"; print qq{ <input type="button" value="Server info" onclick="ajax_info()" +> <span id="info"></span><hr> }; print qq{<div id="result"></div><br>\n}; print "<table width='50%'>"; for (my $i = 0; $i < $max; $i++) { (0 == $i % $ncols) and print "<tr>\n"; my $num = $i + 1; my $onclick = qq{onclick="show_factors($num)"}; print qq{<td id="N$num" class="normal data" $onclick>$num\n}; } print "</table>"; print "</center>\n"; print "</body>\n"; } sub server_side_ajax { my $mode = param('mode') || ""; ($mode eq 'info') or return; # If we get here, it's because we were called with 'mode=info' # in the HTML request (via the ajax function 'ajax_info()'). ## print "Content-type: text/html\n\n"; # Never forget the header! my $ltime = localtime(); print "Server local time is $ltime"; exit; }

This is the CSS stylesheet "pm.css":

body { background: #ffcfff; font-family: arial; } .data { border: 1px solid black; text-align: center; cursor: pointer; min-width: 32px; min-height: 32px; width: 32px; height: 32px; } .normal { background: lightgreen; } .composite { background: #3366ff; } .prime { background: deeppink; } .factor { background: yellow; }

And this is the javascript code "pm.js" which the server downloads to the client (in the HTML page created by "pm.cgi"):
// // Note: adding the line: // // var J = jQuery.noConflict(); // // lets you change '$' everywhere in this file to 'J'. // function show_factors(num) { // First reset all data $('.data').each(function() { $("#"+this.id).attr('class', 'normal data'); }); // Then find and show all the factors var nfactors = 0; var factors = ""; for (var i = 1; i < num; i++) { if (0 == num % i) { ++nfactors; if (factors) factors += ", "; factors += i; var tag = "#N" + i; $(tag).removeClass('normal').addClass('factor'); } } // Highlight chosen square with class 'prime' or 'composite' var b_prime = (nfactors > 1)? false: true; var newclass = (b_prime)? 'prime': 'composite'; var tag = "#N" + num; $(tag).removeClass('normal').addClass(newclass); // Finally, explain the results var text; if (1 == num) { text = "The number 1 is neither prime nor composite"; } else if (b_prime) { text = "The number " + num + " is prime"; text += " (Its only factors are 1 and itself)."; } else { text = "The number " + num + " is composite."; text += " It has " + nfactors + " factors besides itself: " + + factors; } $('#result').html(text); } function ajax_info() { $.ajax({ url: "pm.cgi", cache: false, dataType: "text", data: { mode: 'info' }, success: function(result) { ajax_info_result(result); } }); } function ajax_info_result(result) { var text = "The server says: <b>" + result + "</b>"; $('#info').html(text); }
say  substr+lc crypt(qw $i3 SI$),4,5

Comment on Simple example of CGI (Perl) + HTML + CSS + Javascript/jQuery + Ajax
Select or Download Code
Re: Simple example of CGI (Perl) + HTML + CSS + Javascript/jQuery + Ajax
by rnewsham (Hermit) on Aug 25, 2013 at 08:31 UTC

    I like your example but I think some people may get a little confused by the amount it does. I have taken your idea and created a very basic example. It does not do anything as interesting but it does show how a simple jquery ajax call can be used with perl.

    The example consists of two files the cgi and the template. The template contains a jquery function to post a number to the cgi. The cgi will return a json formatted result which jquery will place in a div.

    simple.cgi

    #!/usr/bin/perl use strict; use warnings; use CGI; use JSON; use Template; my $q = new CGI; my %data; if ( my $number = $q->param('number') ) { if ( $number =~ /^\d+$/ ) { $data{result} = $number % 2 ? 'odd' : 'even'; } else { $data{result} = 'Not a number'; } print $q->header('application/json'); print to_json(\%data); exit; } $data{title} = 'Simple jquery example'; print $q->header( -charset=>'utf-8' ); my $tt = Template->new; $tt->process('simple.tmpl', \%data);

    simple.tmpl

    <!DOCTYPE html> <html> <head> <title>[% title %]</title> <meta charset='utf-8' /> <script type='text/javascript' src='//ajax.googleapis.com/ajax +/libs/jquery/1.10.2/jquery.min.js'></script> </head> <body> <div id='result'></div> Enter number: <input type='text' id='number' /> <button onclick='test_number();'>Test</button> <script> function test_number() { $.ajax({ type: 'POST', url: 'simple.cgi', data: { 'number': $('#number').val() }, }).done(function( msg ) { $('#result').html( + msg.result ); }); } </script> </body> </html>
      Gotta say, I'm not impressed.

      The point of my example was to illustrate Perl and jQuery. To that end, I'm intentionally showing how much you can do in a small number of lines of code. I realize JSON and the Template Toolkit are very useful -- I frequently use both for adding features to Bugzilla at work -- but there wasn't any need for them in an example specifically limited to Perl and jQuery.

      On top of that, by "dumbing down" the functionality, your example does nothing more than calculate whether a number is even or odd. You can do that on the client in javascript; why would you need jQuery, Ajax, JSON, the Template Toolkit and a call to the server for that?!

      say  substr+lc crypt(qw $i3 SI$),4,5

        I appreciate the point of your example, and it does do what you intended. However I believe its complexity could be daunting for a newcomer to perl, jquery or ajax in general. In my experience people who ask the question of how do I use X with Y want to see the most basic example of the core workings that they can apply to their own problem. They do not want to have to take a working example of hundreds of lines and have to strip out what is irrelevant to them.

        My example was not intended to do anything useful, interesting or impressive. It is purely a concise example of a jquery perl work flow. It was designed to be simple with only two files involved the one with the jquery and the one with the perl. That way the work flow can be easily tracked. As a demonstration to someone with limited prior knowledge of how jquery and perl can be used together, I do not believe that it needs to do any more.

        Template Toolkit was used as it keeps the html out of the perl and allows for the html output to be understood without executing any perl. JSON was used because I have found that this is by far the simplest way for perl to pass data back to jquery.

        Maybe you want to get rid of  qw{ :standard };
      Hi I like this example, is there any way to have both the HTML and cgi code in one file. For example have the script generate both the html and ajax call? I tried doing it but got stuck when I try but got stuck at the example where it outputs the data, $tt->process('simple.tmpl', \%data); I tried replacing simple.tmpl with simple.cgi but it did not work. thanks.
      +1 to renewsham. The simple example is much easier to read and use. Plus, you adroitly used Template to ease reading of the example, and demonstrate a better way to write HTML.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: CUFP [id://1050387]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (9)
As of 2014-10-24 15:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (132 votes), past polls