UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

150 lines 5.61 kB
import { Indicator, IndicatorView } from "./indicator"; import { Signal0 } from "../../core/signaling"; import { div } from "../../core/dom"; import { Orientation } from "../../core/enums"; import { Enum } from "../../core/kinds"; import { clamp } from "../../core/util/math"; import { process_placeholders, sprintf } from "../../core/util/templating"; import * as progress_css from "../../styles/widgets/progress.css"; const ProgressMode = Enum("determinate", "indeterminate"); const LabelLocation = Enum("none", "inline"); export class ProgressView extends IndicatorView { static __name__ = "ProgressView"; label_el; value_el; bar_el; connect_signals() { super.connect_signals(); const { mode, value, min, max, label, reversed, orientation, disabled, label_location, description } = this.model.properties; this.on_change([mode, value, min, max, label, description], () => this._update_value()); this.on_change(reversed, () => this._update_reversed()); this.on_change(orientation, () => this._update_orientation()); this.on_change(disabled, () => this._update_disabled()); this.on_change(label_location, () => this._update_label_location()); } stylesheets() { return [...super.stylesheets(), progress_css.default]; } render() { super.render(); this.el.role = "progress"; this.label_el = div({ class: progress_css.label }); this.value_el = div({ class: progress_css.value }); this.bar_el = div({ class: progress_css.bar }, this.value_el, this.label_el); this._update_value(); this._update_disabled(); this._update_reversed(); this._update_orientation(); this._update_label_location(); this.shadow_el.append(this.bar_el); } _update_value() { const { value, min, max, label } = this.model; const total = Math.abs(max - min); const index = clamp(value, min, max) - min; const percent = index / total * 100; const indeterminate = this.model.indeterminate || !isFinite(percent); this.class_list.toggle(progress_css.indeterminate, indeterminate); this.value_el.style.setProperty("--progress", `${indeterminate ? 0 : percent}%`); const replacer = (_, name, format) => { const val = (() => { switch (name) { case "min": return min; case "max": return max; case "total": return total; case "value": return value; case "index": return index; case "percent": return percent; // TODO duration, throughput, ETA default: return null; } })(); if (val == null) { return val; } else { return format != null ? sprintf(format, val) : val.toFixed(0); } }; this.label_el.textContent = (() => { if (label != null && !indeterminate) { return process_placeholders(label, replacer); } else { return "0%"; } })(); this.bar_el.title = (() => { const { description } = this.model; if (description != null && !indeterminate) { return process_placeholders(description, replacer); } else { return ""; } })(); } _update_disabled() { const { disabled } = this.model; this.class_list.toggle(progress_css.disabled, disabled); } _update_reversed() { const { reversed } = this.model; this.class_list.toggle(progress_css.reversed, reversed); } _update_orientation() { const { orientation } = this.model; this.class_list.toggle(progress_css.horizontal, orientation == "horizontal"); this.class_list.toggle(progress_css.vertical, orientation == "vertical"); } _update_label_location() { const { label, label_location } = this.model; this.label_el.classList.toggle(progress_css.hidden, label == null || label_location == "none"); } } export class Progress extends Indicator { static __name__ = "Progress"; finished = new Signal0(this, "finished"); constructor(attrs) { super(attrs); } static { this.prototype.default_view = ProgressView; this.define(({ Bool, Int, Str, Nullable }) => ({ mode: [ProgressMode, "determinate"], value: [Int, 0], min: [Int, 0], max: [Int, 100], reversed: [Bool, false], orientation: [Orientation, "horizontal"], label: [Nullable(Str), "@{percent}%"], label_location: [LabelLocation, "inline"], description: [Nullable(Str), null], })); } get indeterminate() { return this.mode == "indeterminate"; } get has_finished() { return !this.indeterminate && this.value == this.max; } update(n) { if (this.indeterminate) { return false; } const { value, min, max } = this; this.value = clamp(value + n, min, max); const { has_finished } = this; if (has_finished) { this.finished.emit(); } return has_finished; } increment(n = 1) { return this.update(n); } decrement(n = 1) { this.update(-n); } } //# sourceMappingURL=progress.js.map