jQuery File Tree for WordPress

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']);
        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>";

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
    root: '',
    script: ajaxurl,
    _wpnonce: '<?php echo wp_create_nonce('myplugin_jqueryFileTree_nonce') ?>',
    action: 'myplugin_jqueryFileTree',
    multiFolder: false
    function(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.

Raymie’s Zoo

My 6-year-old son is obsessed with animals.  He loves watching animals, playing with animals, reading books about animals, learning new things about animals, drawing pictures of animals, and teaching other people about animals.  A couple of weeks ago, we had the idea of starting our own website about all the animals we see.  So here it is: Raymie’s Zoo!

Raymie’s Zoo is a blog about animals.  It features lots of pictures, stories, and videos about all the animals he encounters everyday.  So far, we’ve been really good about adding a new post almost everyday.  He’s already got 15 different animals featured on the blog (so far mostly birds and bugs). Here is one of my favorite photos from Raymie’s Zoo.  It is a giant water bug:

If you like what you see, you can subscribe to Raymie’s Zoo on Facebook, Twitter, or even subscribe by e-mail.  So check it out!


Healthy Salad Recipe

We’ve been on the Maker’s Diet for a day now.  Raymie is intrigued: he likes the idea of us eating “superfoods” and not junk foods.  Anyway, Raymie and I had a lot of fun making a salad last night.  He was so excited everytime we found something new to put in it, and he was a little disappointed when I told him we didn’t have anything else to put in it.  Of course, he didn’t actually try the salad when we were done, but I did, and it was very good.  I told him we’d post our recipe on the website so that other people could try it.  So here it is:

Healthy Avocado and Nut Salad

  • Baby romaine
  • Avocado
  • Raw almonds
  • Raw sunflower seeds
  • Raw pumpkin seeds
  • Raisins
  • Carrots
  • Feta cheese
  • Onions
  • Mushrooms

I topped it off with Bragg Ginger & Sesame dressing, and it was very tasty.  If you try it, let Raymie and I know what you think.

The Maker’s Diet

We’re gonna do it.

Because of Leanna’s recent diagnosis of a very mild case of Crohn’s, she and I are going on the Maker’s Diet starting today.  I was on this diet for 6 weeks several years ago with a group of people from my church, and I was pleased with the results at the time.  However, it is fairly restrictive when compared to our standard American diet, and I fell back into the habit of junk food pretty easily.  Now, however, we have a new reason to improve our diet.

The Maker’s Diet is based on the idea that our bodies were designed to eat natural food and have problems eating modern processed food.  Organic fruits, vegetables, meats, and fish are encouraged, and anything artificial is not allowed.  Cane sugar, corn syrup, and artificial sweeteners are not allowed; honey, maple syrup, and stevia are the recommended sweeteners.  Most conventional bread, pasta, and cereal are to be avoided; instead, sprouted and sourdough breads and spelt pasta are encouraged.  The diet also follows the dietary laws found in the Bible, which means that pork and shellfish are not allowed.  There are a lot more details, but those are the main points.

The purpose of the diet is to improve digestive health, and the book specifically claims to help with Crohn’s.  (The author had severe Crohn’s, and was helped by this diet.)  We are hopeful that between the Maker’s Diet, taking fish oil and probiotics (both recommended by both Leanna’s doctor and the Maker’s Diet), and prayer, Leanna’s health will improve quickly.  We’d like to avoid the prescription medication, if possible.  Although weight loss is not a primary objective of this diet, I did find that the last time I was on the diet I lost weight quite easily.  So we’ve got that going for us.  Which is nice. :)  Even if you don’t believe that the Old Testament dietary laws are worth anything and you don’t buy the organic hype, there is little doubt that this diet is much healthier than what we have been eating.

I must admit I’m kind of excited about changing up my diet for a while.  I like trying new things.  Leanna is a little nervous about all this, though.  The hardest part of the diet is the first couple of weeks.  So if you see her, say something encouraging.  She’ll appreciate it!

The Empire Strikes Back Remake

A super-special edition of a beloved classic.

Starring (in order of appearance):
Ben, Raymie, Leanna, and Evie

Bars vs. Grocery Stores

The Strange Maps blog has a map of the U.S. that is very interesting.  A yellow dot indicates more grocery stores than bars in that location; a red dot indicates more bars.  I bet you can imagine what the map looks like….

My Favorite Super Bowl Commercials 2010

The Super Bowl has come and gone this year.  As soon as the Packers get knocked out of the playoffs, the football season is done, in my opinion.  But I usually watch the Super Bowl anyway, just to see if the commercials will be any better than the year before.

Here are my 3 favorites from this year, in no particular order:
Click here to read more »

Christmas Lights in Staunton, VA

My uncle Mark Miller designed and built a really neat Christmas light display for his community of Staunton, Virginia a few years ago, and it has become an annual favorite. The display covers an entire baseball diamond, and features an animated home run. I helped him out with the wiring and programming. Here is a news clip that aired last night in Staunton interviewing him about the display.

Update: It now works in Internet Explorer! However, I still recommend that everyone install a better browser.

I’m Sorry

I would like to apologize to everyone whose name and/or face I have forgotten over the years. I think there are a lot of you. Perhaps this will explain things:


Paul, this one’s for you…

From Jay Leno last night: Click here to read more »