Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Mojolicious refresh

by Anonymous Monk
on Mar 18, 2020 at 01:01 UTC ( #11114408=perlquestion: print w/replies, xml ) Need Help??

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

How does one make a Mojolicious app periodically update the contents of a webpage? Is there more than one way to do it? I'm looking for as smooth a transition as possible, of text or an image (my ultimate goal). Here's an SSCCE:
#!/usr/bin/perl use strict; use warnings; use Mojolicious::Lite; use Time::HiRes 'time'; get '/' => sub { my $c = shift; my $t = timer(); $c->render(text => $t) }; app->start; sub timer { return time }
Thanks for your guidance.

Replies are listed 'Best First'.
Re: Mojolicious refresh
by haukex (Bishop) on Mar 18, 2020 at 07:45 UTC

    <update> Your Mother beat me to it by seconds :-) </update>

    IMHO, the best way nowadays is JavaScript:

    #!/usr/bin/env perl use Mojolicious::Lite -signatures; get '/' => sub ($c) { $c->render(template => 'index'); } => 'index'; get '/dynupd' => sub ($c) { $c->render(json => { time => time }); } => 'dynupd'; app->start; __DATA__ @@ layouts/main.html.ep <!DOCTYPE html> <html> <head><title><%= title %></title></head> <body> %= content </body> </html> @@ index.html.ep % layout 'main', title => 'Hello, World!'; <div>Hello, World!</div> <div id="dyn_upd">Fetching, please wait...</div> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script> <script> function updateDynamic() { $.ajax({ url: '<%= url_for('dynupd') %>', timeout: 1000 }) .done( function( data ) { $('#dyn_upd').text(data.time); }) .fail( function( jqXHR, textStatus, errorThrown ) { $('#dyn_upd').text("Update Failed: "+textStatus +" / "+jqXHR.status+" "+errorThrown); }); } $(function () { updateDynamic(); setInterval(updateDynamic, 2000); }); </script>

      Yeah, but your error handling is better. :P

Re: Mojolicious refresh
by LanX (Sage) on Mar 18, 2020 at 01:18 UTC
    Yes there are many different approaches

    That's a basic HTML question, which is agnostic of the underlying web framework.

    Not sure if mojo offers specialized methods for all.

    The classic approach is to reload the page.

    Either by specifying

    • using an Ajax XMLhttprequest will reduce the necessary bandwidth and let it look more smooth if only small parts of the page are refreshed. (Needs JS again + DOM manipulation)
    • I'm aware that mojo supports web sockets to actively push new content to the webpage. Never used it, but it allows to better control the refresh from the server side.

    Timtowtdi

    I hope this overview will give you a starters to specify what you need and want.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      A more advanced technique consists in a client side framework like Angular where the page's content depends on some JS variables and is automatically refreshed whenever a variable's value changes. These changes may be pushed to the client via web sockets. This way page updates are minimal, smooth and happen immediately.

      Implementing this using Mojolicious::Lite on the server side is pretty easy. The real work has to be done on the client.

      Greetings,
      -jo

      $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
        > A more advanced technique consists in a client side framework like Angular

        I always thought that the benefit of Web sockets was that the action can be initiated from the server.

        I don't see the big difference to the AJAX/DOM point I listed.

        Or what's the advancement here?

        Speed?

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re: Mojolicious refresh
by Anonymous Monk on Mar 18, 2020 at 03:11 UTC
Re: Mojolicious refresh
by Anonymous Monk on Mar 18, 2020 at 06:54 UTC
    Thank you LanX and Anon. I thought meta refresh was a blunt approach. I also figured Mojo might provide an HTTP solution using NPH or something like the venerable CGI::Simple (websockets I guess). Anyway I figured out how to do the job, but will research your other suggestions for a more elegant solution:
    #!/usr/bin/perl use strict; use warnings; use Mojolicious::Lite; use Time::HiRes 'time'; get '/' => sub { my $c = shift; $c->clock; $c->render('index') }; helper clock => sub { my $c = shift; $c->stash(clock => time) }; app->start; __DATA__ @@ index.html.ep <!DOCTYPE html> <html> <head> <META http-equiv="refresh" content="1;<%=url_for('/')->to_abs%>"> <title>MojoClock</title></head> <body> <h1><%= $clock %></h1> </body> </html>

      You’re killing me, Smalls.

      #!/usr/bin/perl use strict; use warnings; use Mojolicious::Lite; get "/" => sub { my $c = shift; $c->clock; $c->render("index"); }; helper clock => sub { my $clock = { clock => time }; +shift->stash( $clock ); $clock; }; get "/clock" => sub { my $c = shift; $c->render(json => $c->clock); }; app->start; __DATA__ @@ index.html.ep <!DOCTYPE html> <html> <head> <title>MojoClock</title> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJ +o=" crossorigin="anonymous"></script> <style>* { font-family:"helvetica neue", helvetica }</style> </head> <body> <h1 class="clock"> <%= $clock %> </h1> <script type="text/javascript"> function clockMe() { $clock = $(".clock"); $.ajax({ type: "GET" ,url: "clock" ,success: function(json){ $clock.fadeOut(10,function(){ $clock.text(json.clock +).fadeIn() }); } ,error: function(req,msg){ alert("Oh, noes! Errerz!!!"); } }); }; setInterval(clockMe, 1000) </script> </body> </html>

      I consider meta refresh an unambiguously worst UX practice except in the rare case of needing to do it *once* in a situation you want to present a message to the user before a real redirect or ensure a session timeout or something where JS is disabled… or pump up your page view stats for advertisers like certain broadsheet hacks who shall remain unnamed. :P

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2022-05-21 16:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Do you prefer to work remotely?



    Results (76 votes). Check out past polls.

    Notices?