UNPKG

uikit

Version:

UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.

203 lines (154 loc) 4.9 kB
import {addClass, ajax, matches, noop, on, removeClass, trigger} from 'uikit-util'; export default { props: { allow: String, clsDragover: String, concurrent: Number, maxSize: Number, method: String, mime: String, msgInvalidMime: String, msgInvalidName: String, msgInvalidSize: String, multiple: Boolean, name: String, params: Object, type: String, url: String }, data: { allow: false, clsDragover: 'uk-dragover', concurrent: 1, maxSize: 0, method: 'POST', mime: false, msgInvalidMime: 'Invalid File Type: %s', msgInvalidName: 'Invalid File Name: %s', msgInvalidSize: 'Invalid File Size: %s Kilobytes Max', multiple: false, name: 'files[]', params: {}, type: '', url: '', abort: noop, beforeAll: noop, beforeSend: noop, complete: noop, completeAll: noop, error: noop, fail: noop, load: noop, loadEnd: noop, loadStart: noop, progress: noop }, events: { change(e) { if (!matches(e.target, 'input[type="file"]')) { return; } e.preventDefault(); if (e.target.files) { this.upload(e.target.files); } e.target.value = ''; }, drop(e) { stop(e); const transfer = e.dataTransfer; if (!transfer || !transfer.files) { return; } removeClass(this.$el, this.clsDragover); this.upload(transfer.files); }, dragenter(e) { stop(e); }, dragover(e) { stop(e); addClass(this.$el, this.clsDragover); }, dragleave(e) { stop(e); removeClass(this.$el, this.clsDragover); } }, methods: { upload(files) { if (!files.length) { return; } trigger(this.$el, 'upload', [files]); for (let i = 0; i < files.length; i++) { if (this.maxSize && this.maxSize * 1000 < files[i].size) { this.fail(this.msgInvalidSize.replace('%s', this.maxSize)); return; } if (this.allow && !match(this.allow, files[i].name)) { this.fail(this.msgInvalidName.replace('%s', this.allow)); return; } if (this.mime && !match(this.mime, files[i].type)) { this.fail(this.msgInvalidMime.replace('%s', this.mime)); return; } } if (!this.multiple) { files = [files[0]]; } this.beforeAll(this, files); const chunks = chunk(files, this.concurrent); const upload = files => { const data = new FormData(); files.forEach(file => data.append(this.name, file)); for (const key in this.params) { data.append(key, this.params[key]); } ajax(this.url, { data, method: this.method, responseType: this.type, beforeSend: env => { const {xhr} = env; xhr.upload && on(xhr.upload, 'progress', this.progress); ['loadStart', 'load', 'loadEnd', 'abort'].forEach(type => on(xhr, type.toLowerCase(), this[type]) ); return this.beforeSend(env); } }).then( xhr => { this.complete(xhr); if (chunks.length) { upload(chunks.shift()); } else { this.completeAll(xhr); } }, e => this.error(e) ); }; upload(chunks.shift()); } } }; function match(pattern, path) { return path.match(new RegExp(`^${pattern.replace(/\//g, '\\/').replace(/\*\*/g, '(\\/[^\\/]+)*').replace(/\*/g, '[^\\/]+').replace(/((?!\\))\?/g, '$1.')}$`, 'i')); } function chunk(files, size) { const chunks = []; for (let i = 0; i < files.length; i += size) { const chunk = []; for (let j = 0; j < size; j++) { chunk.push(files[i + j]); } chunks.push(chunk); } return chunks; } function stop(e) { e.preventDefault(); e.stopPropagation(); }