File browser

From Trephine

Jump to: navigation, search

File browser

Basic interactive demo showing how to implement a file browser through calls to trephine.

You must have JavaScript enabled to run this demo.

/* Status and element functions. */
var e = function(tag,index){ return demotab.getElementsByTagName(tag)[index||0]; };
var status = function(msg) {
  if (!msg) return e('p').style.display = 'none';
  e('p').style.display = '';
  e('p').innerHTML = msg;
};
 
/* File browser implementation singleton. */
var filebrowser = window.filebrowser = {
 
  // Setup the demo
  init: function() {
    var self = this;
 
    // Setup the "up" link
    e('a').onclick = function(evt) {
      if (!evt) evt = window.event;
      evt.cancelBubble = true;
      if (evt.stopPropagation) evt.stopPropagation();
      var result = trephine.js( function(path) {
        return (new java.io.File(path)).parent + '';
      }, e('input').value );
      if (result.error) throw "Error: " + result.error;
      self.show(result.result.toString() + '');
      return false;
    };
 
    // Setup the path text box (when Enter is pressed, reload)
    var input = e('input');
    input.onkeyup = function(evt) {
      var event = evt || window.event, code = event.keyCode;
      if (code == 13) return self.show(input.value);
    };
 
    // Setup the browse button
    e('input', 1).onclick = function(evt) {
      var result = trephine.js( function() {
        (new java.lang.Thread(new java.lang.Runnable({
          run: function() {
            var p = function(s){ java.lang.System.out.println(s); };
            p("filebrowser::browse - START [" + java.lang.Thread.currentThread() + "]" );
            var dialog = new java.awt.FileDialog(
              new java.awt.Frame(),
              "Choose a directory",
              java.awt.FileDialog.LOAD
            ); 
            p("filebrowser::browse - showing FileDialog" );
            dialog.show();
            p("filebrowser::browse - dialog closed, directory = " + dialog.directory + "");
            var re = function(s){ return new RegExp(s,'g'); };
            var path = (dialog.directory + '').replace(re('([\'"\\\\])'), '\\\\\\$1');
            p("filebrowser::browse - calling window.eval() to trigger filebrowser.show(path)");
            window.eval("setTimeout('window.top.filebrowser.show(\"" + path + "\")', 10)");
            p("filebrowser::browse - DONE!");
          }
        }))).start();
        return true;
      } );
      if (result.error) throw "Error: " + result.error;
    };
 
    // Determine OS specific path separator
    var result = trephine.js( function() { return java.io.File.separator + ''; } );
    this.separator = result.result.toString() + '' || '/';
 
    // Initialize path text input box
    var result = trephine.js( function() { return java.lang.System.getProperty('user.home') + ''; } );
    if (result.error) throw "Error: " + result.error;
    this.show(result.result.toString() + '');
  },
 
  // Show a given directory's contents
  show: function(dir) {
    var self = this;
    e('input').value = dir;
    var result = trephine.js( function(path) {
      var dir = new java.io.File(path);
      if (!dir.isDirectory()) throw "Path [" + path + "] is not a directory";
      if (!dir.canRead()) throw "Path [" + path + "] is not readable";
      var list = dir.listFiles(), files = [], subdirs = [], buf = [];
      for (var i=0; i<list.length; i++) {
        if (list[i].isDirectory()) subdirs[subdirs.length] = list[i].getName() + '';
        else files[files.length] = list[i].getName() + '';
      }
      subdirs.sort();
      files.sort();
      var symbols = {};
      symbols['"'] = '&quot;';
      symbols['<'] = '&lt;';
      symbols['>'] = '&gt;';
      symbols['&'] = '&amp;';
      var htmlspecialchars = function(str) {
        var buf = (str + '').split('');
        for (var i=0; i<buf.length; i++) buf[i] = symbols[buf[i]] || buf[i];
        return buf.join('');
      };
      for (var i=0; i<subdirs.length; i++) {
        var name = htmlspecialchars(subdirs[i]);
        buf[buf.length] = ['<a href="" title="', name, '">', name, '</a>'].join('');
      };
      for (var i=0; i<files.length; i++) {
        buf[buf.length] = htmlspecialchars(files[i]);
      };
      return ['<ul><li>', buf.join('</li><li>'), '</li></ul>'].join('');
    }, e('input').value );
    if (result.error) e('div').innerHTML = "<p class=\"error\">Error: " + result.error.getMessage() + "</p>";
    e('div').innerHTML = result.result.toString() + '';
    var elems = e('div').getElementsByTagName('a');
    for (var i=0; i<elems.length; i++) (function(a){
      a.onclick = function(evt) {
        if (!evt) evt = window.event;
        evt.cancelBubble = true;
        if (evt.stopPropagation) evt.stopPropagation();
        self.show(dir + self.separator + a.title);
        return false;
      };
    })(elems[i]);
  }
};
 
/* Load trephine */
status('<span class="spinner"></span> Loading trephine...');
trephine.load({
  debug: true, // Enables debug logging to the Java Console
  engines: ['js'], // Initialize the JavaScript engine as soon as possible
  onload: function() { // Immediately prompt for permissions
    status('<span class="spinner"></span> Asking for elevated permissions...');
    trephine.askPermission( function(response) {
      if (!response) { // Short-circuit if permission request was denied
        return demotab.innerHTML = '<div class="error">Sorry, you must grant trephine privileges to enjoy this demo.</div>';
      }
      status('Permission request granted.');
      setTimeout( function(){ status(); }, 2000 );
      filebrowser.init();
    } );
  }
});
<p class="notice"></p>
<p>
  <a href="" class="upbutton" title="Up to parent directory"><span>&uarr;</span></a>
  <input class="filepath" type="text" value="">
  <input class="button" type="button" value="browse"/>
</p>
<div></div>
.demotab p {
  margin-bottom: 9px;
}
.demotab .upbutton {
  font-weight: bold;
  font-size: 24px;
  line-height: 18px;
}
.demotab .upbutton span {
  position: relative;
  top: 4px;
}
.demotab .filepath {
  width: 500px;
}
.demotab div {
  height: 180px;
  overflow: auto;
  margin-bottom: 18px;
  border: 1px solid #ccc;
}
.demotab ul {
  margin: 0;
}
.demotab li {
  padding-left: 0.5em;
  list-style-type: none;
}
.demotab .spinner {
  float: left;
  height: 20px;
  width: 25px;
  background: url("skins/common/images/spinner.gif");
  background-repeat: no-repeat;
}

Activation

  1. Activate the demo by clicking the specified link.
  2. You may see a Java Security dialog, if so, click "Run" or "Trust" to indicate your acceptance
  3. In the "Trephine permission request" dialog, answer the math challenge and click "OK" to grant scripts on this page elevated privileges.

Usage

  • Navigate to subdirectories by clicking them.
  • Click the ↑ link to go up to the parent directory.
  • Use the browse button to launch a native file dialog and jump to the selected directory.
Personal tools