ldx-widgets
Version:
widgets
290 lines (280 loc) • 10.3 kB
JavaScript
(function() {
var AlertModal, FileInput, IMAGE_TYPES, ProgressBar, React, button, div, input, li, ref, ul, utils,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
React = require('react');
ProgressBar = React.createFactory(require('./progress_bar'));
AlertModal = React.createFactory(require('./alert_modal'));
utils = require('../utils');
IMAGE_TYPES = require('../constants/file_types').IMAGE_TYPES;
ref = React.DOM, div = ref.div, input = ref.input, button = ref.button, ul = ref.ul, li = ref.li;
FileInput = React.createClass({
displayName: 'FileInput',
propTypes: {
openAlertModal: React.PropTypes.func.isRequired,
wrapperClass: React.PropTypes.string,
className: React.PropTypes.string,
multiple: React.PropTypes.bool,
chooseFileText: React.PropTypes.string,
removeFileText: React.PropTypes.string,
name: React.PropTypes.string.isRequired,
maxSize: React.PropTypes.number,
resolution: React.PropTypes.object,
disabled: React.PropTypes.bool,
uploadProgress: React.PropTypes.oneOfType([React.PropTypes.object, React.PropTypes.string, React.PropTypes.number])
},
getDefaultProps: function() {
return {
wrapperClass: 'file-input-wrapper',
className: 'file-input',
multiple: false,
chooseFileText: 'Choose file...',
removeFileText: 'Remove file',
maxSize: 1048576,
disabled: false,
name: '',
openAlertModal: function() {}
};
},
getInitialState: function() {
return {
fileInputKey: 0,
valid: true,
inputHasFile: false,
filename: ''
};
},
render: function() {
var chooseFileText, className, disabled, fileInputKey, filename, hideUpload, inputHasFile, multiple, name, ref1, ref2, removeFileText, showFileRemove, uploadProgress, wrapperClass;
ref1 = this.props, name = ref1.name, className = ref1.className, wrapperClass = ref1.wrapperClass, multiple = ref1.multiple, uploadProgress = ref1.uploadProgress, chooseFileText = ref1.chooseFileText, removeFileText = ref1.removeFileText, showFileRemove = ref1.showFileRemove, disabled = ref1.disabled, hideUpload = ref1.hideUpload;
ref2 = this.state, fileInputKey = ref2.fileInputKey, inputHasFile = ref2.inputHasFile, filename = ref2.filename;
multiple = multiple ? 'multiple' : '';
if (typeof uploadProgress === 'object') {
uploadProgress = uploadProgress[name];
}
if ((uploadProgress != null) && uploadProgress !== '') {
wrapperClass += ' is-uploading';
}
return div({
className: wrapperClass
}, [
input({
key: fileInputKey,
className: className,
type: 'file',
ref: 'file',
name: name,
multiple: multiple,
onChange: this.handleChange,
style: {
display: inputHasFile ? 'none' : 'block'
},
disabled: disabled
}), !disabled ? div({
key: 'overlay',
className: "file-overlay " + ((uploadProgress != null) && uploadProgress !== '' ? 'is-uploading' : '')
}, [
div({
key: 'tools',
className: 'overlay-tools'
}, [
div({
key: 'filename',
className: 'filename'
}, filename), !(hideUpload && inputHasFile) ? button({
key: 'add',
className: 'add-file',
onClick: this.handleFileClick
}, chooseFileText) : void 0, inputHasFile || showFileRemove ? button({
key: 'remove',
className: 'remove-file',
onClick: this.handleFileRemove
}, removeFileText) : void 0
]), (uploadProgress != null) && uploadProgress !== '' ? ProgressBar({
key: 'progress',
progress: uploadProgress
}) : void 0
]) : void 0
]);
},
clear: function() {
return this.setState({
fileInputKey: this.state.fileInputKey + 1,
inputHasFile: false,
filename: ''
});
},
validate: function(file, img) {
var URL, extension, fileTypes, files, max, maxSize, min, ref1, resErrors, resolution, status, types;
ref1 = this.props, fileTypes = ref1.fileTypes, maxSize = ref1.maxSize, resolution = ref1.resolution;
files = this.refs.file.files;
status = {
errors: []
};
URL = window.URL || window.webkitURL;
extension = file.name.split('.').pop().toLowerCase();
if ((maxSize != null) && file.size > maxSize) {
status.errors.push(t("Size must be less than __maxSize__", {
maxSize: utils.bytesToSize(maxSize)
}));
}
if (fileTypes != null) {
if (typeof fileTypes === 'object') {
types = fileTypes.join(', ');
} else if (typeof fileTypes === 'string' && fileTypes === 'imagesOnly') {
types = IMAGE_TYPES.join(', ');
}
if (types.length && types.search(extension) === -1) {
status.errors.push(t("File type must be __fileType__", {
fileType: types.toUpperCase()
}));
}
}
if ((resolution != null) && (img != null) && (URL != null)) {
min = resolution.min, max = resolution.max;
resErrors = [];
if (max != null) {
if (max.h && img.height > max.h) {
resErrors.push(t("Less than __value__ in __measure__", {
value: max.h + "px",
measure: 'height'
}));
}
if (max.w && img.width > max.w) {
resErrors.push(t("Less than __value__ in __measure__", {
value: max.w + "px",
measure: 'width'
}));
}
}
if (min != null) {
if (min.h && img.height < min.h) {
resErrors.push(t("Greater than __value__ in __measure__", {
value: min.h + "px",
measure: 'height'
}));
}
if (min.w && img.width < min.w) {
resErrors.push(t("Greater than __value__ in __measure__", {
value: min.w + "px",
measure: 'width'
}));
}
}
if (resErrors.length) {
status.errors.push(t('Resolution requirements'));
status.errors.push(resErrors);
}
}
return status;
},
showErrorMessage: function(errors) {
var error, i, index, j, len, len1, messages, msg, sErr;
this.stopFilesLoop = true;
messages = [];
for (index = i = 0, len = errors.length; i < len; index = ++i) {
error = errors[index];
if (typeof error === 'object' && error.length) {
for (j = 0, len1 = error.length; j < len1; j++) {
sErr = error[j];
messages.push(li({
key: index,
className: 'sub-item'
}, sErr));
}
} else {
messages.push(li({
key: index,
className: 'item'
}, error));
}
}
if (messages.length) {
msg = ul({
key: 'list',
className: 'error-message-list'
}, messages);
} else {
msg = t("Selected files must match requirements");
}
this.props.openAlertModal(msg);
return this.clear();
},
handleFileRemove: function() {
var base;
return typeof (base = this.props).onFileRemove === "function" ? base.onFileRemove(this.getValue(), this.clear) : void 0;
},
handleFileClick: function(e) {
e.stopPropagation();
return utils.synthesizeMouseEvent(this.refs.file, 'click');
},
handleChange: function(e) {
var URL, extension, file, files, i, img, index, isImage, isLastFile, len, name, onChange, ref1, resolution, uploadProgress, v;
ref1 = this.props, uploadProgress = ref1.uploadProgress, onChange = ref1.onChange, resolution = ref1.resolution, name = ref1.name;
files = this.refs.file.files;
this.stopFilesLoop = false;
URL = window.URL || window.webkitURL;
if (uploadProgress[name] != null) {
return e.preventDefault();
}
this.setState({
filename: files[0].name + " (" + (utils.bytesToSize(files[0].size, 2)) + ")"
});
for (index = i = 0, len = files.length; i < len; index = ++i) {
file = files[index];
extension = file.name.split('.').pop().toLowerCase();
isImage = indexOf.call(IMAGE_TYPES, extension) >= 0;
isLastFile = index === files.length - 1;
if (this.stopFilesLoop) {
this.stopFilesLoop = false;
this.setState({
filename: ''
});
return;
}
if ((resolution != null) && isImage && (URL != null)) {
img = new Image();
img.onload = (function(_this) {
return function() {
var v;
v = _this.validate(file, img);
if (v.errors.length) {
return _this.showErrorMessage(v.errors);
} else if (isLastFile && v) {
if (typeof onChange === "function") {
onChange(_this.getValue());
}
return _this.setState({
inputHasFile: true
});
}
};
})(this);
img.src = URL.createObjectURL(file);
} else {
v = this.validate(file);
if (v.errors.length) {
this.showErrorMessage(v.errors);
} else if (isLastFile && v) {
if (typeof onChange === "function") {
onChange(this.getValue());
}
this.setState({
inputHasFile: true
});
}
}
}
},
getValue: function() {
var value;
value = {
files: this.refs.file.files,
name: this.refs.file.name,
maxSize: this.props.maxSize,
ref: this
};
return value;
}
});
module.exports = FileInput;
}).call(this);