1

I am trying to create a webpage that displays a file tree. I chose to use the jqueryFileTree from this website: http://www.abeautifulsite.net/blog/2008/03/jquery-file-tree/

Eventually, I will be hooking this tree up to a server. For now, however, I am trying to get it working on my Windows machine running a Node.js localhost.

As this jquery plugin requires the use a of a connector script (to be able to pull directory information), I have chosen to use their included python connector script, jqueryFileTree.py.

My issue is that the localhost is telling me that the python script cannot be found (error 404). However, I know that I have provided the correct path for the file because when I enter the url into a browser, I am able to download the script. This behavior is throwing me off because it is telling me one thing but doing another.

Below is all of my relevant code and information.

Directory structure:

|-public (localhost)
 |-connectors
  |-jqueryFileTree.py

Creation of the jqueryFileTree object:

$(window).load(
function()
{
    $('#fileTree').fileTree({
        root: '/',
        script: 'connectors/jqueryFileTree.py',
        expandSpeed: 500,
        collapseSpeed: 500,
        multiFolder: true
    },
    function(file)
    {
        alert(file);
    });
});

Here's my error message:

Failed to load resource: the server responded with a status of 404 (Not Found): http://localhost:3700/connectors/jqueryFileTree.py

Below is the code for the jqueryFileTree and connector script. I did not write the code. It comes as is when you download the plugin from the website I mentioned earlier.

Plugin code:

