Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
johndoe committed Sep 5, 2019
1 parent d14678d commit d12bc6b
Showing 1 changed file with 236 additions and 0 deletions.
236 changes: 236 additions & 0 deletions code/utils_file.js
Expand Up @@ -29,3 +29,239 @@ window.saveFile = function (data,filename,dataType) {
saveAs([data], filename, dataType);
}
};


/*
* @class FileReader
* @aka L.FileReader
* @inherits Evented
*
* Leaflet thin wrapper over [`FileReader`](https://w3c.github.io/FileAPI/#APIASynch) Web API.
*
* @example
*
* ```js
* L.fileReader(file)
* .on('load',function (e) {
* console.log(e.file.name,e.reader.result)
* });
* ```
*/
L.FileReader = L.Evented.extend({
options: {
// encoding: 'utf-8' // todo

// @option readAs: String = 'readAsText'
// Function to use for file reading.
readAs: 'readAsText'
},

initialize: function (file, options) {
this._setOptions(options);
var reader = new FileReader();
this._eventTypes.forEach(function (type) {
reader.addEventListener(type,this._fire.bind(this,type));
},this);
this.reader = reader;
this.once('loadstart',function () {
if (!this.listens('error',true)) {
this.on('error',this._onerror);
}
});
if (file) { this.read(file); }
},

_setOptions: function (options) {
if (typeof options === 'string') {
options = {readAs: options};
}
return L.Util.setOptions(this, options);
},

// @method read(file?, options?: Object or String): this
// Starts reading the contents of the `file` using [reader method](https://w3c.github.io/FileAPI/#reading-a-file) specified in options.
// `file` argument is optional only if already specified (in constructor, or in previous method call).
// `options` argument has the same meaning as in constructor.
read: function (file, options) {
if (options) { this._setOptions(options); }
if (file) { this.file = file; }
this.reader[this.options.readAs](this.file);
return this;
},

_onerror: function (e) {
console.warn('Error loading file: ',e.file.name,'\n',e.reader.error.message); // eslint-disable-line no-console
},

// @event [abort, error, load, loadstart, loadend, progress](https://w3c.github.io/FileAPI/#events): Event
// Event object has following additional properties:
// `reader`: raw instance of [`FileReader`](https://w3c.github.io/FileAPI/#APIASynch) interface
// `file`: raw instance of [`File`/`Blob`](https://w3c.github.io/FileAPI/#dfn-file)
// `originalEvent`: raw [event](https://w3c.github.io/FileAPI/#events)
// Note: if no handlers found for `error` then default one will be attached (`console.warn`)
_eventTypes: ['abort','error','load','loadstart','loadend','progress'],

_fire: function (type,event) {
if (!this.listens(type,true)) { return; }
this.fire(type,Object.assign({originalEvent: event},this),true);
}
});

// @factory L.fileReader(file?: Blob, options?: Object or String)
// Instantiates a `FileReader` object given the [`File`/`Blob`](https://w3c.github.io/FileAPI/#dfn-file)
// and optionally an object literal with `options`.
// If `file` argument is specified, then `read` method is called immediately.
// Note: it's possible to specify `readAs` directly instead of full `options` object
L.fileReader = function (file, options) {
return new L.FileReader(file, options);
};

/*
* @class FileListReader
* @aka L.FileListReader
* @inherits Evented
*
* Used to handle [FileList](https://w3c.github.io/FileAPI/#filelist-section), processing it as whole.
* Each `File` will be loaded with `L.FileReader` using common event handlers,
* including propagated from underlying `L.FileReader`.
*
* @example
*
* ```js
* L.FileListReader(fileList)
* .on('load',function (e) {
* console.log(e.file.name,e.reader.result)
* });
* .on('loaded',function (e) {
* console.log('All done!')
* });
* .load();
* ```
*/
L.FileListReader = L.Evented.extend({
options: {
// @option readAs: String = 'readAsText'
// Function to use for file reading.
readAs: 'readAsText'
},

initialize: function (fileList, options) {
L.Util.setOptions(this, options);
this._readers = [];
this.once('loadstart',function () {
debugger;
if (this.listens('loaded')) {
this.on('loadend',this._onloadend);
}
});
if (fileList) {
this.load(fileList);
}
},

// @method load(fileList: FileList)
// Starts loading files listed in `fileList` argument.
// ??Note: all event handlers expected to be already attached **before** this method call.
load: function (fileList) {
if (!fileList) {
throw new Error('`fileList` arg not specified');
}
this._toload = fileList.length;
Array.prototype.forEach.call(fileList,function (file) {
var options = this.options;
if (this.listens('init')) {
options = L.extend({},options);
var stop;
// @event init: Event
// Fired for each file _before_ reading.
// Event object has additional property `file`, containing processed [`File`](https://w3c.github.io/FileAPI/#dfn-file) object.
// `stop()`: do not read current file
// `setOptions(options)`: use special options for current file
// (`this.options` extended with given `options` argument.
this.fire('init',{
file: file,
stop: function () { stop = true; },
setOptions: function (o) { L.extend(options,o); }
});
if (stop) { this._onloadend(); return; }
}
var reader = L.fileReader(file,options)
.addEventParent(this);
this._readers.push(reader);
},this);
return this; //????
},

// @event loaded: Event
// Fired after all files are processed (either with success or with error).
_onloadend: function () {
debugger;
this._toload--;
if (this._toload === 0) { this.fire('loaded'); }
}
});

// @factory L.fileListReader(fileList?: FileList, options?: Object)
// Instantiates a `FileListReader` object given the [`FileList`](https://w3c.github.io/FileAPI/#filelist-section)
// and optionally an object literal with `options`.
// If `fileList` argument is specified, then `load` method is called immediately.
L.fileListReader = function (fileList, options) {
return new L.FileListReader(fileList, options);
};

function chooseFiles (options,callback) {
// assert callback
var input = document.createElement('input');
input.type='file';
if (options) {
input.accept = options.accept;
input.multiple = options.multiple;
}
input.style.display = 'none';
input.addEventListener('change', function () {
callback(this.files);
}, false);
document.body.appendChild(input);
input.click();
input.remove();
}

window.loadFiles = function (options) { // compatibility shim for IITCm
var loader;
if (window.requestFile) {
loader = new L.Evented();
window.requestFile(function (filename,text) {
var file = {
name: filename,
size: text.length(),
type: ''
};
var stop;
this.fire('init',{
file: file,
stop: function () { stop = true; }
});
if (!stop) {
this.fire('load',{
file: file,
reader: {result: text},
});
}
this.fire('loaded');
}.bind(this));
return loader;
}
loader = L.fileListReader();
chooseFiles(options,loader.load.bind(loader));
return loader;
};

/*
var options = {accept:'.json', multiple:true};
loadFiles(options)
.on('init',function (e) {
if (e.file.name === 'package.json') e.stop();
})
.on('load',console.log)
.on('loaded',console.log);
*/

0 comments on commit d12bc6b

Please sign in to comment.