/** * Loads a file from disk and returns a binary string * * Copyright (C) 2012 Mike Gerwitz * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * * The file uses a number of features introduced in the HTML5 and ECMAScript * specs, as it depends on FileReader. */ /** * Load file into memory as binary string from a given file element * * This class handles the loading of only a single file (as that is all this * project requires). */ ltjs.FileLoader = Class( 'FileLoader', { /** * DOM file element to watch * @type {HTMLInputElement} */ 'private _element': null, /** * Callback to call on file load * @type {function(Error,string)} */ 'private _callback': null, /** * Initialize file loader, monitoring the given file element * * @param {HtmlInputElement} element file element to monitor */ __construct: function( element ) { if ( element.type !== 'file' ) { throw TypeError( 'Expected file element, given ' + element.type ); } this._element = element; }, /** * Bind callback to file load event * * The given callback will be called when the file is loaded. It must accept * two arguments: the first will be used to indicate an error (otherwise * null) and the second argument will contain the binary string of data * (unless an error occurred, in which case it will be undefined). * * @param {function(Error,string)} callback file load callback * * @return {FileLoader} self */ 'public onLoad': function( callback ) { this._callback = callback; // we do not want to monitor the change event until *after* a callback // is registered (it is otherwise pointless) this._element.addEventListener( 'change', this._loadFile.bind( this ) ); // attempt to load file immediately (in case a file has already been // selected) this._loadFile( { target: this._element } ); return this; }, /** * Process file and invokes callback with result * * Called on filename change. * * @param {Object} event change event * * @return {undefined} */ 'private _loadFile': function( event ) { var _self = this, files = event.target.files; if ( files.length === 0 ) return; var reader = new FileReader(); reader.onload = function( revent ) { _self._callback.call( this.__inst, null, revent.target.result ); }; reader.onerror = function( e ) { _self._callback.call( this.__inst, e ); }; // load file reader.readAsBinaryString( files[ 0 ] ); } } );