http://www.perlmonks.org?node_id=1051389

Mojolicious comes with jquery2.x, here is how you can use it

docs

code is single file( moquery.pl ), subroutines above , static files and templates in __DATA__; The template language is simple, its regular perl %= time() or  <%= rand(time) %>

#!/usr/bin/perl -- # Automatically use-s strict/warnings/utf8 and feature :5.10 use Mojolicious::Lite; sub mojo_index { my( $self ) = @_; my $time = time; return $self->render( title => "Mojo $time"); } ## delay ajax requests (localhost too fast for disable visualfx) sub sleeper { my( $self ) = @_; if( $self->req->headers->header('x-requested-with') ) { ## "XMLHttpRequest" sleep 1.3; } return; } ## map paths to subroutines ### #~ route named 'index', render's template index.html.ep if html is acc +epted get '/' => \&mojo_index => 'index';;; #~ https://localhost:3000/index #~ https://localhost:3000/index.html #~ https://localhost:3000/index.txt get '/index' => sub { shift->render( title => "Mojo \$time") }; #~ https://localhost:3000/error post '/error' => sub { sleeper(@_); shift->render( data => '<b>this is not json (duh)</b>' ); }; #~ https://localhost:3000/simple any [qw[ GET POST ]] => '/simple' => sub { sleeper(@_); my( $self ) = @_; my $number = $self->param('toy_number') ; my $not_a = scalar( Scalar::Util::looks_like_number( $number ) ) ? 'looks_like_number' : 'DOES NOT looks_like_number' ;;;;;; my $message = $self->render( partial => 1, ## no http number => $number, not_a => $not_a, inline => q{You chose the <b>(<%= $number =%>)</b> and it is <b> <%= $not_a =%> </b>}, ); return $self->render( json => { result => $message } ); }; # Start the Mojolicious command system _aka_ shagadelic('daemon'); app->start; __DATA__ @@ index.txt.ep If you ask for text you will get text its <%= title %> @@ index.html.ep <html> <head> <title><%= title =%></title> <meta charset="utf-8" /></meta> </head> <body> <h1><%= title =%></h1> <div id="toy_toy_toy"> Yecho <input id="toy_number" type="text" value="42" /> <button onclick="test_yecho('<%= url_for 'simple' =%> ');" +> /simple </button> <button onclick="test_yecho('<%= url_for 'error' =%> ');"> + /error </button> <button onclick="test_yecho('/nowhere/nohow/notfound');"> +4our-0h-4our </button> <button onclick="test_yecho('http://example.com/fantasy'); +"> ex </button> <hr /></hr> <div id="toy_status"></div> <div id="toy_result"></div> </div> <hr /></hr> <table> <tr> <% for my $method ( qw[ get post ] ){ =%> <% for my $action ( qw[ simple error ] ){ =%> <td> %= form_for $action => (method => $method) => begin %= hidden_field toy_number => 42 %= submit_button "$method /$action" %= end </td> <% } ## end $action =%> <% } ## end $method =%> </tr> </table> <% for my $page ( qw{ index index.html index.txt /myecho.js } ){ =% +> | <%= link_to( $page => $page ); %> <% } ## end $page =%> %= javascript '/mojo/jquery/jquery.js' %= javascript '/myecho.js' </body> </html> @@ myecho.js var test_yecho = function ( route ) { "use strict"; /*** declare callbacks ***/ var toy_fail = function( data, textStatus, jqXHR ) { $('#toy_result').html( $("<div/>").text( String.concat( "\n", '.fail ' , route, "\n", textStatus, "\n", JSON.stringify(jqXHR, null, 2), "\n", JSON.stringify(data, null, 2), '' ) ).html() ); }; var toy_always = function(){ /*** clear the obsoleted, re-enable disabled ***/ $('#toy_result').html(''); $('#toy_toy_toy *').attr('disabled', null ); }; var toy_done = function( msg ) { try { $('#toy_result').html( '<b>hey toy</b><br>'+ msg.result ); } catch(e){ $('#toy_result').html( "hey exception<br> <pre>" + JSON.stringify( {uhoh:1, message: msg,exception:e}, null,2 ) ); } }; var toy_ajax = { type: 'POST', url: route, data: { 'toy_number': $('#toy_number').val() }, dataType: 'json', /* i want this */ accepts: { 'json': 'application/json' }, /* send Accept: this +*/ }; /*** do that thing, remoting ***/ $('#toy_toy_toy *').attr('disabled', 'disabled' ); $('#toy_result').html('.ajax-ing the ' + route ); $.ajax( toy_ajax ).always( toy_always ).done( toy_done ).fail( toy +_fail ); };

to run this

perl moquery.pl daemon perl moquery.pl daemon --mode=production -l http://localhost:80
and fireup your browser to http://localhost:3000 or http://localhost:80, click the buttons/links and watch the visual changes. Note how get/ing /error is a 404

All praise be to all the innovators and to everybody :) thanks all