diff --git a/README-ru.md b/README-ru.md index d303853..ea6ac7b 100644 --- a/README-ru.md +++ b/README-ru.md @@ -1472,6 +1472,12 @@ radius необходимо передать nil | 18 | "blockquote" | Цитата. Изменяет стиль текста | | 19 | "code" | Программный код. Изменяет стиль текста | +### Свойство "tooltip" + +Свойство "tooltip" (константа Tooltip) типа string задает текст всплывающей подсказки. +Подсказка всплывает при наведении курсора мыши. При оформление текста подсказки можно +использовать html тэги + ### Свойства текста Все перечисленные в этом разделе свойства являются наследуемыми, т.е. свойство будет применяться не только ко View @@ -5591,6 +5597,9 @@ Safari и Firefox. | ruiPopupTextColor | Цвет текста всплывающего окна | | ruiPopupTitleColor | Цвет фона заголовка всплывающего окна | | ruiPopupTitleTextColor | Цвет текста заголовка всплывающего окна | +| ruiTooltipBackground | Цвет фона всплывающей подсказки | +| ruiTooltipTextColor | Цвет текста всплывающей подсказки | +| ruiTooltipShadowColor | Цвет тени всплывающей подсказки | Константы которые вы можете переопределять: diff --git a/README.md b/README.md index 3881b10..0e91275 100644 --- a/README.md +++ b/README.md @@ -1453,6 +1453,12 @@ It also helps to voice the interface to systems for people with disabilities: | 18 | "blockquote" | Quote. Changes the style of the text | | 19 | "code" | Program code. Changes the style of the text | +### "tooltip" property + +The "tooltip" string property (Tooltip constant) specifies the tooltip text. +Tooltip pops up when hovering the mouse cursor. +You can use html tags when formatting the tooltip text. + ### Text properties All properties listed in this section are inherited, i.e. the property will apply @@ -5542,6 +5548,9 @@ System color constants that you can override: | ruiPopupTextColor | Popup text color | | ruiPopupTitleColor | Popup title background color | | ruiPopupTitleTextColor | Popup Title Text Color | +| ruiTooltipBackground | Tooltip background color | +| ruiTooltipTextColor | Tooltip text color | +| ruiTooltipShadowColor | Tooltip shadow color | Constants that you can override: diff --git a/app_scripts.js b/app_scripts.js index 2b39533..15d5e98 100644 --- a/app_scripts.js +++ b/app_scripts.js @@ -1877,3 +1877,124 @@ function localStorageClear() { sendMessage("storageError{session=" + sessionID + ", error=`" + err + "`}") } } + +function showTooltip(element, tooltip) { + const layer = document.getElementById("ruiTooltipLayer"); + if (!layer) { + return; + } + + layer.style.left = "0px"; + layer.style.right = "0px"; + + var tooltipBox = document.getElementById("ruiTooltipText"); + if (tooltipBox) { + tooltipBox.innerHTML = tooltip; + } + + var left = element.offsetLeft; + var top = element.offsetTop; + var width = element.offsetWidth; + var height = element.offsetHeight; + var parent = element.offsetParent; + + while (parent) { + left += parent.offsetLeft; + top += parent.offsetTop; + width = parent.offsetWidth; + height = parent.offsetHeight; + parent = parent.offsetParent; + } + + if (element.offsetWidth >= tooltipBox.offsetWidth) { + layer.style.left = left + "px"; + layer.style.justifyItems = "start"; + } else { + const rightOff = width - (left + element.offsetWidth); + if (left > rightOff) { + if (width - left < tooltipBox.offsetWidth) { + layer.style.right = rightOff + "px"; + layer.style.justifyItems = "end"; + } else { + layer.style.left = (left - rightOff) + "px"; + layer.style.right = "0px"; + layer.style.justifyItems = "center"; + } + } else { + if (width - rightOff < tooltipBox.offsetWidth) { + layer.style.left = left + "px"; + layer.style.justifyItems = "start"; + } else { + layer.style.right = (rightOff - left) + "px"; + layer.style.justifyItems = "center"; + } + } + } + + const bottomOff = height - (top + element.offsetHeight); + var arrow = document.getElementById("ruiTooltipTopArrow"); + + if (bottomOff < arrow.offsetHeight + tooltipBox.offsetHeight) { + if (arrow) { + arrow.style.visibility = "hidden"; + } + + arrow = document.getElementById("ruiTooltipBottomArrow"); + if (arrow) { + arrow.style.visibility = "visible"; + } + + layer.style.top = "0px"; + layer.style.bottom = height - top - arrow.offsetHeight / 2 + "px"; + layer.style.gridTemplateRows = "1fr auto auto" + + } else { + if (arrow) { + arrow.style.visibility = "visible"; + } + + layer.style.top = top + element.offsetHeight - arrow.offsetHeight / 2 + "px"; + layer.style.bottom = "0px"; + layer.style.gridTemplateRows = "auto auto 1fr" + + arrow = document.getElementById("ruiTooltipBottomArrow"); + if (arrow) { + arrow.style.visibility = "hidden"; + } + } + + layer.style.visibility = "visible"; + layer.style.opacity = 1; +} + +function mouseEnterEvent(element, event) { + event.stopPropagation(); + + let tooltip = element.getAttribute("data-tooltip"); + if (tooltip) { + showTooltip(element, tooltip); + } + + sendMessage("mouse-enter{session=" + sessionID + ",id=" + element.id + mouseEventData(element, event) + "}"); +} + +function mouseLeaveEvent(element, event) { + event.stopPropagation(); + + if (element.getAttribute("data-tooltip")) { + const layer = document.getElementById("ruiTooltipLayer"); + if (layer) { + layer.style.opacity = 0; + layer.style.visibility = "hidden"; + } + } + + sendMessage("mouse-leave{session=" + sessionID + ",id=" + element.id + mouseEventData(element, event) + "}"); +} + +function setCssVar(tag, value) { + const root = document.querySelector(':root'); + if (root) { + root.style.setProperty(tag, value); + } +} diff --git a/app_styles.css b/app_styles.css index 79f53e9..2e090a5 100644 --- a/app_styles.css +++ b/app_styles.css @@ -8,6 +8,13 @@ text-overflow: ellipsis; } +:root { + --tooltip-arrow-size: 6px; + --tooltip-background: white; + --tooltip-text-color: black; + --tooltip-shadow-color: gray; +} + body { -webkit-touch-callout: none; -webkit-user-select: none; @@ -76,7 +83,54 @@ ul:focus { left: 0px; } +.ruiTooltipLayer { + display: grid; + grid-template-rows: 1fr auto 1fr; + justify-items: center; + align-items: center; + position: absolute; + top: 0px; + bottom: 0px; + right: 0px; + left: 0px; + transition: opacity 0.5s ease-out; + filter: drop-shadow(0px 0px 2px var(--tooltip-shadow-color)); +} + +.ruiTooltipTopArrow { + grid-row-start: 1; + grid-row-end: 2; + border-width: var(--tooltip-arrow-size); + border-style: solid; + border-color: transparent transparent var(--tooltip-background) transparent; + margin-left: 12px; + margin-right: 12px; +} + +.ruiTooltipBottomArrow { + grid-row-start: 3; + grid-row-end: 4; + border-width: var(--tooltip-arrow-size); + border-style: solid; + border-color: var(--tooltip-background) transparent transparent transparent; + margin-left: 12px; + margin-right: 12px; +} + +.ruiTooltipText { + grid-row-start: 2; + grid-row-end: 3; + padding: 4px 8px 4px 8px; + margin-left: 8px; + margin-right: 8px; + background-color: var(--tooltip-background); + color: var(--tooltip-text-color); + /*box-shadow: 0px 0px 4px 2px #8888;*/ + border-radius: 4px; +} + .ruiView { + box-sizing: border-box; } .ruiAbsoluteLayout { diff --git a/application.go b/application.go index ceafd5e..e5b3046 100644 --- a/application.go +++ b/application.go @@ -76,6 +76,12 @@ func getStartPage(buffer *strings.Builder, params AppParams, addScripts string)
+