While working on the next-generation version of the Sermon Browser plugin for WordPress, I had a need for a file picker that would allow the site administrator to choose a file from a folder on the server.  I found a great AJAX-enabled jQuery plugin named jQuery File Tree written by Cory S.N. LaViska, but it wasn’t really designed to work with WordPress.  With a few simple changes, I was able to integrate it into my WordPress plugin.  In this post, I’d like to share what I had to do to get it working.

jQuery File Tree has three parts:

  1. jqueryFileTree.js contains the jQuery code that issues the AJAX request for the list of files and displays the file tree.  It needs some modification to work with WordPress.
  2. jqueryFileTree.css contains the styles needed to generate the file tree display.
  3. A connector script is needed to respond to the AJAX request and look up the files on the server.  jQuery File Tree comes with a PHP connector script, but the code needs to be modified slightly and included in your plugin code to work properly.

Modify jQueryFileTree.js

First, we need to modify jQueryFileTree.js.  We need the script to accept two additional parameters: ‘_wpnonce’ and ‘action’.  These parameters will be passed on to the WordPress AJAX handler.  You can view and download my modified jQueryFileTree.js file here.

Add jQuery File Tree files

First,we need to add the jQuery File Tree files to your plugin folder.  I put the files in a ‘lib/jqueryFileTree/’ subfolder, but if you want to put the files in a different folder, you’ll need to adjust the code in the next section to point to the correct area.  You need jqueryFileTree.js, jqueryFileTree.css, and you need the images folder with all the contents.

Next, we need to enqueue the .js and .css files so they get included.  Add the following lines to your plugin:

wp_enqueue_script('myplugin_jqueryFileTree_js', plugins_url('lib/jqueryFileTree/jqueryFileTree.js', __FILE__), array('jquery'), '1.01.01');
wp_enqueue_style('myplugin_jqueryFileTree_css', plugins_url('lib/jqueryFileTree/jqueryFileTree.css', __FILE__), false, '1.01.01');

The first parameter in each line is a unique handle for each script.  The name is not important.  The path to the files is the relative path to the jQuery File Tree files from your plugin PHP file.

In my plugin, jQuery File Tree is only needed on a specific admin page, so I wrapped these lines inside an if statement, so that they only get included if the user is on that admin page.

Add WordPress AJAX action

WordPress has a built-in AJAX handling system that we want to tie into.  To do this, we need to add the following line to your plugin:

add_action ('wp_ajax_myplugin_jqueryFileTree', 'myplugin_ajax_jqueryFileTree_function');

This line has two parameters.  ‘wp_ajax_myplugin_jqueryFileTree’ is the Action Hook.  This name needs to begin with ‘wp_ajax_’.  The second parameter is the callback function.  We will define this function next.

Again, it is good practice to only include code in the context that you need it, so in my plugin, the line has been wrapped around an if statement that only runs it if the user is on the appropriate admin page.

Add AJAX handler callback function

This function will take the place of the connector script that normally works with jQuery File Tree.  Add the following function to your plugin:

/**
* Handles the myplugin_jqueryFileTree AJAX request, the connector script for jqueryFileTree
*/
function myplugin_ajax_jqueryFileTree_function() {
    if (!check_ajax_referer ("myplugin_jqueryFileTree_nonce"))
        die ('Suspicious behaviour blocked');
    $root = '';
    $_POST['dir'] = urldecode($_POST['dir']);
    if( file_exists($root . $_POST['dir']) ) {
        $files = scandir($root . $_POST['dir']);
        natcasesort($files);
        if( count($files) > 2 ) { /* The 2 accounts for . and .. */
            echo "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
            // All dirs
            foreach( $files as $file ) {
                if( file_exists($root . $_POST['dir'] . $file) && $file != '.' && $file != '..' && is_dir($root . $_POST['dir'] . $file) ) {
                    echo "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($_POST['dir'] . $file) . "/\">" . htmlentities($file) . "</a></li>";
                }
            }
            // All files
            foreach( $files as $file ) {
                if( file_exists($root . $_POST['dir'] . $file) && $file != '.' && $file != '..' && !is_dir($root . $_POST['dir'] . $file) ) {
                    $ext = preg_replace('/^.*\./', '', $file);
                    echo "<li class=\"file ext_$ext\"><a href=\"#\" rel=\"" . htmlentities($_POST['dir'] . $file) . "\">" . htmlentities($file) . "</a></li>";
                }
            }
            echo "</ul>";
        }
    }
    die();
}

This function is very similar to the PHP connector script included with jQuery File Tree, with a few changes:

  • The ‘check_ajax_referer’ line (line 5) is a WordPress function designed as a security measure to prevent hacking.  More on this in the next section.
  • $root can be defined (line 7) with an absolute path to any folder you want as your base folder.  The user won’t be able to use jQuery File Tree to see anything above this root path.
  • The die function is called at the end, because all WordPress AJAX handler functions need to end with this call.

Add the File Tree to your page

Finally, we are ready to add the file tree to our page.  To do this, we add an empty div to our page:

<div id='myplugin_file_tree'></div>

Next, we add some jQuery script to the page to call our code:

//Add the File Tree
$('#myplugin_file_tree').fileTree({
    root: '',
    script: ajaxurl,
    _wpnonce: '<?php echo wp_create_nonce('myplugin_jqueryFileTree_nonce') ?>',
    action: 'myplugin_jqueryFileTree',
    multiFolder: false
    },
    function(file) {
        alert(file);
    }
);

Comparing this to the example jQuery call on the original post, I’ve added a few things:

  • ajaxurl is a standard WordPress-defined constant that contains the path to the WordPress AJAX handler.
  • action is the name of the Action Hook that we defined above in the add_action line.  Remove the “wp_ajax_” prefix for use here.
  • _wpnonce is a nonce that is inspected by our AJAX handling callback function.  You’ll see that I’m calling a PHP function here.  This is only possible if you have included this jQuery code in a PHP file.  If this is not possible, you can remove the _wpnonce line here.  You’ll also need to remove the nonce check in your AJAX handling callback, which is less secure for your site.
  • The function that is defined at the end is what happens after the user chooses a file.  In this case, all that happens is an alert pops up with the filename.  After you get jQuery File Tree working, you’ll need to replace this function with something useful.  You can either call another JavaScript function here or you could make another AJAX request to WordPress.

I hope this was helpful to someone.  Feel free to leave a comment if you have any questions or improvements.