diff --git a/src/NativeFileSystem.js b/src/NativeFileSystem.js
index 1efedc348e4..350cc8ffca8 100644
--- a/src/NativeFileSystem.js
+++ b/src/NativeFileSystem.js
@@ -11,25 +11,30 @@ window.NativeFileSystem = {
* @param {function} resultCallback
* @constructor
*/
- showOpenDialog: function ( allowMultipleSelection,
+ showOpenDialog: function ( allowMultipleSelection,
chooseDirectories,
title,
initialPath,
fileTypes,
- resultCallback ) {
-
- if( !resultCallback )
- return null;
+ successCallback,
+ errorCallback ) {
+ if( !successCallback )
+ return;
- var files = brackets.file.showOpenDialog( allowMultipleSelection,
- chooseDirectories,
- title,
- initialPath,
- fileTypes,
- resultCallback );
+ var files = brackets.fs.showOpenDialog( allowMultipleSelection,
+ chooseDirectories,
+ title,
+ initialPath,
+ fileTypes,
+ function( err, data ){
+ if( ! err )
+ successCallback( data );
+ else if (errorCallback)
+ errorCallback(NativeFileSystem._nativeToFileError(err));
+ });
+
},
-
/** requestNativeFileSystem
*
* @param {string} path
@@ -37,22 +42,55 @@ window.NativeFileSystem = {
* @param {function} errorCallback
*/
requestNativeFileSystem: function( path, successCallback, errorCallback ){
-
- // TODO: assumes path is a directory right now. Need to error check
- // TODO: don't actually need to get the listing here, but should verify the directory exists
- var entryList = brackets.file.getDirectoryListing(path);
- if (entryList) {
- var files = JSON.parse(entryList);
- var root = new DirectoryEntry( path );
- return root;
- }
- else {
- return null;
+ brackets.fs.stat(path, function( err, data ){
+ if( !err ){
+ var root = new DirectoryEntry( path );
+ successCallback( root );
+ }
+ else if (errorCallback) {
+ errorCallback(NativeFileSystem._nativeToFileError(err));
+ }
+ });
+ },
+
+ _nativeToFileError: function(nativeErr) {
+ // The HTML file spec says SECURITY_ERR is a catch-all to be used in situations
+ // not covered by other error codes.
+ var error = FileError.SECURITY_ERR;
+
+ switch (nativeErr) {
+ // We map ERR_UNKNOWN and ERR_INVALID_PARAMS to SECURITY_ERR,
+ // since there aren't specific mappings for these.
+ case brackets.fs.ERR_UNKNOWN:
+ case brackets.fs.ERR_INVALID_PARAMS:
+ error = FileError.SECURITY_ERR;
+ break;
+
+ case brackets.fs.ERR_NOT_FOUND:
+ error = FileError.NOT_FOUND_ERR;
+ break;
+ case brackets.fs.ERR_CANT_READ:
+ error = FileError.NOT_READABLE_ERR;
+ break;
+
+ // It might seem like you should use FileError.ENCODING_ERR for this,
+ // but according to the spec that's for malformed URLs.
+ case brackets.fs.ERR_UNSUPPORTED_ENCODING:
+ error = FileError.SECURITY_ERR;
+ break;
+
+ case brackets.fs.ERR_CANT_WRITE:
+ error = FileError.NO_MODIFICATION_ALLOWED_ERR;
+ break;
+ case brackets.fs.ERR_OUT_OF_SPACE:
+ error = FileError.QUOTA_EXCEEDED_ERR;
+ break;
}
- }
+
+ return new FileError(error);
+ }
};
-
/** class: Entry
*
* @param {string} name
@@ -73,7 +111,7 @@ Entry = function( fullPath, isDirectory) {
this.name = pathParts.pop();
}
- // IMPLEMENT LATERvar filesystem;
+ // IMPLEMENT LATER var filesystem;
// IMPLEMENT LATER void moveTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
// IMPLEMENT LATER void copyTo (DirectoryEntry parent, optional DOMString newName, optional EntryCallback successCallback, optional ErrorCallback errorCallback);
// IMPLEMENT LATER DOMString toURL (optional DOMString mimeType);
@@ -131,7 +169,7 @@ DirectoryReader = function() {
};
-/** readEntires
+/** readEntries
*
* @param {function} successCallback
* @param {function} errorCallback
@@ -139,31 +177,63 @@ DirectoryReader = function() {
*/
DirectoryReader.prototype.readEntries = function( successCallback, errorCallback ){
var rootPath = this._directory.fullPath;
- var jsonList = brackets.file.getDirectoryListing( rootPath );
- var nameList = JSON.parse(jsonList);
-
- // Create entries for each name
- var entries = [];
- nameList.forEach(function(item){
- // Ignore names starting with "."
- if (item.indexOf(".") != 0) {
- var itemFullPath = rootPath + "/" + item;
-
- if( brackets.file.isDirectory( itemFullPath ) ) {
- entries.push( new DirectoryEntry( itemFullPath ) );
- }
- else {
- entries.push( new FileEntry( itemFullPath ) );
- }
+ var jsonList = brackets.fs.readdir( rootPath, function( err, filelist ) {
+ if( ! err ){
+ // Create entries for each name
+ var entries = [];
+ filelist.forEach(function(item){
+ var itemFullPath = rootPath + "/" + item;
+
+ brackets.fs.stat( itemFullPath, function( err, statData) {
+
+ if( !err ){
+ if( statData.isDirectory( itemFullPath ) )
+ entries.push( new DirectoryEntry( itemFullPath ) );
+ else if( statData.isFile( itemFullPath ) )
+ entries.push( new FileEntry( itemFullPath ) );
+ }
+ else if (errorCallback) {
+ errorCallback(NativeFileSystem._nativeToFileError(err));
+ }
+
+ })
+ });
+
+ successCallback( entries );
}
- });
-
-
-
- successCallback( entries );
-
- // TODO: error handling
+ else if (errorCallback) {
+ errorCallback(NativeFileSystem._nativeToFileError(err));
+ }
+ });
};
+/** class: FileError
+ *
+ * Implementation of HTML file API error code return class. Note that the
+ * various HTML file API specs are not consistent in their definition of
+ * some error code values like ABORT_ERR; I'm using the definitions from
+ * the Directories and System spec since it seems to be the most
+ * comprehensive.
+ *
+ * @constructor
+ * @param {number} code The error code to return with this FileError. Must be
+ * one of the codes defined in the FileError class.
+ */
+FileError = function(code) {
+ this.code = code || 0;
+};
-
+$.extend(FileError, {
+ NOT_FOUND_ERR: 1,
+ SECURITY_ERR: 2,
+ ABORT_ERR: 3,
+ NOT_READABLE_ERR: 4,
+ ENCODING_ERR: 5,
+ NO_MODIFICATION_ALLOWED_ERR: 6,
+ INVALID_STATE_ERR: 7,
+ SYNTAX_ERR: 8,
+ INVALID_MODIFICATION_ERR: 9,
+ QUOTA_EXCEEDED_ERR: 10,
+ TYPE_MISMATCH_ERR: 11,
+ PATH_EXISTS_ERR: 12
+});
diff --git a/src/brackets.js b/src/brackets.js
index a2c9d89ab63..d2c617ec431 100644
--- a/src/brackets.js
+++ b/src/brackets.js
@@ -13,10 +13,50 @@ $(document).ready(function() {
// Temporary button to test file directory traversa;
$("#menu-file-open").click(function(){
if (!inBrowser) {
- window.NativeFileSystem.showOpenDialog(false, true, "Choose a folder", null, null, showOpenDialogCallback);
+ window.NativeFileSystem.showOpenDialog( false, true, "Choose a folder",
+ null, null,
+ showOpenDialogSuccessCallback,
+ showOpenDialogErrorCallback);
+
+ /*
+ // TEST CODE
+ var reader = new FileReader();
+ reader.onerror = errorHandler;
+
+ reader.onabort = function(e) {
+ alert('File read cancelled');
+ };
+
+ reader.onloadstart = function(e) {
+ console.log( "loading" );
+ };
+
+
+ // Read in the image file as a binary string.
+ reader.readAsText(file);
+
+
+ function errorHandler(evt) {
+ switch(evt.target.error.code) {
+ case evt.target.error.NOT_FOUND_ERR:
+ alert('File Not Found!');
+ break;
+ case evt.target.error.NOT_READABLE_ERR:
+ alert('File is not readable');
+ break;
+ case evt.target.error.ABORT_ERR:
+ break; // noop
+ default:
+ alert('An error occurred reading this file.');
+ };
+ }
+
+*/
+
}
});
+
// Implements the 'Run Tests' menu to bring up the Jasmine unit test window
var testWindow = null;
$("#menu-runtests").click(function(){
@@ -34,21 +74,36 @@ $(document).ready(function() {
}
});
- function showOpenDialogCallback( files ) {
+ function showOpenDialogErrorCallback( err ){
+ console.log( err )
+ }
+
+ function showOpenDialogSuccessCallback( files ) {
var folderName = files instanceof Array ? files[0] : files;
+ var nestingLevel = 0;
if (folderName != "") {
- var rootEntry = window.NativeFileSystem.requestNativeFileSystem( folderName, null, null ); // TODO: add callbacks
+ window.NativeFileSystem.requestNativeFileSystem( folderName,
+ requestNativeFileSystemSuccessCB, requestNativeFileSystemErrorCB ); // TODO: add callbacks
+
+ }
+
+ function requestNativeFileSystemSuccessCB( rootEntry ){
var nestingLevel = 0;
if( rootEntry && rootEntry.isDirectory )
readDirectory( rootEntry );
}
+ function requestNativeFileSystemErrorCB( err){
+ console.log( err );
+ }
+
// Test directory traversal
function readDirectory( entry ){
+
var reader = entry.createReader();
reader.readEntries( dirReaderSuccessCB, dirReaderErrorCB);
}
diff --git a/test/SpecRunner.html b/test/SpecRunner.html
index 1e383df4d8b..ab4088e5191 100644
--- a/test/SpecRunner.html
+++ b/test/SpecRunner.html
@@ -24,7 +24,7 @@
-
+
diff --git a/test/spec/SampleTest.js b/test/spec/Editor-test.js
similarity index 55%
rename from test/spec/SampleTest.js
rename to test/spec/Editor-test.js
index 56d8db8fb8b..ebd266c0c52 100644
--- a/test/spec/SampleTest.js
+++ b/test/spec/Editor-test.js
@@ -1,15 +1,5 @@
-describe("Brackets", function(){
- var content = 'Brackets is going to be awesome!"\n';
-
- it("should be awesome", function() {
- this.addMatchers({
- toBeAwesome: function(expected) {
- return true;
- }
- });
-
- expect("Brackets").toBeAwesome();
- });
+describe("Editor", function(){
+ var content = 'Brackets is going to be awesome!\n';
describe("CodeMirror", function() {
var myCodeMirror;
@@ -33,9 +23,3 @@ describe("Brackets", function(){
});
});
});
-
-describe("Failure", function() {
- it("is expected sometimes", function() {
- expect("failure").toEqual("sometimes");
- });
-});
\ No newline at end of file
diff --git a/test/spec/NativeFileSystem-test.js b/test/spec/NativeFileSystem-test.js
index 98e10b69156..c74bc1bc6c8 100644
--- a/test/spec/NativeFileSystem-test.js
+++ b/test/spec/NativeFileSystem-test.js
@@ -21,9 +21,6 @@ describe("NativeFileSystem", function(){
return false;
}
});
- });
-
- it("should read a directory from disk", function() {
//TODO: Make this relative -- right now, asking for "." gives "/"
//Want to be able to simply use:
@@ -32,26 +29,80 @@ describe("NativeFileSystem", function(){
path = path.substr("file://".length);
path = path.substr(0,path.lastIndexOf("/")+1);
path = path + "spec/NativeFileSystem-test-files";
+ this.path = path;
+ });
+ it("should read a directory from disk", function() {
var entries = null;
var readComplete = false;
- var nfs = window.NativeFileSystem.requestNativeFileSystem(path);
- var reader = nfs.createReader();
-
- var successCallback = function(e) { entries = e; readComplete = true; }
- // TODO: not sure what parameters error callback will take because it's not implemented yet
- var errorCallback = function() { readComplete = true; }
-
- reader.readEntries(successCallback, errorCallback);
-
- waitsFor(function() { return readComplete; }, 1000);
-
- runs(function() {
- expect(entries).toContainDirectoryWithName("dir1");
- expect(entries).toContainFileWithName("file1");
- expect(entries).not.toContainFileWithName("file2");
- });
+ var nfs = window.NativeFileSystem.requestNativeFileSystem(this.path, requestNativeFileSystemSuccessCB);
+ function requestNativeFileSystemSuccessCB( nfs ){
+ var reader = nfs.createReader();
+
+ var successCallback = function(e) { entries = e; readComplete = true; }
+ // TODO: not sure what parameters error callback will take because it's not implemented yet
+ var errorCallback = function() { readComplete = true; }
+
+ reader.readEntries(successCallback, errorCallback);
+
+ waitsFor(function() { return readComplete; }, 1000);
+
+ runs(function() {
+ expect(entries).toContainDirectoryWithName("dir1");
+ expect(entries).toContainFileWithName("file1");
+ expect(entries).not.toContainFileWithName("file2");
+ });
+ }
+ });
+
+ it("should return an error if the directory doesn't exist", function() {
+ var successCalled = false, errorCalled = false, error = null;
+ window.NativeFileSystem.requestNativeFileSystem(this.path + '/nonexistent-dir', function(data) {
+ successCalled = true;
+ }, function(err) {
+ errorCalled = true;
+ error = err;
+ });
+
+ waitsFor(function() { return successCalled || errorCalled; }, 1000);
+
+ runs(function() {
+ expect(successCalled).toBe(false);
+ expect(errorCalled).toBe(true);
+ expect(error.code).toBe(FileError.NOT_FOUND_ERR);
+ });
+ });
+
+ it("should return an error if you pass a bad parameter", function() {
+ var successCalled = false, errorCalled = false, error = null;
+ window.NativeFileSystem.requestNativeFileSystem(0xDEADBEEF, function(data) {
+ successCalled = true;
+ }, function(err) {
+ errorCalled = true;
+ error = err;
+ });
+
+ waitsFor(function() { return successCalled || errorCalled; }, 1000);
+
+ runs(function() {
+ expect(successCalled).toBe(false);
+ expect(errorCalled).toBe(true);
+ expect(error.code).toBe(FileError.SECURITY_ERR);
+ });
+ });
+
+ it("should be okay to not pass an error callback", function() {
+ var entries = null;
+ window.NativeFileSystem.requestNativeFileSystem(this.path, function(data) {
+ entries = data;
+ });
+
+ waitsFor(function() { return entries != null; }, 1000);
+
+ runs(function() {
+ expect(entries).not.toBe(null);
+ });
});
});
});