UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

112 lines 4.06 kB
import { InputWidget, InputWidgetView, ClearInput } from "./input_widget"; import { input } from "../../core/dom"; import { isString } from "../../core/util/types"; import * as p from "../../core/properties"; import * as inputs from "../../styles/widgets/inputs.css"; import buttons_css from "../../styles/buttons.css"; export class FileInputView extends InputWidgetView { static __name__ = "FileInputView"; connect_signals() { super.connect_signals(); this.model.on_event(ClearInput, () => { this.model.setv({ value: "", // p.unset, mime_type: "", // p.unset, filename: "", // p.unset, }); this.input_el.value = ""; }); } stylesheets() { return [...super.stylesheets(), buttons_css]; } _render_input() { const { multiple, disabled, directory } = this.model; const accept = (() => { const { accept } = this.model; return isString(accept) ? accept : accept.join(","); })(); return this.input_el = input({ type: "file", class: inputs.input, multiple, accept, disabled, webkitdirectory: directory }); } render() { super.render(); this.input_el.addEventListener("change", async () => { const { files } = this.input_el; if (files != null) { await this.load_files(files); } }); } async load_files(files) { const values = []; const filenames = []; const mime_types = []; const { directory, multiple } = this.model; const accept = (() => { const { accept } = this.model; return isString(accept) ? accept : accept.join(","); })(); for (const file of files) { const data_url = await this._read_file(file); const [, mime_type = "", , value = ""] = data_url.split(/[:;,]/, 4); if (directory) { const ext = file.name.split(".").pop(); if ((accept.length > 0 && isString(ext)) ? accept.includes(`.${ext}`) : true) { filenames.push(file.webkitRelativePath); values.push(value); mime_types.push(mime_type); } } else { filenames.push(file.name); values.push(value); mime_types.push(mime_type); } } const [value, filename, mime_type] = (() => { if (directory || multiple) { return [values, filenames, mime_types]; } else if (files.length != 0) { return [values[0], filenames[0], mime_types[0]]; } else { return ["", "", ""]; } })(); this.model.setv({ value, filename, mime_type }); } _read_file(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => { const { result } = reader; if (result != null) { resolve(result); } else { reject(reader.error ?? new Error(`unable to read '${file.name}'`)); } }; reader.readAsDataURL(file); }); } } export class FileInput extends InputWidget { static __name__ = "FileInput"; constructor(attrs) { super(attrs); } static { this.prototype.default_view = FileInputView; this.define(({ Bool, Str, List, Or }) => ({ value: [Or(Str, List(Str)), p.unset, { readonly: true }], mime_type: [Or(Str, List(Str)), p.unset, { readonly: true }], filename: [Or(Str, List(Str)), p.unset, { readonly: true }], accept: [Or(Str, List(Str)), ""], multiple: [Bool, false], directory: [Bool, false], })); } } //# sourceMappingURL=file_input.js.map