File browser
From Trephine
[subscribe] Recent blog entries
- Simple prototypal inheritance new!
- Adventures in Rhino - setters and getters
- Site improvements - fighting with Disqus
- JavaScript task chaining
- JavaScript string building benchmarks
- Efficient JavaScript string building
- Alternative JavaScript worker thread API
- Implementing JavaScript worker threads
- Thread safe DOM manipulation
- Site improvements - CSS sprites
- Trephine worker threads made easy
- Pitfalls of multithreaded browser development
- Site improvements - reducing dependencies
- The unsplittability of XML
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['"'] = '"'; symbols['<'] = '<'; symbols['>'] = '>'; symbols['&'] = '&'; 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>↑</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
- Activate the demo by clicking the specified link.
- You may see a Java Security dialog, if so, click "Run" or "Trust" to indicate your acceptance
- 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.