mirror of https://github.com/anoshenko/rui.git
Added "tooltip" property
This commit is contained in:
parent
ac8bb47677
commit
a83d634f54
|
@ -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 | Цвет тени всплывающей подсказки |
|
||||
|
||||
Константы которые вы можете переопределять:
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
121
app_scripts.js
121
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -76,6 +76,12 @@ func getStartPage(buffer *strings.Builder, params AppParams, addScripts string)
|
|||
<body>
|
||||
<div class="ruiRoot" id="ruiRootView"></div>
|
||||
<div class="ruiPopupLayer" id="ruiPopupLayer" style="visibility: hidden; isolation: isolate;" onclick="clickOutsidePopup(event)"></div>
|
||||
<div class="ruiTooltipLayer" id="ruiTooltipLayer" style="visibility: hidden; opacity: 0;">
|
||||
<div id="ruiTooltipText" class="ruiTooltipText"></div>
|
||||
<div id="ruiTooltipTopArrow" class="ruiTooltipTopArrow"></div>
|
||||
<div id="ruiTooltipBottomArrow" class="ruiTooltipBottomArrow"></div>
|
||||
</div>
|
||||
|
||||
<a id="ruiDownloader" download style="display: none;"></a>
|
||||
</body>`)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ theme {
|
|||
ruiTabTextColor = #FF404040,
|
||||
ruiCurrentTabColor = #FFFFFFFF,
|
||||
ruiCurrentTabTextColor = #FF000000,
|
||||
ruiTooltipBackground = #FFFFFFFF,
|
||||
ruiTooltipTextColor = #FF000000,
|
||||
ruiTooltipShadowColor = #FF808080,
|
||||
},
|
||||
colors:dark = _{
|
||||
ruiTextColor = #FFE0E0E0,
|
||||
|
@ -43,6 +46,9 @@ theme {
|
|||
ruiTabTextColor = #FFE0E0E0,
|
||||
ruiCurrentTabColor = #FF000000,
|
||||
ruiCurrentTabTextColor = #FFFFFFFF,
|
||||
ruiTooltipBackground = #FF303030,
|
||||
ruiTooltipTextColor = #FFDDDDDD,
|
||||
ruiTooltipShadowColor = #FFDDDDDD,
|
||||
},
|
||||
constants = _{
|
||||
ruiButtonHorizontalPadding = 16px,
|
||||
|
|
|
@ -184,7 +184,7 @@ func (view *viewData) removeMouseListener(tag string) {
|
|||
}
|
||||
}
|
||||
|
||||
func mouseEventsHtml(view View, buffer *strings.Builder) {
|
||||
func mouseEventsHtml(view View, buffer *strings.Builder, hasTooltip bool) {
|
||||
for tag, js := range mouseEvents {
|
||||
if value := view.getRaw(tag); value != nil {
|
||||
if listeners, ok := value.([]func(View, MouseEvent)); ok && len(listeners) > 0 {
|
||||
|
@ -192,6 +192,11 @@ func mouseEventsHtml(view View, buffer *strings.Builder) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hasTooltip {
|
||||
buffer.WriteString(`onmouseenter="mouseEnterEvent(this, event)" `)
|
||||
buffer.WriteString(`onmouseleave="mouseLeaveEvent(this, event)" `)
|
||||
}
|
||||
}
|
||||
|
||||
func getTimeStamp(data DataObject) uint64 {
|
||||
|
|
1
popup.go
1
popup.go
|
@ -637,6 +637,7 @@ func (manager *popupManager) showPopup(popup Popup) {
|
|||
|
||||
session.callFunc("blurCurrent")
|
||||
manager.updatePopupLayerInnerHTML(session)
|
||||
session.updateCSSProperty("ruiTooltipLayer", "visibility", "hidden")
|
||||
session.updateCSSProperty("ruiPopupLayer", "visibility", "visible")
|
||||
session.updateCSSProperty("ruiRoot", "pointer-events", "none")
|
||||
}
|
||||
|
|
|
@ -702,4 +702,6 @@ const (
|
|||
// * tabindex="0" means that View should be focusable in sequential keyboard navigation, after any positive tabindex values and its order is defined in order of its addition.
|
||||
// * A positive value means View should be focusable in sequential keyboard navigation, with its order defined by the value of the number.
|
||||
TabIndex = "tabindex"
|
||||
|
||||
Tooltip = "tooltip"
|
||||
)
|
||||
|
|
16
session.go
16
session.go
|
@ -303,6 +303,21 @@ func (session *sessionData) writeInitScript(writer *strings.Builder) {
|
|||
writer.WriteString(text)
|
||||
writer.WriteString("';\nscanElementsSize();")
|
||||
}
|
||||
|
||||
session.updateTooltipConstants()
|
||||
}
|
||||
|
||||
func (session *sessionData) updateTooltipConstants() {
|
||||
if color, ok := session.Color("ruiTooltipBackground"); ok {
|
||||
session.bridge.callFunc("setCssVar", "--tooltip-background", color.cssString())
|
||||
}
|
||||
if color, ok := session.Color("ruiTooltipTextColor"); ok {
|
||||
session.bridge.callFunc("setCssVar", "--tooltip-text-color", color.cssString())
|
||||
}
|
||||
if color, ok := session.Color("ruiTooltipShadowColor"); ok {
|
||||
session.bridge.callFunc("setCssVar", "--tooltip-shadow-color", color.cssString())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (session *sessionData) reload() {
|
||||
|
@ -323,6 +338,7 @@ func (session *sessionData) reload() {
|
|||
}
|
||||
|
||||
session.bridge.writeMessage(buffer.String())
|
||||
session.updateTooltipConstants()
|
||||
}
|
||||
|
||||
func (session *sessionData) ignoreViewUpdates() bool {
|
||||
|
|
20
view.go
20
view.go
|
@ -634,6 +634,16 @@ func viewPropertyChanged(view *viewData, tag string) {
|
|||
session.updateCSSProperty(htmlID, `column-span`, `none`)
|
||||
}
|
||||
return
|
||||
|
||||
case Tooltip:
|
||||
if tooltip := GetTooltip(view); tooltip == "" {
|
||||
session.removeProperty(htmlID, "data-tooltip")
|
||||
} else {
|
||||
session.updateProperty(htmlID, "data-tooltip", tooltip)
|
||||
session.updateProperty(htmlID, "onmouseenter", "mouseEnterEvent(this, event)")
|
||||
session.updateProperty(htmlID, "onmouseleave", "mouseLeaveEvent(this, event)")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if cssTag, ok := sizeProperties[tag]; ok {
|
||||
|
@ -796,10 +806,18 @@ func viewHTML(view View, buffer *strings.Builder) {
|
|||
}
|
||||
}
|
||||
|
||||
hasTooltip := false
|
||||
if tooltip := GetTooltip(view); tooltip != "" {
|
||||
buffer.WriteString(`data-tooltip=" `)
|
||||
buffer.WriteString(tooltip)
|
||||
buffer.WriteString(`" `)
|
||||
hasTooltip = true
|
||||
}
|
||||
|
||||
buffer.WriteString(`onscroll="scrollEvent(this, event)" `)
|
||||
|
||||
keyEventsHtml(view, buffer)
|
||||
mouseEventsHtml(view, buffer)
|
||||
mouseEventsHtml(view, buffer, hasTooltip)
|
||||
pointerEventsHtml(view, buffer)
|
||||
touchEventsHtml(view, buffer)
|
||||
focusEventsHtml(view, buffer)
|
||||
|
|
18
viewUtils.go
18
viewUtils.go
|
@ -945,3 +945,21 @@ func GetMixBlendMode(view View, subviewID ...string) int {
|
|||
func GetBackgroundBlendMode(view View, subviewID ...string) int {
|
||||
return enumStyledProperty(view, subviewID, BackgroundBlendMode, BlendNormal, true)
|
||||
}
|
||||
|
||||
// GetTooltip returns a tooltip text of the subview.
|
||||
// If the second argument (subviewID) is not specified or it is "" then a value from the first argument (view) is returned.
|
||||
func GetTooltip(view View, subviewID ...string) string {
|
||||
if len(subviewID) > 0 && subviewID[0] != "" {
|
||||
view = ViewByID(view, subviewID[0])
|
||||
}
|
||||
|
||||
if view != nil {
|
||||
if value := view.Get(Tooltip); value != nil {
|
||||
if text, ok := value.(string); ok {
|
||||
return text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue