File: components/AttachmentsForm.js
/** @jsx React.DOM */
"use strict";
var _ = require("lodash");
var React = require("react/addons");
var classSet = React.addons.classSet;
var Button = require("react-bootstrap/Button");
var filesize = require("filesize");
var FileItem = require("app/components/FileItem");
/**
* AttachmentsForm
*
* @namespace components
* @class AttachmentsForm
* @constructor
* @param {Object} props
* @param {Number} [props] maxSize Max size for a single file to be uploaded
*/
var AttachmentsForm = React.createClass({
propTypes: {
maxSize: React.PropTypes.number
},
getDefaultProps: function() {
// 50mb
return { maxSize: 5e+7 };
},
getInitialState: function() {
return {
files: []
};
},
/**
* @method isUnderSizeLimit
* @param {HTML5 File Object} file
* @return Boolean
*/
isUnderSizeLimit: function(file) {
return file.size < this.props.maxSize;
},
/**
* Get files selected by the user
*
* @method getFiles
* @return {Array} of HTML 5 File objects
*/
getFiles: function() {
return this.state.files.filter(this.isUnderSizeLimit);
},
/**
* Clear selected files
*
* @method clear
*/
clear: function() {
this.setState({ files: [] });
},
/**
* Copy HTML 5 file objects from the file input to the component state
*
* @method handleFileChange
*/
handleFileChange: function(e) {
this.setState({
files: _.uniq(this.state.files.concat(_.toArray(e.target.files)), toUniqueId)
});
// http://stackoverflow.com/a/13351234/153718
this.refs.form.getDOMNode().reset();
},
/**
* @method removeFile
* @param {HTML5 File Object} file Remove given file from the component
* state
*/
removeFile: function(file) {
this.setState({
files: this.state.files.filter(function(current) {
return current !== file;
})
});
},
/**
* Open file section dialog
*
* @method openFileDialog
*/
openFileDialog: function(e) {
if (e) e.preventDefault();
this.refs.file.getDOMNode().click();
},
render: function() {
var self = this;
var files = this.state.files;
var totalSize = files.reduce(function(total, f) {
return total + f.size;
}, 0);
return (
<div className="AttachmentsForm" style={{ display: "block" }}>
<form ref="form" style={{ display: "none" }}>
<input type="file" ref="file" multiple onChange={self.handleFileChange} />
</form>
<ul>
{files.map(function(f) {
var isTooLarge = !self.isUnderSizeLimit(f);
var classes = classSet({
"too-large": isTooLarge
});
return <li key={toUniqueId(f)} >
<Button className="remove-button" bsStyle="danger" bsSize="xsmall" onClick={self.removeFile.bind(self, f)} >×</Button>
<span className={classes} >
<FileItem mime={f.type} name={f.name} size={f.size} />
</span>
{isTooLarge &&
<div className="size-error-message">
Tiedosto on liian suuri ladattavaksi.
Suurin mahdollinen koko on {filesize(self.props.maxSize)}
</div>}
</li>;
})}
{files.length > 1 && <li className="total">
Yhteensä {filesize(totalSize)}
</li>}
</ul>
<a className="select-button" href="#" onClick={this.openFileDialog}>Liitä tiedosto...</a>
</div>
);
}
});
/**
* Figure out an unique id for a HTML 5 File Object
*
* Not perfect...
*
* @static
* @private
* @method toUniqueId
* @param {HTML5 File Object} file
* @return {String}
*/
function toUniqueId(file) {
return file.name + (file.lastModifiedDate || "") + String(file.size);
}
module.exports = AttachmentsForm;