@bokeh/bokehjs
Version:
Interactive, novel data visualization
358 lines • 10.3 kB
JavaScript
import { input, textarea, select, option } from "../../../core/dom";
import { isInteger, isString } from "../../../core/util/types";
import { DOMComponentView } from "../../../core/dom_view";
import { Model } from "../../../model";
import { DTINDEX_NAME } from "./definitions";
import * as tables from "../../../styles/widgets/tables.css";
export class CellEditorView extends DOMComponentView {
static __name__ = "CellEditorView";
defaultValue;
get emptyValue() {
return null;
}
inputEl;
args;
constructor(options) {
const { model, parent } = options.column;
super({ model, parent, ...options });
this.args = options;
this.initialize(); // XXX: no build_views()
this.render(); // XXX: this isn't governed by layout
}
initialize() {
super.initialize();
this.inputEl = this._createInput();
this.defaultValue = null;
}
async lazy_initialize() {
throw new Error("unsupported");
}
css_classes() {
return super.css_classes().concat(tables.cell_editor);
}
render() {
this.args.container.append(this.el);
this.shadow_el.appendChild(this.inputEl);
this.renderEditor();
this.disableNavigation();
}
renderEditor() { }
disableNavigation() {
// XXX: without cast `event` is of non-specific type `Event`
this.inputEl.addEventListener("keydown", (event) => {
switch (event.key) {
case "ArrowLeft":
case "ArrowRight":
case "ArrowUp":
case "ArrowDown":
case "PageUp":
case "PageDown": {
event.stopImmediatePropagation();
break;
}
}
});
}
destroy() {
this.remove();
}
focus() {
this.inputEl.focus();
}
show() { }
hide() { }
position() { }
getValue() {
return this.inputEl.value;
}
setValue(val) {
this.inputEl.value = val;
}
serializeValue() {
return this.getValue();
}
isValueChanged() {
return !(this.getValue() == "" && this.defaultValue == null) && this.getValue() !== this.defaultValue;
}
applyValue(item, state) {
const grid_data = this.args.grid.getData();
const offset = grid_data.index.indexOf(item[DTINDEX_NAME]);
grid_data.setField(offset, this.args.column.field, state);
}
loadValue(item) {
const value = item[this.args.column.field];
this.defaultValue = value != null ? value : this.emptyValue;
this.setValue(this.defaultValue);
}
validateValue(value) {
if (this.args.column.validator) {
const result = this.args.column.validator(value);
if (!result.valid) {
return result;
}
}
return { valid: true, msg: null };
}
validate() {
return this.validateValue(this.getValue());
}
}
export class CellEditor extends Model {
static __name__ = "CellEditor";
}
export class StringEditorView extends CellEditorView {
static __name__ = "StringEditorView";
get emptyValue() {
return "";
}
_createInput() {
return input({ type: "text" });
}
renderEditor() {
//completions = @model.completions
//if completions.length != 0
// @inputEl.classList.add("bk-cell-editor-completion")
// $(@inputEl).autocomplete({source: completions})
// $(@inputEl).autocomplete("widget")
this.inputEl.focus();
this.inputEl.select();
}
loadValue(item) {
super.loadValue(item);
this.inputEl.defaultValue = this.defaultValue;
this.inputEl.select();
}
}
export class StringEditor extends CellEditor {
static __name__ = "StringEditor";
static {
this.prototype.default_view = StringEditorView;
this.define(({ Str, List }) => ({
completions: [List(Str), []],
}));
}
}
export class TextEditorView extends CellEditorView {
static __name__ = "TextEditorView";
_createInput() {
return textarea();
}
renderEditor() {
this.inputEl.focus();
this.inputEl.select();
}
}
export class TextEditor extends CellEditor {
static __name__ = "TextEditor";
static {
this.prototype.default_view = TextEditorView;
}
}
export class SelectEditorView extends CellEditorView {
static __name__ = "SelectEditorView";
_createInput() {
return select();
}
renderEditor() {
for (const opt of this.model.options) {
this.inputEl.appendChild(option({ value: opt }, opt));
}
this.focus();
}
}
export class SelectEditor extends CellEditor {
static __name__ = "SelectEditor";
static {
this.prototype.default_view = SelectEditorView;
this.define(({ Str, List }) => ({
options: [List(Str), []],
}));
}
}
export class PercentEditorView extends CellEditorView {
static __name__ = "PercentEditorView";
_createInput() {
return input({ type: "text" });
}
}
export class PercentEditor extends CellEditor {
static __name__ = "PercentEditor";
static {
this.prototype.default_view = PercentEditorView;
}
}
export class CheckboxEditorView extends CellEditorView {
static __name__ = "CheckboxEditorView";
_createInput() {
return input({ type: "checkbox" });
}
renderEditor() {
this.focus();
}
loadValue(item) {
this.defaultValue = !!item[this.args.column.field];
this.inputEl.checked = this.defaultValue;
}
serializeValue() {
return this.inputEl.checked;
}
}
export class CheckboxEditor extends CellEditor {
static __name__ = "CheckboxEditor";
static {
this.prototype.default_view = CheckboxEditorView;
}
}
export class IntEditorView extends CellEditorView {
static __name__ = "IntEditorView";
_createInput() {
return input({ type: "text" });
}
renderEditor() {
//$(@inputEl).spinner({step: @model.step})
this.inputEl.focus();
this.inputEl.select();
}
remove() {
//$(@inputEl).spinner("destroy")
super.remove();
}
serializeValue() {
const value = parseInt(this.getValue(), 10);
return isNaN(value) ? 0 : value;
}
loadValue(item) {
super.loadValue(item);
this.inputEl.defaultValue = this.defaultValue;
this.inputEl.select();
}
validateValue(value) {
if (isString(value)) {
value = Number(value);
}
if (isInteger(value)) {
return super.validateValue(value);
}
else {
return { valid: false, msg: "Please enter a valid integer" };
}
}
}
export class IntEditor extends CellEditor {
static __name__ = "IntEditor";
static {
this.prototype.default_view = IntEditorView;
this.define(({ Int }) => ({
step: [Int, 1],
}));
}
}
export class NumberEditorView extends CellEditorView {
static __name__ = "NumberEditorView";
_createInput() {
return input({ type: "text" });
}
renderEditor() {
//$(@inputEl).spinner({step: @model.step})
this.inputEl.focus();
this.inputEl.select();
}
remove() {
//$(@inputEl).spinner("destroy")
super.remove();
}
serializeValue() {
const value = parseFloat(this.getValue());
return isNaN(value) ? 0.0 : value;
}
loadValue(item) {
super.loadValue(item);
this.inputEl.defaultValue = this.defaultValue;
this.inputEl.select();
}
validateValue(value) {
if (isNaN(value)) {
return { valid: false, msg: "Please enter a valid number" };
}
else {
return super.validateValue(value);
}
}
}
export class NumberEditor extends CellEditor {
static __name__ = "NumberEditor";
static {
this.prototype.default_view = NumberEditorView;
this.define(({ Float }) => ({
step: [Float, 0.01],
}));
}
}
export class TimeEditorView extends CellEditorView {
static __name__ = "TimeEditorView";
_createInput() {
return input({ type: "text" });
}
}
export class TimeEditor extends CellEditor {
static __name__ = "TimeEditor";
static {
this.prototype.default_view = TimeEditorView;
}
}
export class DateEditorView extends CellEditorView {
static __name__ = "DateEditorView";
_createInput() {
return input({ type: "text" });
}
get emptyValue() {
return new Date();
}
renderEditor() {
//this.calendarOpen = false
//@$datepicker = $(@inputEl).datepicker({
// showOn: "button"
// buttonImageOnly: true
// beforeShow: () => @calendarOpen = true
// onClose: () => @calendarOpen = false
//})
//@$datepicker.siblings(".ui-datepicker-trigger").css("vertical-align": "middle")
//@$datepicker.width(@$datepicker.width() - (14 + 2*4 + 4)) # img width + margins + edge distance
this.inputEl.focus();
this.inputEl.select();
}
destroy() {
//$.datepicker.dpDiv.stop(true, true)
//@$datepicker.datepicker("hide")
//@$datepicker.datepicker("destroy")
super.destroy();
}
show() {
//if @calendarOpen
// $.datepicker.dpDiv.stop(true, true).show()
super.show();
}
hide() {
//if @calendarOpen
// $.datepicker.dpDiv.stop(true, true).hide()
super.hide();
}
position( /*_position*/) {
//if @calendarOpen
// $.datepicker.dpDiv.css(top: position.top + 30, left: position.left)
return super.position();
}
getValue() {
//return @$datepicker.datepicker("getDate").getTime()
}
setValue(_val) {
//@$datepicker.datepicker("setDate", new Date(val))
}
}
export class DateEditor extends CellEditor {
static __name__ = "DateEditor";
static {
this.prototype.default_view = DateEditorView;
}
}
//# sourceMappingURL=cell_editors.js.map