Skip to content

Commit

Permalink
corrections post bokeh#8085
Browse files Browse the repository at this point in the history
  • Loading branch information
xavArtley committed Feb 2, 2019
1 parent 904fd7b commit d45689c
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 91 deletions.
53 changes: 17 additions & 36 deletions bokehjs/src/lib/models/widgets/color_picker.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,57 @@
import {logger} from "core/logging"
import * as p from "core/properties"
import {empty, label, input} from 'core/dom'
import {input} from 'core/dom'
import {InputWidget, InputWidgetView} from 'models/widgets/input_widget'
import {Color} from 'core/types'


export class ColorPickerView extends InputWidgetView {
model: ColorPicker

protected inputEl: HTMLInputElement

initialize(options: any): void {
super.initialize(options)
this.render()
}
protected input: HTMLInputElement

connect_signals(): void {
super.connect_signals()
this.connect(this.model.change, () => this.render())
this.connect(this.model.properties.name.change, () => this.input.name = this.model.name || "")
this.connect(this.model.properties.color.change, () => this.input.value = this.model.color)
this.connect(this.model.properties.disabled.change, () => this.input.disabled = this.model.disabled)
}

render(): void {
super.render()

empty(this.el)

const labelEl = label({for: this.model.id}, this.model.title)
this.el.appendChild(labelEl)

this.inputEl = input({
class: "bk-widget-form-input",
id: this.model.id,
this.input = input({
type: "color",
class: "bk-input",
name: this.model.name,
value: this.model.color,
disabled: this.model.disabled,
type: "color",
})

this.inputEl.append(this.model.color)
this.inputEl.addEventListener("change", () => this.change_input())
this.el.appendChild(this.inputEl)

// TODO - This 35 is a hack we should be able to compute it
if (this.model.width)
this.inputEl.style.width = `${this.model.width - 35}px`

// TODO - This 35 is a hack we should be able to compute it
if (this.model.height)
this.inputEl.style.height = `${this.model.height - 35}px`
this.input.addEventListener("change", () => this.change_input())
this.el.appendChild(this.input)
}

change_input(): void {
const color = this.inputEl.value
logger.debug(`widget/text_input: value = ${color}`)
this.model.color = color
this.model.color = this.input.value
super.change_input()
}

}

export namespace ColorPicker {
export interface Attrs extends InputWidget.Attrs {
color: Color
}
export interface Props extends InputWidget.Props {}

export interface Props extends InputWidget.Props {
color: p.Property<Color>
}
}

export interface ColorPicker extends ColorPicker.Attrs {}

export class ColorPicker extends InputWidget {

properties: ColorPicker.Props

static initClass(): void {
this.prototype.type = "ColorPicker"
this.prototype.default_view = ColorPickerView
Expand All @@ -79,5 +61,4 @@ export class ColorPicker extends InputWidget {
})
}
}

ColorPicker.initClass()
56 changes: 25 additions & 31 deletions bokehjs/src/lib/models/widgets/spinner.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as p from "core/properties"
import {empty, input, label} from 'core/dom'
import {input} from 'core/dom'
import {InputWidget, InputWidgetView} from 'models/widgets/input_widget'

function log10(x: number): number{
function log10(x: number): number {
if (Math.log10) {
return Math.log10(x)
} else {
Expand All @@ -13,52 +13,39 @@ function log10(x: number): number{
export class SpinnerView extends InputWidgetView {
model: Spinner

protected inputEl: HTMLInputElement

initialize(options: any): void {
super.initialize(options)
this.render()
}
protected input: HTMLInputElement

connect_signals(): void {
super.connect_signals()
this.connect(this.model.change, () => this.render())
this.connect(this.model.properties.name.change, () => this.input.name = this.model.name || "")
this.connect(this.model.properties.low.change, () => this.input.min = this.model.low.toFixed(log10(1 / this.model.step)))
this.connect(this.model.properties.high.change, () => this.input.max = this.model.high.toFixed(log10(1 / this.model.step)))
this.connect(this.model.properties.step.change, () => this.input.step = this.model.value.toFixed(log10(1 / this.model.step)))
this.connect(this.model.properties.value.change, () => this.input.value = this.model.value.toFixed(log10(1 / this.model.step)))
this.connect(this.model.properties.disabled.change, () => this.input.disabled = this.model.disabled)
}

render(): void {
super.render()

empty(this.el)

const labelEl = label({for: this.model.id}, this.model.title)
this.el.appendChild(labelEl)

this.inputEl = input({
class: "bk-widget-form-input",
id: this.model.id,
this.input = input({
type: "number",
class: "bk-input",
name: this.model.name,
min: this.model.low,
max: this.model.high,
value: this.model.value,
step: this.model.step,
disabled: this.model.disabled,
type: "number",
})
this.inputEl.addEventListener("change", () => this.change_input())
this.el.appendChild(this.inputEl)

// TODO - This 35 is a hack we should be able to compute it
if (this.model.width)
this.inputEl.style.width = `${this.model.width - 35}px`

// TODO - This 35 is a hack we should be able to compute it
if (this.model.height)
this.inputEl.style.height = `${this.model.height - 35}px`
this.input.addEventListener("change", () => this.change_input())
//this.input.addEventListener("input", () => this.change_input())
this.el.appendChild(this.input)
}

change_input(): void {
const {step, low, high} = this.model
const new_value = Number(this.inputEl.value)
const new_value = Number(this.input.value)
let process_value
if (low != null) {
process_value = low + step * Math.round((new_value - low) / step)
Expand All @@ -71,7 +58,7 @@ export class SpinnerView extends InputWidgetView {
if (high != null) {
process_value = Math.min(process_value, high)
}
this.model.value = Number(process_value.toFixed(log10(1/step)))
this.model.value = Number(process_value.toFixed(log10(1 / step)))

if (this.model.value != new_value) {
//this is needeed when the current value in the intput is already at bounded value
Expand All @@ -91,13 +78,20 @@ export namespace Spinner {
high: number
step: number
}
export interface Props extends InputWidget.Props {}
export interface Props extends InputWidget.Props {
value: p.Property<number>
low: p.Property<number>
high: p.Property<number>
step: p.Property<number>
}
}

export interface Spinner extends Spinner.Attrs {}

export class Spinner extends InputWidget {

properties: Spinner.Props

static initClass(): void {
this.prototype.type = "Spinner"
this.prototype.default_view = SpinnerView
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
cds = ColumnDataSource(data=dict(x=(0, 1), y=(0, 1)))

p = Figure(x_range=(0, 1), y_range=(0, 1))
w = ColorPicker(title="Line Color", color="red", height=50, width=100)
w = ColorPicker(title="Line Color", color="red", height=20, width=100)
line = p.line(x='x', y='y', source=cds, color=w.color)
cb = CustomJS(args={'line': line}, code="""
line.glyph.line_color = cb_obj.color
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
p = Figure(x_range=(0, 1), y_range=(0, 1))
points = p.scatter(x='x', y='y', source=cds)

w = Spinner(title="Glyph size", low=1, high=20, step=1, value=4, width=100)
w = Spinner(title="Glyph size", low=1, high=20, step=0.1, value=4, width=100)
cb = CustomJS(args={'points': points}, code="""
points.glyph.size = cb_obj.value
""")
Expand Down
29 changes: 20 additions & 9 deletions tests/integration/widgets/test_color_picker.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,35 @@ def cb(attr, old, new):


def enter_value_in_color_picker(driver, el, color):
input_el = el.find_element_by_tag_name("input")
driver.execute_script("arguments[0].value = '%s'" % color, input_el)
driver.execute_script("arguments[0].dispatchEvent(new Event('change'))", input_el)
driver.execute_script("arguments[0].value = '%s'" % color, el)
driver.execute_script("arguments[0].dispatchEvent(new Event('change'))", el)


@pytest.mark.integration
@pytest.mark.selenium
class Test_ColorPicker(object):

def test_display_color_input(self, bokeh_model_page):
colorpicker = ColorPicker(css_classes=["foo"])

page = bokeh_model_page(colorpicker)

el = page.driver.find_element_by_css_selector('.foo input')
assert el.get_attribute('type') == "color"

assert page.has_no_console_errors()


def test_displays_title(self, bokeh_model_page):
colorpicker = ColorPicker(css_classes=["foo"], title="title")

page = bokeh_model_page(colorpicker)

input_div = page.driver.find_element_by_class_name('foo')
el = input_div.find_element_by_tag_name("label")
el = page.driver.find_element_by_css_selector('.foo label')
assert el.text == "title"

el = page.driver.find_element_by_css_selector('.foo input')
assert el.get_attribute('type') == "color"

assert page.has_no_console_errors()

Expand All @@ -77,17 +89,16 @@ def test_input_value(self, bokeh_model_page):

page = bokeh_model_page(colorpicker)

input_div = page.driver.find_element_by_class_name('foo')
el = input_div.find_element_by_tag_name("input")

el = page.driver.find_element_by_css_selector('.foo input')

assert el.get_attribute('value') == '#ff0000'

assert page.has_no_console_errors()

def test_server_on_change_round_trip(self, bokeh_server_page):
page = bokeh_server_page(modify_doc)

el = page.driver.find_element_by_class_name('foo')
el = page.driver.find_element_by_css_selector('.foo input')

# new value
enter_value_in_color_picker(page.driver, el, '#0000ff')
Expand Down
34 changes: 21 additions & 13 deletions tests/integration/widgets/test_spinner.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,11 @@ def cb(attr, old, new):


def enter_value_in_spinner(driver, el, value, del_prev=True):
input_el = el.find_element_by_tag_name("input")
actions = ActionChains(driver)
actions.move_to_element(input_el)
actions.move_to_element(el)
actions.click()
if del_prev:
nb_char = len(input_el.get_attribute('value'))
actions.send_keys(Keys.END + Keys.BACKSPACE * nb_char)
actions.key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL)
actions.send_keys(str(value))
actions.send_keys(Keys.ENTER)
actions.perform()
Expand All @@ -68,14 +66,25 @@ def enter_value_in_spinner(driver, el, value, del_prev=True):
@pytest.mark.selenium
class Test_Spinner(object):

def test_displays_title(self, bokeh_model_page):
spinner = Spinner(css_classes=["foo"], title="title")
def test_display_number_input(self, bokeh_model_page):
spinner = Spinner(css_classes=["foo"])

page = bokeh_model_page(spinner)

input_div = page.driver.find_element_by_class_name('foo')
el = input_div.find_element_by_tag_name("label")
el = page.driver.find_element_by_css_selector('.foo input')
assert el.get_attribute('type') == "number"

assert page.has_no_console_errors()

def test_displays_title(self, bokeh_model_page):
text_input = Spinner(title="title", css_classes=["foo"])

page = bokeh_model_page(text_input)

el = page.driver.find_element_by_css_selector('.foo label')
assert el.text == "title"
el = page.driver.find_element_by_css_selector('.foo input')
assert el.get_attribute('type') == "number"

assert page.has_no_console_errors()

Expand All @@ -84,9 +93,8 @@ def test_input_value_min_max_step(self, bokeh_model_page):

page = bokeh_model_page(spinner)

input_div = page.driver.find_element_by_class_name('foo')
el = input_div.find_element_by_tag_name("input")

el = page.driver.find_element_by_css_selector('.foo input')

assert el.get_attribute('value') == '1'
assert el.get_attribute('step') == '1'
assert el.get_attribute('max') == '10'
Expand All @@ -97,7 +105,7 @@ def test_input_value_min_max_step(self, bokeh_model_page):
def test_server_on_change_round_trip(self, bokeh_server_page):
page = bokeh_server_page(modify_doc)

el = page.driver.find_element_by_class_name('foo')
el = page.driver.find_element_by_css_selector('.foo input')

# same value
enter_value_in_spinner(page.driver, el, 4)
Expand Down Expand Up @@ -147,7 +155,7 @@ def test_callback_property_executes(self, single_plot_page):

page = single_plot_page(column(spinner, plot))

el = page.driver.find_element_by_class_name('foo')
el = page.driver.find_element_by_css_selector('.foo input')

enter_value_in_spinner(page.driver, el, 4)
results = page.results
Expand Down

0 comments on commit d45689c

Please sign in to comment.