jstree and mojolicious

64 views
Skip to first unread message

Luis Diaz

unread,
Sep 13, 2017, 11:16:59 AM9/13/17
to Mojolicious
Hi!

I've been asked at work to create a website that runs under mojolicious (perl web framework) and it need to have a dynamically created tree, based on some info retrieved from other files.

Right now, I've been able to create the file that holds the json file to populate the tree. ie:

[
{"id": "0", "parent": "#", "text":"0","icon":"folder", "state":{"opened":true, "selected":false}},
{"id": "1", "parent": "0", "text":"1","icon":"file file-txt", "state":{"opened":false, "selected":false}}
]


  I've used the example from jstree that uses a json file and I've created it properly. Now, the issue comes when I use the mojolicious script to create it. 


use strict;
use warnings;
use Mojolicious::Lite;
my $jsonlist;

sub appendLevel(){

    #minimal use: id and parent
    my $id = shift;
    my $parent = shift;
    my $text = shift;
    my $icon = shift;
    my $opened = shift;
    my $selected = shift;

    #data treatment for minimal use
    $text = $id if ! defined $text;
    $icon = "folder" if (! defined $icon and ($parent eq "root" or $parent eq "#"));
    $icon = "file file-txt" if (! defined $icon and ($parent ne "root" or $parent ne "#"));
    $opened = "true" if (! defined $opened and ($parent eq "root" or $parent eq "#")); # if the node is a root node, keep it opened
    $opened = "false" if (! defined $opened and ($parent ne "root" or $parent ne "#")); # if the node is not a root node, keep it closed
    $selected = "false" if ! defined $selected;

    #alias treatment
    $parent = "#" if $parent eq "root";
    $opened = "true" if $parent eq "opened";
    $opened = "false" if $parent eq "closed";
    $selected = "true" if $selected eq "selected";
    $selected = "false" if $selected eq "unselected";

    my $temp = ','."\n".'{"id": "'.$id.'", "parent": "'.$parent.'", "text":"'.$text.'","icon":"'.$icon.'", "state":{"opened":'.$opened.', "selected":'.$selected.'}}';
    if(! defined $jsonlist){
        $temp = substr $temp,1; #remove first colon
        $jsonlist = "[".$temp."]";
    }else{
        substr $jsonlist,-1, 0, $temp;
    }
}

&appendLevel(0,"root");
for my $x (1..10){
    &appendLevel($x,$x-1);
}
&appendLevel("master","#");
for my $x (11..20){
    &appendLevel($x,"master");
}
# &appendLevel("master","root");
# &appendLevel("child","master");
print "\n".$jsonlist."\n";



get '/index' => sub {
    my ( $mojo ) = @_;

    # $mojo -> stash ( 'tagitems' => \@tagitems );
    # $mojo -> stash ('levelsArray' => \@levelsArray);
    $mojo -> render (template => 'index' );
};



app->start('daemon', '-l', 'http://*:8080');

__DATA__
@@index.html.ep
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>jstree basic demos</title>
<style>
     html { margin:0; padding:0; font-size:62.5%; }
     body { max-width:800px; min-width:300px; margin:0 auto; padding:20px 10px; font-size:14px; font-size:1.4em; }
     h1 { font-size:1.8em; }
     .demo { overflow:auto; border:1px solid silver; min-height:100px; }
</style>
<!-- <link rel="stylesheet" href="./../../dist/themes/default/style.min.css" /> -->
</head>
<body>

<h1>AJAX demo</h1>
<div id="ajax" class="demo"></div>

<h1>Callback function data demo</h1>
<div id="clbk" class="demo"></div>

<h1>Interaction and events demo</h1>
<button id="evts_button">select node with id 1</button> <em>either click the button or a node in the tree</em>
<div id="evts" class="demo"></div>

<script src="./../../dist/jstree.min.js"></script> -->
    <!-- 5 include the minified jstree source -->

<script>
// ajax demo
$('#ajax').jstree({
'core' : {
'data' : {
"url" : "./root.json",
"dataType" : "json" // needed only if you do not supply JSON headers
}
}
});

// data from callback
$('#clbk').jstree({
'core' : {
'data' : function (node, cb) {
if(node.id === "#") {
cb([{"text" : "Root", "id" : "1", "children" : true}]);
}
else {
cb(["Child"]);
}
}
}
});

// interaction and events
$('#evts_button').on("click", function () {
var instance = $('#evts').jstree(true);
instance.deselect_all();
instance.select_node('1');
});
$('#evts')
.on("changed.jstree", function (e, data) {
if(data.selected.length) {
alert('The selected node is: ' + data.instance.get_node(data.selected[0]).text);
}
})
.jstree({
'core' : {
'multiple' : false,
'data' : [
{ "text" : "Root node", "children" : [
{ "text" : "Child node 1", "id" : 1 },
{ "text" : "Child node 2" }
]}
]
}
});
</script>
    
