UNPKG

10.8 kBJavaScriptView Raw
1function _typeof(obj) {
2 if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
3 _typeof = function _typeof(obj) {
4 return typeof obj;
5 };
6 } else {
7 _typeof = function _typeof(obj) {
8 return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
9 };
10 }
11
12 return _typeof(obj);
13}
14
15function _classCallCheck(instance, Constructor) {
16 if (!(instance instanceof Constructor)) {
17 throw new TypeError("Cannot call a class as a function");
18 }
19}
20
21function _defineProperties(target, props) {
22 for (var i = 0; i < props.length; i++) {
23 var descriptor = props[i];
24 descriptor.enumerable = descriptor.enumerable || false;
25 descriptor.configurable = true;
26 if ("value" in descriptor) descriptor.writable = true;
27 Object.defineProperty(target, descriptor.key, descriptor);
28 }
29}
30
31function _createClass(Constructor, protoProps, staticProps) {
32 if (protoProps) _defineProperties(Constructor.prototype, protoProps);
33 if (staticProps) _defineProperties(Constructor, staticProps);
34 return Constructor;
35}
36
37function _possibleConstructorReturn(self, call) {
38 if (call && (_typeof(call) === "object" || typeof call === "function")) {
39 return call;
40 }
41
42 return _assertThisInitialized(self);
43}
44
45function _assertThisInitialized(self) {
46 if (self === void 0) {
47 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
48 }
49
50 return self;
51}
52
53function _getPrototypeOf(o) {
54 _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
55 return o.__proto__ || Object.getPrototypeOf(o);
56 };
57 return _getPrototypeOf(o);
58}
59
60function _inherits(subClass, superClass) {
61 if (typeof superClass !== "function" && superClass !== null) {
62 throw new TypeError("Super expression must either be null or a function");
63 }
64
65 subClass.prototype = Object.create(superClass && superClass.prototype, {
66 constructor: {
67 value: subClass,
68 writable: true,
69 configurable: true
70 }
71 });
72 if (superClass) _setPrototypeOf(subClass, superClass);
73}
74
75function _setPrototypeOf(o, p) {
76 _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
77 o.__proto__ = p;
78 return o;
79 };
80
81 return _setPrototypeOf(o, p);
82}
83/**
84 * Copyright IBM Corp. 2016, 2018
85 *
86 * This source code is licensed under the Apache-2.0 license found in the
87 * LICENSE file in the root directory of this source tree.
88 */
89
90
91import { componentsX } from '../../globals/js/feature-flags';
92import settings from '../../globals/js/settings';
93import mixin from '../../globals/js/misc/mixin';
94import createComponent from '../../globals/js/mixins/create-component';
95import initComponentBySearch from '../../globals/js/mixins/init-component-by-search';
96import eventedState from '../../globals/js/mixins/evented-state';
97import handles from '../../globals/js/mixins/handles';
98import eventMatches from '../../globals/js/misc/event-matches';
99import on from '../../globals/js/misc/on';
100
101var toArray = function toArray(arrayLike) {
102 return Array.prototype.slice.call(arrayLike);
103};
104
105var FileUploader =
106/*#__PURE__*/
107function (_mixin) {
108 _inherits(FileUploader, _mixin);
109 /**
110 * File uploader.
111 * @extends CreateComponent
112 * @extends InitComponentBySearch
113 * @extends eventedState
114 * @extends Handles
115 * @param {HTMLElement} element The element working as a file uploader.
116 * @param {Object} [options] The component options. See static options.
117 */
118
119
120 function FileUploader(element) {
121 var _this;
122
123 var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
124
125 _classCallCheck(this, FileUploader);
126
127 _this = _possibleConstructorReturn(this, _getPrototypeOf(FileUploader).call(this, element, options));
128
129 _this._changeState = function (state, detail, callback) {
130 if (state === 'delete-filename-fileuploader') {
131 _this.container.removeChild(detail.filenameElement);
132 }
133
134 if (typeof callback === 'function') {
135 callback();
136 }
137 };
138
139 _this._handleDeleteButton = function (evt) {
140 var target = eventMatches(evt, "[data-for=".concat(_this.inputId, "]"));
141
142 if (target) {
143 _this._changeState('delete-filename-fileuploader', {
144 initialEvt: evt,
145 filenameElement: target.parentNode
146 });
147 }
148 };
149
150 _this.input = _this.element.querySelector(_this.options.selectorInput);
151 _this.container = _this.element.querySelector(_this.options.selectorContainer);
152
153 if (!_this.input) {
154 throw new TypeError('Cannot find the file input box.');
155 }
156
157 if (!_this.container) {
158 throw new TypeError('Cannot find the file names container.');
159 }
160
161 _this.inputId = _this.input.getAttribute('id');
162
163 _this.manage(on(_this.input, 'change', function () {
164 return _this._displayFilenames();
165 }));
166
167 _this.manage(on(_this.container, 'click', _this._handleDeleteButton));
168
169 return _this;
170 }
171
172 _createClass(FileUploader, [{
173 key: "_filenamesHTML",
174 value: function _filenamesHTML(name, id) {
175 return "<span class=\"".concat(this.options.classSelectedFile, "\">\n <p class=\"").concat(this.options.classFileName, "\">").concat(name, "</p>\n <span data-for=\"").concat(id, "\" class=\"").concat(this.options.classStateContainer, "\"></span>\n </span>");
176 }
177 }, {
178 key: "_uploadHTML",
179 value: function _uploadHTML() {
180 return "\n <div data-loading class=\"".concat(this.options.classLoading, "\">\n <svg class=\"").concat(this.options.classLoadingSvg, "\" viewBox=\"-42 -42 84 84\">\n <circle cx=\"0\" cy=\"0\" r=\"37.5\" />\n </svg>\n </div>");
181 }
182 }, {
183 key: "_closeButtonHTML",
184 value: function _closeButtonHTML() {
185 if (componentsX) {
186 return "\n <button class=\"".concat(this.options.classFileClose, "\" type=\"button\" aria-label=\"close\">\n <svg aria-hidden=\"true\" viewBox=\"0 0 16 16\" width=\"16\" height=\"16\">\n <path fill=\"#231F20\" d=\"M12 4.7l-.7-.7L8 7.3 4.7 4l-.7.7L7.3 8 4 11.3l.7.7L8 8.7l3.3 3.3.7-.7L8.7 8z\"/>\n </svg>\n </button>");
187 }
188
189 return "\n <svg class=\"".concat(this.options.classFileClose, "\" tabindex=\"0\" viewBox=\"0 0 16 16\" fill-rule=\"evenodd\" width=\"16\" height=\"16\">\n <path d=\"M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3.5 10.1l-1.4 1.4L8\n 9.4l-2.1 2.1-1.4-1.4L6.6 8 4.5 5.9l1.4-1.4L8 6.6l2.1-2.1 1.4 1.4L9.4 8l2.1 2.1z\" />\n </svg>");
190 }
191 }, {
192 key: "_checkmarkHTML",
193 value: function _checkmarkHTML() {
194 return "\n <svg class=\"".concat(this.options.classFileComplete, "\" viewBox=\"0 0 16 16\" fill-rule=\"evenodd\" width=\"16\" height=\"16\">\n <path d=\"M8 0C3.6 0 0 3.6 0 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zM6.7 11.5L3.4 8.1l1.4-1.4 1.9 1.9 4.1-4.1 1.4 1.4-5.5 5.6z\"/>\n </svg>");
195 }
196 }, {
197 key: "_getStateContainers",
198 value: function _getStateContainers() {
199 var stateContainers = toArray(this.element.querySelectorAll("[data-for=".concat(this.inputId, "]")));
200
201 if (stateContainers.length === 0) {
202 throw new TypeError('State container elements not found; invoke _displayFilenames() first');
203 }
204
205 if (stateContainers[0].dataset.for !== this.inputId) {
206 throw new TypeError('File input id must equal [data-for] attribute');
207 }
208
209 return stateContainers;
210 }
211 /**
212 * Inject selected files into DOM. Invoked on change event.
213 */
214
215 }, {
216 key: "_displayFilenames",
217 value: function _displayFilenames() {
218 var _this2 = this;
219
220 var container = this.element.querySelector(this.options.selectorContainer);
221 var HTMLString = toArray(this.input.files).map(function (file) {
222 return _this2._filenamesHTML(file.name, _this2.inputId);
223 }).join('');
224 container.insertAdjacentHTML('afterbegin', HTMLString);
225 }
226 }, {
227 key: "_removeState",
228 value: function _removeState(element) {
229 if (!element || element.nodeType !== Node.ELEMENT_NODE) {
230 throw new TypeError('DOM element should be given to initialize this widget.');
231 }
232
233 while (element.firstChild) {
234 element.removeChild(element.firstChild);
235 }
236 }
237 }, {
238 key: "_handleStateChange",
239 value: function _handleStateChange(elements, selectIndex, html) {
240 var _this3 = this;
241
242 if (selectIndex === undefined) {
243 elements.forEach(function (el) {
244 _this3._removeState(el);
245
246 el.insertAdjacentHTML('beforeend', html);
247 });
248 } else {
249 elements.forEach(function (el, index) {
250 if (index === selectIndex) {
251 _this3._removeState(el);
252
253 el.insertAdjacentHTML('beforeend', html);
254 }
255 });
256 }
257 }
258 /**
259 * Handles delete button.
260 * @param {Event} evt The event triggering this action.
261 * @private
262 */
263
264 }, {
265 key: "setState",
266 value: function setState(state, selectIndex) {
267 var stateContainers = this._getStateContainers();
268
269 if (state === 'edit') {
270 this._handleStateChange(stateContainers, selectIndex, this._closeButtonHTML());
271 }
272
273 if (state === 'upload') {
274 this._handleStateChange(stateContainers, selectIndex, this._uploadHTML());
275 }
276
277 if (state === 'complete') {
278 this._handleStateChange(stateContainers, selectIndex, this._checkmarkHTML());
279 }
280 }
281 /**
282 * The map associating DOM element and file uploader instance.
283 * @member FileUploader.components
284 * @type {WeakMap}
285 */
286
287 }], [{
288 key: "options",
289 get: function get() {
290 var prefix = settings.prefix;
291 return {
292 selectorInit: '[data-file]',
293 selectorInput: "input[type=\"file\"].".concat(prefix, "--file-input"),
294 selectorContainer: '[data-file-container]',
295 selectorCloseButton: ".".concat(prefix, "--file-close"),
296 classLoading: "".concat(prefix, "--loading"),
297 classLoadingSvg: "".concat(prefix, "--loading__svg"),
298 classFileName: "".concat(prefix, "--file-filename"),
299 classFileClose: "".concat(prefix, "--file-close"),
300 classFileComplete: "".concat(prefix, "--file-complete"),
301 classSelectedFile: "".concat(prefix, "--file__selected-file"),
302 classStateContainer: "".concat(prefix, "--file__state-container"),
303 eventBeforeDeleteFilenameFileuploader: 'fileuploader-before-delete-filename',
304 eventAfterDeleteFilenameFileuploader: 'fileuploader-after-delete-filename'
305 };
306 }
307 }]);
308
309 FileUploader.components = new WeakMap();
310 return FileUploader;
311}(mixin(createComponent, initComponentBySearch, eventedState, handles));
312
313export default FileUploader;
\No newline at end of file