Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

jquery scripts

by hermit23 (Initiate)
on Oct 02, 2015 at 09:17 UTC ( [id://1143651]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Brothers
I have a .cgi script which outputs an HTML page.
The HTML page includes a short jquery script which draws a graph on the HTML page.
The critical line in the jquery script is:
<script> var data=[[0,170],[1,27],[2,3],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0],[9,0],[10,0]]; where the bits in square brackets are positions and data.
This works fine as long as the data line is hard coded, but I normally don't know what the data is going to be till the .cgi script has run.
Ideally, I'd like to write a line like this: <script> var data=$mydata where $mydata is a string prepared by the cgi script. However, jquery seems not to like this. I think this, is because it interprets the $ as a reference to itself.
Does anyone have any suggestions how to solve this?The general question is how do I move smoothly between perl and jquery?

Replies are listed 'Best First'.
Re: jquery scripts
by Corion (Patriarch) on Oct 02, 2015 at 09:25 UTC

    In your templating system, have the positions interpolate as a string instead of using a literal variable $mydata. If you can show us a (tiny) example script that does what you describe, we can likely point out better what you need to change.

    Basically, I imagine your script being:

    #!perl -w use strict; my $mydata = "[[0,170],[1,27],[2,3],[3,0],[4,0],[5,0],[6,0],[7,0],[8,0 +],[9,0],[10,0]]"; print <<'HTML'; <html> <head> <script src="jquery.js"></script> <script> var data=$mydata; </script> </head> <body> <h1>Hello</h1> </body> HTML

    In that case, the easiest approach would be to change the interpolation to double quotes.

    The best approach is to use a proper templating system like HTML::Template or Template::Toolkit.

      Or, if your data are stored in an array in Perl, use a JSON module to convert them to JSON:
      my @mydata = map [ $i++, $_ ], 170, 27, 3, (0) x 8; my $json = to_json(\@mydata); print << "HTML"; <html> <head> <script src="jquery.js"></script> <script> var data=$json; </script> </head> <body> <h1>Hello</h1> </body> HTML
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: jquery scripts
by golux (Chaplain) on Oct 02, 2015 at 17:24 UTC
    Hi hermit23,

    Here's a short but complete example of a self-contained CGI script that will query the server and display the data points it gets back.

    It makes use of Javascript/jQuery, and calls back to the server once, using Ajax to get the data points, which it then displays to page. You can, of course, modify the subroutine "server_side_ajax()" to have more meaningful points than the random ones my script generates. Plus, you can do something more fun with the points in the javascript function "done_query" than just print them to the page.

    Of course, let us know if you have any questions.

    Update:  And if you were only asking about how not to use '$', pay special attention to the line "var J = jQuery.noConflict();" which enables the magic letting you refer to jQuery with 'J' (or whatever else you like) instead of '$'.

    #!/usr/bin/perl ############### ## Libraries ## ############### use strict; use warnings; use JSON; ################## ## User-defined ## ################## # This is a link to Google's publicly-available jQuery library my $jquery = "ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js +"; ################## ## Main Program ## ################## my $this_prog = $ENV{'REQUEST_URI'}; my $h_param = cgi_params(); if (exists $h_param->{'ajax'}) { # If 'ajax' was sent in the URL, it's the client communicating # with the Server via Ajax. See function ajax_query_server(), # which initiates this. You could also put '?ajax' in the URL # query to see the data results directly. ## server_side_ajax(); } else { # If the URL doesn't contain the key 'ajax', we display the HTML # page normally. ## print "Content-type: text/html\n\n"; print_javascript(); print_html_page(); } ################# ## Subroutines ## ################# sub cgi_params { my $query = $ENV{'QUERY_STRING'} || 0; $query or return { }; my $h_params = { }; foreach my $key (split('&', $query)) { my $val = ($key =~ s/=(.*)$//)? $1: undef; $h_params->{$key} = $val; } return $h_params; } sub server_side_ajax { # Calculate data somehow my $a_data = [ ]; my $npoints = 16; # For the sake of example, just randomize it for now for (my $i = 0; $i < $npoints; $i++) { my ($x, $y) = (int(rand(100)), int(rand(100))); push @$a_data, [ $x, $y ]; } my $h_json = { 'data' => $a_data }; # Print the JSON header and data print "Content-type: application/json\n\n"; print to_json($h_json); exit; } sub print_javascript { # Send the jQuery/Javascript code to the browser print qq{ <head> <script src="https://$jquery"></script> <script> // I prefer 'J' to '$' for jQuery within Perl var J = jQuery.noConflict(); J(function() { ajax_query_server() }); // Here the browser talks to the server function ajax_query_server() { J.ajax({ url: "$this_prog", dataType: 'json', data: { ajax: 1 }, success: function(json) { done_query(json); } }); } // Here the browser gets data back from the server function done_query(json) { var a_points = json['data']; for (var i = 0; i < a_points.length; i++) { var x = a_points[i][0]; var y = a_points[i][1]; var text = "Point "+(i+1)+": ("+x+","+y+")\\n"; J('#data').append(text); } } </script> </head> }; } sub print_html_page { # Here's where the HTML body gets printed print qq{ <body style="background:peachpuff"> <h3> Ajax Data Example </h3> <pre id="data"></pre> </body> }; }

    say  substr+lc crypt(qw $i3 SI$),4,5
Re: jquery scripts
by hermit23 (Initiate) on Oct 05, 2015 at 07:49 UTC

    dear brothers

    Thank you for your helpful answers to my question about jquery scripts

    My solution to this problem is shown in the short cgi program below. However, I can't help feeling that this solution is not just clunky, but probably heretical. Can you show me the way to do it properly?

    #!/usr/bin/perl -w use CGI ':standard'; use CGI::Carp(fatalsToBrowser); print "Content-type: text/html\n\n"; ###data in Json format is prepared by the cgi script and added to the +first line of the script my $dline="<script> var data=[[1,13],[2,25],[3,17],[4,3],[5,10]];"; ###$pt2 defines what the graph output looks like. my $pt2='var dataset = [{data: data}]; var options = {series: {lines: { show: true },points: {radius +: 3,show: true} } }; $(document).ready(function (){$.plot($("#mychart"), dataset, +options);}); </script> '; ###$pscript is a jquery script made up of $dline and $pt2 my $pscript=$dline.$pt2; ##code for HTML output my $htmlHeader=' <!DOCTYPE html PUBLIC> <html> <head> <style> body { background: #99bbee;} #mychart {width:250px;height:300px;background:white;} </style> <script src="jquery-1.11.3.min.js"></script> <script src="jquery.flot.min.js"></script> </head> '; my $body=' <body> <div id="mychart"></div> <p><hr><p> </body> </html> '; ###print the graph print qq($htmlHeader); print qq($body); print qq($pscript);

      The traditional approach is to move the HTML into a templating system instead of several print statements. This allows you to keep your code separate from the presentation part in the template. Depending on your workflow, this makes it possible for people other than you to change the HTML as it is generated.

      For example using Template::Toolkit:

      use strict; use Template; my $json = '[[1,13],[2,25],[3,17],[4,3],[5,10]]'; # or use JSON.pm use CGI ':standard'; use CGI::Carp(fatalsToBrowser); print "Content-type: text/html\n\n"; my $tmpl = Template->new(); $template->process('/home/hermit23/mysite/mytemplate.tt', { json => $json, });

      With the template file /home/hermit23/mysite/mytemplate.tt containing:

      <!DOCTYPE html PUBLIC> <html> <head> <style> body { background: #99bbee;} #mychart {width:250px;height:300px;background:white;} </style> <script src="jquery-1.11.3.min.js"></script> <script src="jquery.flot.min.js"></script> <script> var data= [% json %]; var dataset = [{data: data}]; var options = {series: {lines: { show: true },points: {radius +: 3,show: true} } }; $(document).ready(function (){$.plot($("#mychart"), dataset, +options);}); </script> </head> <body> <div id="mychart"></div> <p><hr><p> </body> </html>

      Note the [% json %], which will get replaced verbatim by the value of the json key in the parameters to ->process(...)

      If you're going to  use CGI ':standard'; then use header() instead of  "Content-type: text/html\n\n";

        Thanks to Corion, Sundialsvc4, Golux and Anonymous monks for their comments on my question about jQuery scripts. Much appreciated. The suggestion to use HTML Templates has been particularly useful.

Re: jquery scripts
by sundialsvc4 (Abbot) on Oct 02, 2015 at 15:49 UTC

    A templating system can be used to construct a Perl-friendly string containing the necessary data ... but also, this is essentially what the JSON format already is.   (Originally, the idea behind JSON was that a JavaScript client could simply eval the string, but those innocent days are gone now.)

    It is impossible for you to refer to a Perl variable, such as $mydata, in the web-page text that you send to the client, because the client has no idea where the web-page came from and has no access at all to the (Perl) software that may have produced it.   Directly or indirectly, it must see a JavaScript statement that it can correctly parse and execute.   The (Perl) server must use the content of its (Perl) variable to generate syntactically-correct and executable JavaScript literals.

      "It is impossible for you to refer to a Perl variable, such as $mydata, in the web-page text that you send to the client, because the client has no idea where the web-page came from and has no access at all to the (Perl) software that may have produced it."

      Proving once again that you have no idea what you're talking about. This is possible and quite common. You replied after other users provided working example code (an alien concept to you I know) that shows how to achieve this.

        in the web-page text that you send to the client

        That having been clarified, I don't think that's what the OP was after anyway, so sundial's answer is still essentially useless.

      dear Brothers,

      Thank you very much for your further comments on using jquery scripts. I shall need to go away and meditate on templating systems.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1143651]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2024-04-23 22:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found