import _defineProperty from 'babel-runtime/helpers/defineProperty'; import _extends from 'babel-runtime/helpers/extends'; import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; import _createClass from 'babel-runtime/helpers/createClass'; import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; import _inherits from 'babel-runtime/helpers/inherits'; /* eslint react/sort-comp:0 */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; import classNames from 'classnames'; import getUid from './uid'; import warning from 'warning'; var IFRAME_STYLE = { position: 'absolute', top: 0, opacity: 0, filter: 'alpha(opacity=0)', left: 0, zIndex: 9999 }; // diferent from AjaxUpload, can only upload on at one time, serial seriously var IframeUploader = function (_Component) { _inherits(IframeUploader, _Component); function IframeUploader() { var _ref; var _temp, _this, _ret; _classCallCheck(this, IframeUploader); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = IframeUploader.__proto__ || Object.getPrototypeOf(IframeUploader)).call.apply(_ref, [this].concat(args))), _this), _this.state = { uploading: false }, _this.file = {}, _this.onLoad = function () { if (!_this.state.uploading) { return; } var _this2 = _this, props = _this2.props, file = _this2.file; var response = void 0; try { var doc = _this.getIframeDocument(); var script = doc.getElementsByTagName('script')[0]; if (script && script.parentNode === doc.body) { doc.body.removeChild(script); } response = doc.body.innerHTML; props.onSuccess(response, file); } catch (err) { warning(false, 'cross domain error for Upload. Maybe server should return document.domain script. see Note from https://github.com/react-component/upload'); response = 'cross-domain'; props.onError(err, null, file); } _this.endUpload(); }, _this.onChange = function () { var target = _this.getFormInputNode(); // ie8/9 don't support FileList Object // http://stackoverflow.com/questions/12830058/ie8-input-type-file-get-files var file = _this.file = { uid: getUid(), name: target.value && target.value.substring(target.value.lastIndexOf('\\') + 1, target.value.length) }; _this.startUpload(); var _this3 = _this, props = _this3.props; if (!props.beforeUpload) { return _this.post(file); } var before = props.beforeUpload(file); if (before && before.then) { before.then(function () { _this.post(file); }, function () { _this.endUpload(); }); } else if (before !== false) { _this.post(file); } else { _this.endUpload(); } }, _this.saveIframe = function (node) { _this.iframe = node; }, _temp), _possibleConstructorReturn(_this, _ret); } _createClass(IframeUploader, [{ key: 'componentDidMount', value: function componentDidMount() { this.updateIframeWH(); this.initIframe(); } }, { key: 'componentDidUpdate', value: function componentDidUpdate() { this.updateIframeWH(); } }, { key: 'getIframeNode', value: function getIframeNode() { return this.iframe; } }, { key: 'getIframeDocument', value: function getIframeDocument() { return this.getIframeNode().contentDocument; } }, { key: 'getFormNode', value: function getFormNode() { return this.getIframeDocument().getElementById('form'); } }, { key: 'getFormInputNode', value: function getFormInputNode() { return this.getIframeDocument().getElementById('input'); } }, { key: 'getFormDataNode', value: function getFormDataNode() { return this.getIframeDocument().getElementById('data'); } }, { key: 'getFileForMultiple', value: function getFileForMultiple(file) { return this.props.multiple ? [file] : file; } }, { key: 'getIframeHTML', value: function getIframeHTML(domain) { var domainScript = ''; var domainInput = ''; if (domain) { var script = 'script'; domainScript = '<' + script + '>document.domain="' + domain + '";'; domainInput = ''; } return '\n \n \n \n \n \n ' + domainScript + '\n \n \n
\n \n ' + domainInput + '\n \n
\n \n \n '; } }, { key: 'initIframeSrc', value: function initIframeSrc() { if (this.domain) { this.getIframeNode().src = 'javascript:void((function(){\n var d = document;\n d.open();\n d.domain=\'' + this.domain + '\';\n d.write(\'\');\n d.close();\n })())'; } } }, { key: 'initIframe', value: function initIframe() { var iframeNode = this.getIframeNode(); var win = iframeNode.contentWindow; var doc = void 0; this.domain = this.domain || ''; this.initIframeSrc(); try { doc = win.document; } catch (e) { this.domain = document.domain; this.initIframeSrc(); win = iframeNode.contentWindow; doc = win.document; } doc.open('text/html', 'replace'); doc.write(this.getIframeHTML(this.domain)); doc.close(); this.getFormInputNode().onchange = this.onChange; } }, { key: 'endUpload', value: function endUpload() { if (this.state.uploading) { this.file = {}; // hack avoid batch this.state.uploading = false; this.setState({ uploading: false }); this.initIframe(); } } }, { key: 'startUpload', value: function startUpload() { if (!this.state.uploading) { this.state.uploading = true; this.setState({ uploading: true }); } } }, { key: 'updateIframeWH', value: function updateIframeWH() { var rootNode = ReactDOM.findDOMNode(this); var iframeNode = this.getIframeNode(); iframeNode.style.height = rootNode.offsetHeight + 'px'; iframeNode.style.width = rootNode.offsetWidth + 'px'; } }, { key: 'abort', value: function abort(file) { if (file) { var uid = file; if (file && file.uid) { uid = file.uid; } if (uid === this.file.uid) { this.endUpload(); } } else { this.endUpload(); } } }, { key: 'post', value: function post(file) { var _this4 = this; var formNode = this.getFormNode(); var dataSpan = this.getFormDataNode(); var data = this.props.data; var onStart = this.props.onStart; if (typeof data === 'function') { data = data(file); } var inputs = document.createDocumentFragment(); for (var key in data) { if (data.hasOwnProperty(key)) { var input = document.createElement('input'); input.setAttribute('name', key); input.value = data[key]; inputs.appendChild(input); } } dataSpan.appendChild(inputs); new Promise(function (resolve) { var action = _this4.props.action; if (typeof action === 'function') { return resolve(action(file)); } resolve(action); }).then(function (action) { formNode.setAttribute('action', action); formNode.submit(); dataSpan.innerHTML = ''; onStart(file); }); } }, { key: 'render', value: function render() { var _classNames; var _props = this.props, Tag = _props.component, disabled = _props.disabled, className = _props.className, prefixCls = _props.prefixCls, children = _props.children, style = _props.style; var iframeStyle = _extends({}, IFRAME_STYLE, { display: this.state.uploading || disabled ? 'none' : '' }); var cls = classNames((_classNames = {}, _defineProperty(_classNames, prefixCls, true), _defineProperty(_classNames, prefixCls + '-disabled', disabled), _defineProperty(_classNames, className, className), _classNames)); return React.createElement( Tag, { className: cls, style: _extends({ position: 'relative', zIndex: 0 }, style) }, React.createElement('iframe', { ref: this.saveIframe, onLoad: this.onLoad, style: iframeStyle }), children ); } }]); return IframeUploader; }(Component); IframeUploader.propTypes = { component: PropTypes.string, style: PropTypes.object, disabled: PropTypes.bool, prefixCls: PropTypes.string, className: PropTypes.string, accept: PropTypes.string, onStart: PropTypes.func, multiple: PropTypes.bool, children: PropTypes.any, data: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), action: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), name: PropTypes.string }; export default IframeUploader;