// jQuery File Tree Plugin
//
// Version 1.01
//
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 24 March 2008
//
// Visit http://abeautifulsite.net/notebook.php?article=58 for more information
//
// Usage: $('.fileTreeDemo').fileTree( options, callback )
//
// Options:  root           - root folder to display; default = /
//           script         - location of the serverside AJAX file to use; default = jqueryFileTree.php
//           folderEvent    - event to trigger expand/collapse; default = click
//           expandSpeed    - default = 500 (ms); use -1 for no animation
//           collapseSpeed  - default = 500 (ms); use -1 for no animation
//           expandEasing   - easing function to use on expand (optional)
//           collapseEasing - easing function to use on collapse (optional)
//           multiFolder    - whether or not to limit the browser to one subfolder at a time
//           loadMessage    - Message to display while initial tree loads (can be HTML)
//
// History:
//
// 1.01 - updated to work with foreign characters in directory/file names (12 April 2008)
// 1.00 - released (24 March 2008)
//
// TERMS OF USE
//
// This plugin is dual-licensed under the GNU General Public License and the MIT License and
// is copyright 2008 A Beautiful Site, LLC.
//
if(jQuery) (function($){

    $.extend($.fn, {
        fileTree: function(o, h) {
            // Defaults
            if( !o ) var o = {};
            if( o.root == undefined ) o.root = '/';
            if( o.script == undefined ) o.script = 'jqueryFileTree.py';
            if( o.folderEvent == undefined ) o.folderEvent = 'click';
            if( o.expandSpeed == undefined ) o.expandSpeed= 500;
            if( o.collapseSpeed == undefined ) o.collapseSpeed= 500;
            if( o.expandEasing == undefined ) o.expandEasing = null;
            if( o.collapseEasing == undefined ) o.collapseEasing = null;
            if( o.multiFolder == undefined ) o.multiFolder = true;
            if( o.loadMessage == undefined ) o.loadMessage = 'Loading...';

            $(this).each( function() {

                function showTree(c, t) {
                    $(c).addClass('wait');
                    $(".jqueryFileTree.start").remove();
                    $.post(o.script, { dir: t }, function(data) {
                        $(c).find('.start').html('');
                        $(c).removeClass('wait').append(data);
                        if( o.root == t ) $(c).find('UL:hidden').show(); else $(c).find('UL:hidden').slideDown({ duration: o.expandSpeed, easing: o.expandEasing });
                        bindTree(c);
                    });
                }

                function bindTree(t) {
                    $(t).find('LI A').bind(o.folderEvent, function() {
                        if( $(this).parent().hasClass('directory') ) {
                            if( $(this).parent().hasClass('collapsed') ) {
                                // Expand
                                if( !o.multiFolder ) {
                                    $(this).parent().parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
                                    $(this).parent().parent().find('LI.directory').removeClass('expanded').addClass('collapsed');
                                }
                                $(this).parent().find('UL').remove(); // cleanup
                                showTree( $(this).parent(), escape($(this).attr('rel').match( /.*\// )) );
                                $(this).parent().removeClass('collapsed').addClass('expanded');
                            } else {
                                // Collapse
                                $(this).parent().find('UL').slideUp({ duration: o.collapseSpeed, easing: o.collapseEasing });
                                $(this).parent().removeClass('expanded').addClass('collapsed');
                            }
                        } else {
                            h($(this).attr('rel'));
                        }
                        return false;
                    });
                    // Prevent A from triggering the # on non-click events
                    if( o.folderEvent.toLowerCase != 'click' ) $(t).find('LI A').bind('click', function() { return false; });
                }
                // Loading message
                $(this).html('<ul class="jqueryFileTree start"><li class="wait">' + o.loadMessage + '<li></ul>');
                // Get the initial file list
                showTree( $(this), escape(o.root) );
            });
        }
    });

})(jQuery);

Connector script code:

#
# jQuery File Tree
# Python/Django connector script
# By Martin Skou
#
import os
import urllib

def dirlist(request):
   r=['<ul class="jqueryFileTree" style="display: none;">']
   try:
       r=['<ul class="jqueryFileTree" style="display: none;">']
       d=urllib.unquote(request.POST.get('dir','c:\\temp'))
       for f in os.listdir(d):
           ff=os.path.join(d,f)
           if os.path.isdir(ff):
               r.append('<li class="directory collapsed"><a href="#" rel="%s/">%s</a></li>' % (ff,f))
           else:
               e=os.path.splitext(f)[1][1:] # get .ext and remove dot
               r.append('<li class="file ext_%s"><a href="#" rel="%s">%s</a></li>' % (e,ff,f))
       r.append('</ul>')
   except Exception,e:
       r.append('Could not load directory: %s' % str(e))
   r.append('</ul>')
   return HttpResponse(''.join(r))

I may have posted more than what is needed. I wanted to be thorough rather than have to reply and edit with more information. That being said, please feel free to ask for more information.

I appreciate any help!

Lethal Left Eye
  • 368
  • 2
  • 9
  • 17

3 Answers3

0

Try one thing: Instead using this path 'connectors/jqueryFileTree.py' try absolute url that you used in browser to download the script.

andmart
  • 554
  • 2
  • 10
  • I thought that might work as well. I had previously tried that and I received the same error. Honestly, I've tried moving the script all over my file hierarchy and I have also tried playing with so many variations of the path in the JavaScript. I can't seem to have any luck with this. – Lethal Left Eye May 12 '14 at 18:34
0

please excuse me for not checking through your script and for a late response. However, I had the same problem and believe solved it by following the paths described in: http://pastebin.com/kVkTssdG and http://www.abeautifulsite.net/jquery-file-tree/

in details: 1) I created a new folder named 'jQFTree' in my project's 'node_modules' sub folder. 2) I included rows:

var jQFTree=require('jQFTree');

and

app.post('/FileTree', jQFTree.handlePost);

to my app.js file in node.js. 3) Added to my form's html:

div(id="FileTree" class="fTre")

and script respectively:

var orig = window.location.origin + '/FileTree';
var servDir='Mats';//or Carps or Rugs
$("#FileTree").fileTree({
    root: servDir,
    script: orig
},
followed by callback function.

4) The previously created jQFTree folder contains only one file named 'index.js' with following javascript code:

//my Node.js module for jQuery File Tree
var path = require('path'); 
var fs = require('fs');
var util = require('util');
var stringHeader = "<ul class='jqueryFileTree' style='display: none;'>";
var stringFooter = "</ul>";
// arguments: path, directory name
var formatDirectory = 
    "<li class='directory collapsed'><a href='#' rel='%s/'>%s</a><li>";
// arguments: extension, path, filename
var formatFile = "<li class='file ext_%s'><a href='#' rel='%s'>%s</a></li>";
var createStatCallback = (function (res, path, fileName, isLast) {
    return function (err, stats) {
        if (stats.isDirectory()) {
            res.write(util.format(formatDirectory, path, fileName));
        }
        else {
            var fileExt = fileName.slice(fileName.lastIndexOf('.') + 1);
            res.write(util.format(formatFile, fileExt, path, fileName));
        }
        if (isLast) {
            res.end(stringFooter);
        }
    }
});

exports.handlePost = function (req, res) {
    //for safety; only directory name is available from the browser 
    //through the req.body.dir variable
    //but complete dir path in server is required for dir browsing
    // 'text/html'
    //console.log('Filetree handles post dir: '+ req.body.dir);
    res.writeHead(200, { 'content-type': 'text/plain' });
    res.write(stringHeader);
    // get a list of files
    var seeDir = req.body.dir;
    if (seeDir.indexOf('%5C') > -1 || seeDir.indexOf('%2F') > -1) {
        //directory path was returned as a subfolder from jQuery FileTree using URL encoding
        //decode it first:
        seeDir = decodeURIComponent(seeDir);
        //console.log('seeDir: '+seeDir+' __dirname:'+__dirname);
        if (seeDir.slice(-1) == "/" || seeDir.slice(-1) == "\\") {
            //last char either / (MS-windows) or \ (not MS-windows) is dropped
            seeDir = seeDir.slice(0, seeDir.length - 1)
            if (seeDir.indexOf('/') > -1) {
                seeDir = seeDir + '/';
            }
            else {
                seeDir = seeDir + '\\';
            }
        }
    }
    if (req.body.dir == 'Mats' || req.body.dir == 'Carps' || req.body.dir == 'Rugs') {
        //restricted to three sub dirs in server directory: public/MatsCarpsRugs/
        //console.log('.=%s', path.resolve('.'));
        //gives path to the above app.js calling this module (=as wanted)
        //combine path to requested directory:
        seeDir = path.join(path.resolve('.'), 'public', 'MatsCarpsRugs', req.body.dir);
        if (seeDir.indexOf('/')>-1){
            //web-browser not in ms-windows filesystem
            seeDir=seeDir+'/';
        }
        else{
            //web-browser is in ms-windows filesystem
            seeDir=seeDir+'\\';
        }
        //console.log('seeDir now: '+seeDir);
    }
    fs.readdir(seeDir, function (err, files) {
        var fileName = '';
        var path = '';
        var statCallback;
        if (files.length === 0) {
            path = util.format('%s%s', seeDir, fileName);
            statCallback = createStatCallback(res, path, fileName, true);
            fs.stat(path, statCallback);
            }
        for (var i = 0; i < files.length; i++) {
            fileName = files[i];
            path = util.format('%s%s', seeDir, fileName);
            var isLast = (i === (files.length - 1));
            statCallback = createStatCallback(res, path, fileName, isLast);
            fs.stat(path, statCallback);

        }
    });
}

I hope this helps you or someone else to a solution

wiljo
  • 1
0

I think your problem is with :

script: 'connectors/jqueryFileTree.py',

Your javascript is executed on the frontend (user browser) and can't see python files (on the server).

Instead, you should put the url at which the Django view is available. Check Django url routing mechanism (https://docs.djangoproject.com/en/1.11/topics/http/urls/) to find the url associated with your view ("dirlist").

orzel
  • 322
  • 2
  • 7