UNPKG

@eclipse-scout/core

Version:
184 lines (159 loc) 4.96 kB
/* * Copyright (c) 2010, 2023 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ import {arrays, dragAndDrop, DragAndDropHandler, FileInputEventMap, FileInputModel, files as fileUtil, InitModelOf, Widget} from '../index'; export class FileInput extends Widget implements FileInputModel { declare model: FileInputModel; declare eventMap: FileInputEventMap; declare self: FileInput; acceptTypes: string; maximumUploadSize: number; multiSelect: boolean; text: string; uploadController: Widget; files: File[]; $fileInput: JQuery<HTMLInputElement>; $text: JQuery; dragAndDropHandler: DragAndDropHandler; constructor() { super(); this.acceptTypes = null; this.maximumUploadSize = FileInput.DEFAULT_MAXIMUM_UPLOAD_SIZE; this.multiSelect = false; this.files = []; this.text = null; } /** * 50 MiB */ static DEFAULT_MAXIMUM_UPLOAD_SIZE = 50 * 1024 * 1024; protected override _init(model: InitModelOf<this>) { super._init(model); this.uploadController = model.uploadController || model.parent; } protected override _render() { this.$fileInput = this.$parent.makeElement('<input>') .attr('type', 'file') .on('change', this._onFileChange.bind(this)) as JQuery<HTMLInputElement>; this.$container = this.$parent.appendDiv('file-input input-field'); this.$fileInput.appendTo(this.$container); this.$container.on('mousedown', this._onMouseDown.bind(this)); this.$text = this.$container.appendDiv('file-input-text'); } protected override _renderProperties() { super._renderProperties(); this._renderText(); this._renderAcceptTypes(); this._renderMultiSelect(); } protected override _renderEnabled() { super._renderEnabled(); this._installOrUninstallDragAndDropHandler(); this.$container.setTabbable(this.enabledComputed); } setText(text: string) { this.setProperty('text', text); } protected _renderText() { let text = this.text || ''; this.$text.text(text); } setAcceptTypes(acceptTypes: string) { this.setProperty('acceptTypes', acceptTypes); } protected _renderAcceptTypes() { let acceptTypes = this.acceptTypes || ''; this.$fileInput.attr('accept', acceptTypes); } setMultiSelect(multiSelect: boolean) { this.setProperty('multiSelect', multiSelect); } protected _renderMultiSelect() { this.$fileInput.prop('multiple', this.multiSelect); } setMaximumUploadSize(maximumUploadSize: number) { this.setProperty('maximumUploadSize', maximumUploadSize); } protected override _remove() { dragAndDrop.uninstallDragAndDropHandler(this); super._remove(); } protected _installOrUninstallDragAndDropHandler() { dragAndDrop.installOrUninstallDragAndDropHandler( { target: this, onDrop: event => { if (event.files.length >= 1) { this.setFiles(event.files); } }, dropMaximumSize: () => this.maximumUploadSize, // disable file validation validateFiles: (files, defaultValidator) => { // nop } }); } clear() { this.setFiles([]); // _setFiles actually sets the text as well, but only if files have changed. // Make sure text is cleared as well if there are no files but a text set. this.setText(null); if (this.rendered) { this.$fileInput.val(null); } } setFiles(files: FileList | File[] | File) { let fileArray: File[]; if (files instanceof FileList) { fileArray = fileUtil.fileListToArray(files); } else { fileArray = arrays.ensure(files); } if (arrays.equals(this.files, fileArray)) { return; } let name = ''; if (fileArray.length > 0) { name = fileArray[0].name; } this.files = fileArray; this.setText(name); this.trigger('change', { files: fileArray }); } upload(): boolean { if (this.files.length === 0) { return true; } return this.session.uploadFiles(this.uploadController, this.files, undefined, this.maximumUploadSize); } browse() { // Trigger browser's file chooser this.$fileInput.trigger('click'); } protected _onFileChange(event: JQuery.ChangeEvent<HTMLInputElement>) { let files = this.$fileInput[0].files; if (files.length) { this.setFiles(files); } } protected _onMouseDown(event: JQuery.MouseDownEvent) { if (!this.enabled) { return; } this.browse(); } validateMaximumUploadSize(files: Blob | Blob[]) { if (!fileUtil.validateMaximumUploadSize(files, this.maximumUploadSize)) { throw fileUtil.getErrorMessageMaximumUploadSizeExceeded(this.session, this.maximumUploadSize); } } }