HTML5 File System API

HTML

<script src="https://rawgithub.com/jashkenas/underscore/1.5.1/underscore-min.js"></script>
<script src="https://rawgithub.com/postaljs/monologue.js/master/lib/monologue.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/css/bootstrap.min.css">
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0-rc1/js/bootstrap.min.js"></script>
<script src="https://rawgithub.com/postaljs/postal.js/master/lib/postal.min.js"></script>
<script src="https://rawgithub.com/postaljs/monopost.js/master/lib/monopost.min.js"></script>
<script src="https://rawgithub.com/postaljs/postal.diagnostics/master/lib/postal.diagnostics.min.js"></script>
<script src="https://rawgithub.com/ifandelse/37dd214aaa582a77f1b0/raw/c1c5d40183fb15308a921c1f5207e83f8a9cc9f8/IndexedDB_Sillyness.js"></script>
<script type="text/underscore-template" id="pref-template">
    <tr><td><%=fullName %></td><td><%=bandName %></td></tr>
</script>
<div class="tab-pane active well" id="addPrefs">
    <form class="form-inline" id="prefForm">
        <legend>Band/Artist Preference</legend>
       <fieldset>
            <input class="form-control" type="text" id="fullName" placeholder="Your Name" />
            <input class="form-control" type="text" id="bandName" placeholder="Band You Like" />
            <button class="btn btn-default" id="addPref">Add</button>
            <input type="reset" class="btn btn-default" value="Reset" />
        </fieldset>
   </form>
</div>
<table id="prefList" class="table table-condensed table-striped">
    <thead>
        <th>Name</th>
        <th>Band</th>
    </thead>
    <tbody></tbody>
</table>

CSS

#prefList {
    margin-top:2em;
    width:30em;
}
input[type="text"] {
    width: 12.5em;
}

JavaScript

if((navigator && !navigator.webkitPersistentStorage) && (!window.webkitRequestFileSystem)) {
    $("body").html("<h2>Aw, shucks.<br/>Your browser doesn't support the FileSystem API</h2>");
} else {
    function errorHandler(e) {
        var msg = "";
        switch (e.code) {
            case FileError.QUOTA_EXCEEDED_ERR:
                msg = "QUOTA EXCEEDED ERROR";
                break;
            case FileError.NOT_FOUND_ERR:
                msg = "NOT FOUND ERROR";
                break;
            case FileError.SECURITY_ERR:
                msg = "SECURITY ERROR";
                break;
            case FileError.INVALID_MODIFICATION_ERR:
                msg = "INVALID MODIFICATION ERROR";
                break;
            case FileError.INVALID_STATE_ERR:
                msg = "INVALID STATE ERROR";
                break;
            default:
                msg = "Unknown Error";
                break;
        };
        alert("Error: " + msg);
    }
    
    var storageAdapter = (function (bus, Monologue, $) {
        var getWriter = function(contents, cb) {
            return function (fileEntry) {
                // Create a FileWriter object for data.json.
                fileEntry.createWriter(function (fileWriter) {
                    fileWriter.onwriteend = function (e) {
                        console.log("Write completed.");
                        if(cb) { cb(); }
                    };
                    fileWriter.onerror = function (e) {
                        alert("Write failed: " + e.toString());
                    };
                    // Create a new Blob and write it to data.json.
                    var blob = new Blob([JSON.stringify(contents)], {
                        type: "text/plain"
                    });
                    fileWriter.write(blob);
                }, errorHandler);
            }    
        };
        // the actual storage adapter instance that will be returned
        // from this module
        var...