diff --git a/lightweight_charts/js/funcs.js b/lightweight_charts/js/funcs.js
index 67a5ed6..dc61ffa 100644
--- a/lightweight_charts/js/funcs.js
+++ b/lightweight_charts/js/funcs.js
@@ -182,6 +182,9 @@ if (!window.Chart) {
class Legend {
constructor(chart) {
+ this.legendHandler = this.legendHandler.bind(this)
+
+ this.chart = chart
this.ohlcEnabled = false
this.percentEnabled = false
this.linesEnabled = false
@@ -207,80 +210,12 @@ if (!window.Chart) {
this.makeLines(chart)
- let legendItemFormat = (num, decimal) => num.toFixed(decimal).toString().padStart(8, ' ')
-
- let shorthandFormat = (num) => {
- const absNum = Math.abs(num)
- if (absNum >= 1000000) {
- return (num / 1000000).toFixed(1) + 'M';
- } else if (absNum >= 1000) {
- return (num / 1000).toFixed(1) + 'K';
- }
- return num.toString().padStart(8, ' ');
- }
-
- chart.chart.subscribeCrosshairMove((param) => {
- let options = chart.series.options()
- if (!param.time) {
- this.candle.style.color = 'transparent'
- this.candle.innerHTML = this.candle.innerHTML.replace(options['upColor'], '').replace(options['downColor'], '')
- return
- }
- let data = param.seriesData.get(chart.series);
- this.candle.style.color = ''
- let str = ''
- if (data) {
- if (this.ohlcEnabled) {
- str += `O ${legendItemFormat(data.open, chart.precision)} `
- str += `| H ${legendItemFormat(data.high, chart.precision)} `
- str += `| L ${legendItemFormat(data.low, chart.precision)} `
- str += `| C ${legendItemFormat(data.close, chart.precision)} `
- }
-
- if (this.percentEnabled) {
- let percentMove = ((data.close - data.open) / data.open) * 100
- let color = percentMove > 0 ? options['upColor'] : options['downColor']
- let percentStr = `${percentMove >= 0 ? '+' : ''}${percentMove.toFixed(2)} %`
-
- if (this.colorBasedOnCandle) {
- str += `| ${percentStr}`
- }
- else {
- str += '| ' + percentStr
- }
- }
- let volumeData = param.seriesData.get(chart.volumeSeries)
- if (volumeData) {
- str += this.ohlcEnabled ? `
V ${shorthandFormat(volumeData.value)}` : ''
- }
- }
- this.candle.innerHTML = str + ''
-
- this.lines.forEach((line) => {
- if (!this.linesEnabled) {
- line.row.style.display = 'none'
- return
- }
- line.row.style.display = 'flex'
- if (!param.seriesData.get(line.line.series)) return
- let price = param.seriesData.get(line.line.series).value
-
- if (line.line.type === 'histogram') {
- price = shorthandFormat(price)
- }
- else {
- price = legendItemFormat(price, line.line.precision)
- }
- line.div.innerHTML = `▨ ${line.line.name} : ${price}`
- })
-
-
- });
+ chart.chart.subscribeCrosshairMove(this.legendHandler)
}
toJSON() {
// Exclude the chart attribute from serialization
- const {lines, ...serialized} = this;
+ const {lines, chart, ...serialized} = this;
return serialized;
}
@@ -352,6 +287,94 @@ if (!window.Chart) {
solid: line.color.startsWith('rgba') ? line.color.replace(/[^,]+(?=\))/, '1') : line.color
}
}
+
+ legendItemFormat(num, decimal) { return num.toFixed(decimal).toString().padStart(8, ' ') }
+
+ shorthandFormat(num) {
+ const absNum = Math.abs(num)
+ if (absNum >= 1000000) {
+ return (num / 1000000).toFixed(1) + 'M';
+ } else if (absNum >= 1000) {
+ return (num / 1000).toFixed(1) + 'K';
+ }
+ return num.toString().padStart(8, ' ');
+ }
+
+ legendHandler(param) {
+ let options = this.chart.series.options()
+
+ if (!param.time) {
+ this.candle.style.color = 'transparent'
+ this.candle.innerHTML = this.candle.innerHTML.replace(options['upColor'], '').replace(options['downColor'], '')
+ return
+ }
+
+ let usingPoint = !param.point && param.time
+
+ let data, logical
+
+ if (usingPoint) {
+ let coordinate = this.chart.chart.timeScale().timeToCoordinate(param.time)
+ logical = this.chart.chart.timeScale().coordinateToLogical(coordinate)
+ data = this.chart.series.dataByIndex(logical)
+ }
+ else {
+ data = param.seriesData.get(this.chart.series);
+ }
+
+ this.candle.style.color = ''
+ let str = ''
+ if (data) {
+ if (this.ohlcEnabled) {
+ str += `O ${this.legendItemFormat(data.open, this.chart.precision)} `
+ str += `| H ${this.legendItemFormat(data.high, this.chart.precision)} `
+ str += `| L ${this.legendItemFormat(data.low, this.chart.precision)} `
+ str += `| C ${this.legendItemFormat(data.close, this.chart.precision)} `
+ }
+
+ if (this.percentEnabled) {
+ let percentMove = ((data.close - data.open) / data.open) * 100
+ let color = percentMove > 0 ? options['upColor'] : options['downColor']
+ let percentStr = `${percentMove >= 0 ? '+' : ''}${percentMove.toFixed(2)} %`
+
+ if (this.colorBasedOnCandle) {
+ str += `| ${percentStr}`
+ } else {
+ str += '| ' + percentStr
+ }
+ }
+ let volumeData = param.seriesData.get(this.chart.volumeSeries)
+ if (volumeData) {
+ str += this.ohlcEnabled ? `
V ${this.shorthandFormat(volumeData.value)}` : ''
+ }
+ }
+ this.candle.innerHTML = str + ''
+
+ this.lines.forEach((line) => {
+ if (!this.linesEnabled) {
+ line.row.style.display = 'none'
+ return
+ }
+ line.row.style.display = 'flex'
+
+ let price
+ if (usingPoint) {
+ price = line.line.series.dataByIndex(logical)
+ }
+ else {
+ price = param.seriesData.get(line.line.series)
+ }
+ if (!price) return
+ else price = price.value
+
+ if (line.line.type === 'histogram') {
+ price = this.shorthandFormat(price)
+ } else {
+ price = this.legendItemFormat(price, line.line.precision)
+ }
+ line.div.innerHTML = `▨ ${line.line.name} : ${price}`
+ })
+ }
}
window.Legend = Legend
@@ -359,12 +382,13 @@ if (!window.Chart) {
function syncCharts(childChart, parentChart) {
- function crosshairHandler(chart, series, point) {
+ function crosshairHandler(chart, point) {
if (!point) {
- chart.clearCrosshairPosition()
+ chart.chart.clearCrosshairPosition()
return
}
- chart.setCrosshairPosition(point.value || point.close, point.time, series);
+ chart.chart.setCrosshairPosition(point.value || point.close, point.time, chart.series);
+ chart.legend.legendHandler(point)
}
function getPoint(series, param) {
@@ -376,10 +400,10 @@ function syncCharts(childChart, parentChart) {
let setParentRange = (timeRange) => parentChart.chart.timeScale().setVisibleLogicalRange(timeRange)
let setParentCrosshair = (param) => {
- crosshairHandler(parentChart.chart, parentChart.series, getPoint(childChart.series, param))
+ crosshairHandler(parentChart, getPoint(childChart.series, param))
}
let setChildCrosshair = (param) => {
- crosshairHandler(childChart.chart, childChart.series, getPoint(parentChart.series, param))
+ crosshairHandler(childChart, getPoint(parentChart.series, param))
}
let selected = parentChart
diff --git a/lightweight_charts/table.py b/lightweight_charts/table.py
index 2a3c06f..9d23c71 100644
--- a/lightweight_charts/table.py
+++ b/lightweight_charts/table.py
@@ -109,6 +109,6 @@ class Table(Pane, dict):
def visible(self, visible: bool):
self.is_shown = visible
self.run_script(f"""
- {self.id}.container.style.display = '{'block' if visible else 'none'}'
+ {self.id}.container.style.display = '{'flex' if visible else 'none'}'
{self.id}.container.{'add' if visible else 'remove'}EventListener('mousedown', {self.id}.onMouseDown)
""")