@bokeh/bokehjs
Version:
Interactive, novel data visualization
161 lines • 6.26 kB
JavaScript
import noUiSlider from "nouislider";
import * as p from "../../../core/properties";
import { div, span, empty } from "../../../core/dom";
import { repeat } from "../../../core/util/array";
import { color2css } from "../../../core/util/color";
import { OrientedControl, OrientedControlView } from "../oriented_control";
import sliders_css, * as sliders from "../../../styles/widgets/sliders.css";
import nouislider_css from "../../../styles/widgets/nouislider.css";
import * as inputs from "../../../styles/widgets/inputs.css";
export class AbstractSliderView extends OrientedControlView {
static __name__ = "AbstractSliderView";
behaviour;
connected = false;
group_el;
slider_el;
title_el;
_auto_width = "auto";
_auto_height = "auto";
*controls() {
yield this.slider_el;
}
_noUiSlider;
get _steps() {
return this._noUiSlider.steps;
}
_update_slider() {
this._noUiSlider.updateOptions(this._calc_to(), true);
}
connect_signals() {
super.connect_signals();
const { direction, orientation, tooltips } = this.model.properties;
this.on_change([direction, orientation, tooltips], () => this.rerender());
const { bar_color } = this.model.properties;
this.on_change(bar_color, () => {
this._set_bar_color();
});
const { value, title, show_value } = this.model.properties;
this.on_change([value, title, show_value], () => this._update_title());
this.on_change(value, () => this._update_slider());
}
stylesheets() {
return [...super.stylesheets(), nouislider_css, sliders_css];
}
_update_title() {
empty(this.title_el);
const hide_header = this.model.title == null || (this.model.title.length == 0 && !this.model.show_value);
this.title_el.style.display = hide_header ? "none" : "";
if (!hide_header) {
const { title } = this.model;
if (title != null && title.length > 0) {
if (this.contains_tex_string(title)) {
this.title_el.innerHTML = `${this.process_tex(title)}: `;
}
else {
this.title_el.textContent = `${title}: `;
}
}
if (this.model.show_value) {
const { start } = this._calc_to();
const pretty = start.map((v) => this.pretty(v)).join(" .. ");
this.title_el.appendChild(span({ class: sliders.slider_value }, pretty));
}
}
}
_set_bar_color() {
if (this.connected !== false && !this.model.disabled && this.slider_el != null) {
const connect_el = this.slider_el.querySelector(".noUi-connect");
connect_el.style.backgroundColor = color2css(this.model.bar_color);
}
}
render() {
super.render();
let tooltips;
if (this.model.tooltips) {
const formatter = {
to: (value) => this.pretty(value),
};
const { start } = this._calc_to();
tooltips = repeat(formatter, start.length);
}
else {
tooltips = null;
}
if (this.slider_el == null) {
this.slider_el = div();
this._noUiSlider = noUiSlider.create(this.slider_el, {
...this._calc_to(),
behaviour: this.behaviour,
connect: this.connected,
tooltips: tooltips ?? false,
orientation: this.model.orientation,
direction: this.model.direction,
});
this._noUiSlider.on("slide", (_, __, values) => this._slide(values));
this._noUiSlider.on("change", (_, __, values) => this._change(values));
const toggle_tooltip = (i, show) => {
if (tooltips == null || this.slider_el == null) {
return;
}
const handle = this.slider_el.querySelectorAll(".noUi-handle")[i];
const tooltip = handle.querySelector(".noUi-tooltip");
tooltip.style.display = show ? "block" : "";
};
this._noUiSlider.on("start", () => this._toggle_user_select(false));
this._noUiSlider.on("end", () => this._toggle_user_select(true));
this._noUiSlider.on("start", (_, i) => toggle_tooltip(i, true));
this._noUiSlider.on("end", (_, i) => toggle_tooltip(i, false));
}
else {
this._update_slider();
}
this._set_bar_color();
if (this.model.disabled) {
this.slider_el.setAttribute("disabled", "true");
}
else {
this.slider_el.removeAttribute("disabled");
}
this.title_el = div({ class: sliders.slider_title });
this._update_title();
this.group_el = div({ class: inputs.input_group }, this.title_el, this.slider_el);
this.shadow_el.appendChild(this.group_el);
this._has_finished = true;
}
_toggle_user_select(enable) {
const { style } = document.body;
const value = enable ? "" : "none";
style.userSelect = value;
style.webkitUserSelect = value;
}
_slide(values) {
this.model.value = this._calc_from(values);
}
_change(values) {
const value = this._calc_from(values);
this.model.setv({ value, value_throttled: value });
}
}
export class AbstractSlider extends OrientedControl {
static __name__ = "AbstractSlider";
constructor(attrs) {
super(attrs);
}
static {
this.define(({ Unknown, Bool, Str, Color, Enum, Nullable }) => {
return {
title: [Nullable(Str), ""],
show_value: [Bool, true],
value: [Unknown],
value_throttled: [Unknown, p.unset, { readonly: true }],
direction: [Enum("ltr", "rtl"), "ltr"],
tooltips: [Bool, true],
bar_color: [Color, "#e6e6e6"],
};
});
this.override({
width: 300, // sliders don't have any intrinsic width
});
}
}
//# sourceMappingURL=abstract_slider.js.map