http://qs321.pair.com?node_id=1050387

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

Replies are listed 'Best First'.
Re: Simple example of CGI (Perl) + HTML + CSS + Javascript/jQuery + Ajax
by rnewsham (Curate) 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>
      +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.
      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.
Re: Simple example of CGI (Perl) + HTML + CSS + Javascript/jQuery + Ajax
by jeffa (Bishop) on May 20, 2015 at 22:18 UTC