@coreui/coreui-plugin-chartjs-custom-tooltips
Version:
Chart.js custom tooltips designed for CoreUI Templates
146 lines (116 loc) • 4.91 kB
JavaScript
/**
* --------------------------------------------------------------------------
* CoreUI Plugins - Custom Tooltips for Chart.js (v1.3.1): custom-tooltips.js
* Licensed under MIT (https://coreui.io/license)
* --------------------------------------------------------------------------
*/
function CustomTooltips(tooltipModel) {
// Add unique id if not exist
const _setCanvasId = () => {
const _idMaker = () => {
const _hex = 16
const _multiplier = 0x10000
return ((1 + Math.random()) * _multiplier | 0).toString(_hex)
}
const _canvasId = `_canvas-${_idMaker() + _idMaker()}`
this._chart.canvas.id = _canvasId
return _canvasId
}
const ClassName = {
ABOVE : 'above',
BELOW : 'below',
CHARTJS_TOOLTIP : 'chartjs-tooltip',
NO_TRANSFORM : 'no-transform',
TOOLTIP_BODY : 'tooltip-body',
TOOLTIP_BODY_ITEM : 'tooltip-body-item',
TOOLTIP_BODY_ITEM_COLOR : 'tooltip-body-item-color',
TOOLTIP_BODY_ITEM_LABEL : 'tooltip-body-item-label',
TOOLTIP_BODY_ITEM_VALUE : 'tooltip-body-item-value',
TOOLTIP_HEADER : 'tooltip-header',
TOOLTIP_HEADER_ITEM : 'tooltip-header-item'
}
const Selector = {
DIV : 'div',
SPAN : 'span',
TOOLTIP : `${this._chart.canvas.id || _setCanvasId()}-tooltip`
}
let tooltip = document.getElementById(Selector.TOOLTIP)
if (!tooltip) {
tooltip = document.createElement('div')
tooltip.id = Selector.TOOLTIP
tooltip.className = ClassName.CHARTJS_TOOLTIP
this._chart.canvas.parentNode.appendChild(tooltip)
}
// Hide if no tooltip
if (tooltipModel.opacity === 0) {
tooltip.style.opacity = 0
return
}
// Set caret Position
tooltip.classList.remove(ClassName.ABOVE, ClassName.BELOW, ClassName.NO_TRANSFORM)
if (tooltipModel.yAlign) {
tooltip.classList.add(tooltipModel.yAlign)
} else {
tooltip.classList.add(ClassName.NO_TRANSFORM)
}
// Set Text
if (tooltipModel.body) {
const titleLines = tooltipModel.title || []
const tooltipHeader = document.createElement(Selector.DIV)
tooltipHeader.className = ClassName.TOOLTIP_HEADER
titleLines.forEach((title) => {
const tooltipHeaderTitle = document.createElement(Selector.DIV)
tooltipHeaderTitle.className = ClassName.TOOLTIP_HEADER_ITEM
tooltipHeaderTitle.innerHTML = title
tooltipHeader.appendChild(tooltipHeaderTitle)
})
const tooltipBody = document.createElement(Selector.DIV)
tooltipBody.className = ClassName.TOOLTIP_BODY
const tooltipBodyItems = tooltipModel.body.map((item) => item.lines)
tooltipBodyItems.forEach((item, i) => {
const tooltipBodyItem = document.createElement(Selector.DIV)
tooltipBodyItem.className = ClassName.TOOLTIP_BODY_ITEM
const colors = tooltipModel.labelColors[i]
const tooltipBodyItemColor = document.createElement(Selector.SPAN)
tooltipBodyItemColor.className = ClassName.TOOLTIP_BODY_ITEM_COLOR
tooltipBodyItemColor.style.backgroundColor = colors.backgroundColor
tooltipBodyItem.appendChild(tooltipBodyItemColor)
if (item[0].split(':').length > 1) {
const tooltipBodyItemLabel = document.createElement(Selector.SPAN)
tooltipBodyItemLabel.className = ClassName.TOOLTIP_BODY_ITEM_LABEL
tooltipBodyItemLabel.innerHTML = item[0].split(': ')[0]
tooltipBodyItem.appendChild(tooltipBodyItemLabel)
const tooltipBodyItemValue = document.createElement(Selector.SPAN)
tooltipBodyItemValue.className = ClassName.TOOLTIP_BODY_ITEM_VALUE
tooltipBodyItemValue.innerHTML = item[0].split(': ').pop()
tooltipBodyItem.appendChild(tooltipBodyItemValue)
} else {
const tooltipBodyItemValue = document.createElement(Selector.SPAN)
tooltipBodyItemValue.className = ClassName.TOOLTIP_BODY_ITEM_VALUE
tooltipBodyItemValue.innerHTML = item[0]
tooltipBodyItem.appendChild(tooltipBodyItemValue)
}
tooltipBody.appendChild(tooltipBodyItem)
})
tooltip.innerHTML = ''
tooltip.appendChild(tooltipHeader)
tooltip.appendChild(tooltipBody)
}
const position = this._chart.canvas.getBoundingClientRect()
const positionY = this._chart.canvas.offsetTop
const positionX = this._chart.canvas.offsetLeft
let positionLeft = positionX + tooltipModel.caretX
const positionTop = positionY + tooltipModel.caretY
// eslint-disable-next-line
const halfWidth = tooltipModel.width / 2
if (positionLeft + halfWidth > position.width) {
positionLeft -= halfWidth
} else if (positionLeft < halfWidth) {
positionLeft += halfWidth
}
// Display, position, and set styles for font
tooltip.style.opacity = 1
tooltip.style.left = `${positionLeft}px`
tooltip.style.top = `${positionTop}px`
}
export default CustomTooltips