UNPKG

ldx-widgets

Version:

widgets

290 lines (280 loc) 10.3 kB
(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);