</body>
</html>


and the output from the terminal is:

GET "/index"
Routing to a callback
Rendering template "index.html.ep" from DATA section
200 OK (0.005898s, 169.549/s)
GET "/root.json"
Template "not_found.development.html.ep" not found
Template "not_found.html.ep" not found
Rendering cached template "mojo/debug.html.ep"
Rendering cached template "mojo/menubar.html.ep"
404 Not Found (0.011762s, 85.020/s)

So, I know the problem is that mojo is seeing root.json as a url request, so it's trying to reach root.json but as an url, not a file. What can I do to fix it?

Dan Book

unread,
Sep 13, 2017, 11:31:05 AM9/13/17
to mojol...@googlegroups.com
Static files are by default served from the "public" directory, make sure that is where you put your file. https://metacpan.org/pod/Mojolicious::Guides::Tutorial#Static-files

--
You received this message because you are subscribed to the Google Groups "Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious+unsubscribe@googlegroups.com.
To post to this group, send email to mojol...@googlegroups.com.
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

Paolo Saudin

unread,
Sep 14, 2017, 1:29:22 AM9/14/17
to mojol...@googlegroups.com
You need to create a route for the ajax call, i added "root_json", then you probably shuld adjust something in the tree rendering.
Paolo


use strict;
use warnings;
use Mojolicious::Lite;
use Mojo::JSON qw(decode_json encode_json);
get '/root_json' => sub {
    my ( $self ) = @_;

    # render json with message
    $self->render(json => decode_json($jsonlist) );
"url" : "root_json",

Luis Diaz

unread,
Sep 14, 2017, 2:22:22 AM9/14/17
to Mojolicious
Thanks, I think I get it, but root.json is a file in my disk, not a url where the browser needs to go. so, I don't know how is this going to work...  Would you explain it to me please? Never used mojo before and I'm still learning 
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious...@googlegroups.com.

To post to this group, send email to mojol...@googlegroups.com.
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious...@googlegroups.com.

Luis Diaz

unread,
Sep 14, 2017, 2:24:33 AM9/14/17
to Mojolicious
Putting the file under public worked just fine. Thank you so much!
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious...@googlegroups.com.

Luis Diaz

unread,
Sep 14, 2017, 8:58:13 AM9/14/17
to Mojolicious
Hi!

I've another question.. How can I pass data from javascript to perl? I need to do stuff if the user clicks on one node of jstree. I've looked in google but I can't find anything, so I assume I'm not looking for it properly. Will appreciate any help :)


On Wednesday, September 13, 2017 at 5:31:05 PM UTC+2, Dan Book wrote:
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious...@googlegroups.com.

Paolo Saudin

unread,
Sep 14, 2017, 10:20:45 AM9/14/17
to mojol...@googlegroups.com
You need an ajax call, with the URL set to a valid route in the mojolicious application. Search for "mojolicious ajax" and you will find some examples.
Paolo

To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious+unsubscribe@googlegroups.com.

Dominique Dumont

unread,
Sep 15, 2017, 9:07:07 AM9/15/17
to mojol...@googlegroups.com
On Thursday, 14 September 2017 16:20:11 CEST Paolo Saudin wrote:
> You need an ajax call, with the URL set to a valid route in the mojolicious
> application. Search for "mojolicious ajax" and you will find some examples.

Another option which provides a better interactivity is to use websockets.

websockets are used to exchange text (or JSON) messages between the Perl part
and the javascript part. you have to setup on both sides to react to event
(onmessage ...) .

You should search for websocket usage in mojolicious and then websocket in
javascript (like [1])

HTH

[1] https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/
Writing_WebSocket_client_applications

--
https://github.com/dod38fr/ -o- http://search.cpan.org/~ddumont/
http://ddumont.wordpress.com/ -o- irc: dod at irc.debian.org
Message has been deleted

Luis Diaz

unread,
Sep 18, 2017, 4:43:30 AM9/18/17
to Mojolicious
Hi! I was able to do it using a function that is called when a button is pressed:
function exportTree(){
        
var v = $('#levels').jstree(true).get_json('#', {flat:true})
        
var levelsJson = JSON.stringify(v);
        
var xhr = new XMLHttpRequest();
        xhr
.open("POST", "/saveTree", true);
        xhr
.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
        xhr
.send(JSON.stringify(levelsJson));
 
}

And, In perl:

my $json = $self->dumper($self->req->json);
    $json = decode_json $json;


Thanks for all your help
Reply all
Reply to author
Forward
0 new messages