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

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
you can't edit the table directly in the browser

Sure you can, JavaScript makes that possible. <plug type="shameless"> It's even possible to run Perl instead of JS in the browser with WebPerl. </plug>

I also agree with what choroba said about running a webserver locally. You can bind the webserver to your localhost IP, and if you wanted to play it extra safe (like on a multi-user machine), you could use HTTPS and pass an access token.

The following uses Mojolicious to serve up a HTML file, injecting some JavaScript in the process. This JavaScript reacts to clicks on <td> and <th> elements, allowing you to edit their text, and then it immediately POSTs the modified HTML back to the server, which then rewrites the HTML file with what the browser sent. This is admittedly not the most elegant way to go about it, but it should work. Note it only supports one client at a time: although the JS makes sure to only send one request at a time, if two browser windows were to be open and submit requests at the same time, one of the changes would get lost.

#!/usr/bin/env perl use Mojolicious::Lite; use Mojo::Util qw/md5_sum/; use Mojo::DOM; use File::Replace 'replace3'; # Start me with: morbo -l https://localhost:3000/ htmltbledit.pl my $HTMLFILE = '/tmp/test.html'; # ##### For Demo only: Write a default HTML file ##### if (!-e $HTMLFILE) { open my $fh, '>:raw:encoding(UTF-8)', $HTMLFILE or die $!; print $fh <<'END_HTML'; <!DOCTYPE html> <html lang="en"> <head> <title>Hello, World!</title> <style> table { border-collapse: collapse; } table, th, td { border: 1px solid black; } th, td { padding: 0.1em 0.4em; } </style> </head> <body> <table border="1"><tbody> <tr> <th>Foo</th> <th>Bar</th> <th>Quz</th> </tr> <tr> <td>Hello</td> <td>Perl</td> <td>World</td> </tr> <tr> <td>123</td> <td>456</td> <td>789</td> </tr> </tbody></table> </body> </html> END_HTML close $fh; } # ##### Authentication Stuff (optional) ##### my $TOKEN = md5_sum(rand(1e15).time); hook before_server_start => sub { my ($server, $app) = @_; print "URL with Token: ", $_->query(token=>$TOKEN), "\n" for map {Mojo::URL->new($_)} @{$server->listen}; }; under sub { my $c = shift; return 1 if ($c->param('token')//'') eq $TOKEN; $c->render(text => 'Bad token!', status => 403); return undef; }; # ##### JS Code ##### # note: the jQuery JS could also be saved locally my $JSCODE = <<'END_JSCODE'; <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script> $(function() { var requestInProgress = false; $('th, td').click(function() { if (requestInProgress) return; var newtxt = prompt("Foo", $(this).text() ); if ( newtxt==null ) return; $(this).text( newtxt ); requestInProgress = true; $.ajax({ method: 'POST', url: 'save?token=<<<TOKEN>>>', contentType: 'text/plain', data: document.body.innerHTML, dataType: 'text', }) .done(function(data) { console.log(data) }) .fail(function(jqXHR, textStatus, errorThrown) { alert("Error when saving: "+textStatus+"\n"+errorThrown); }) .always(function() { requestInProgress = false; }); }); }); </script> END_JSCODE $JSCODE=~s/<<<TOKEN>>>/$TOKEN/g; # ##### Request Handling Stuff ##### get '/' => sub { # read the file and inject our JavaScript my $c = shift; open my $fh, '<:raw:encoding(UTF-8)', $HTMLFILE or die $!; my $dom = Mojo::DOM->new(do { local $/; <$fh> }); close $fh; $dom->at('head')->append_content($JSCODE); $c->render(text => $dom); }; # NOTE this does not handle multiple requests at once. The JS tries to # prevent this, but it can still happen if there are multiple clients. post '/save' => sub { # rewrite the HTML file my $c = shift; my ($ifh,$ofh,$rpl) = replace3($HTMLFILE, ':raw:encoding(UTF-8)'); my $dom = Mojo::DOM->new(do { local $/; <$ifh> }); # Firefox apparently inserts blank lines here?? Remove them... ( my $newbody = $c->req->body ) =~ s/\n\K\n+\z//; $dom->at('body')->content($newbody); print $ofh $dom->to_string; $rpl->finish; $c->render(text=>'saved successfully'); }; app->start;

Update: Disclaimer: File::Replace is one of my modules too.


In reply to Re: Running local Perl from HTML by haukex
in thread Running local Perl from HTML by Chuma

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (4)
As of 2024-04-25 05:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found