forked from mbk-lab/rui_orig
Added "tooltip" property
This commit is contained in:
parent
ac8bb47677
commit
a83d634f54
|
@ -1472,6 +1472,12 @@ radius необходимо передать nil
|
||||||
| 18 | "blockquote" | Цитата. Изменяет стиль текста |
|
| 18 | "blockquote" | Цитата. Изменяет стиль текста |
|
||||||
| 19 | "code" | Программный код. Изменяет стиль текста |
|
| 19 | "code" | Программный код. Изменяет стиль текста |
|
||||||
|
|
||||||
|
### Свойство "tooltip"
|
||||||
|
|
||||||
|
Свойство "tooltip" (константа Tooltip) типа string задает текст всплывающей подсказки.
|
||||||
|
Подсказка всплывает при наведении курсора мыши. При оформление текста подсказки можно
|
||||||
|
использовать html тэги
|
||||||
|
|
||||||
### Свойства текста
|
### Свойства текста
|
||||||
|
|
||||||
Все перечисленные в этом разделе свойства являются наследуемыми, т.е. свойство будет применяться не только ко View
|
Все перечисленные в этом разделе свойства являются наследуемыми, т.е. свойство будет применяться не только ко View
|
||||||
|
@ -5591,6 +5597,9 @@ Safari и Firefox.
|
||||||
| ruiPopupTextColor | Цвет текста всплывающего окна |
|
| ruiPopupTextColor | Цвет текста всплывающего окна |
|
||||||
| ruiPopupTitleColor | Цвет фона заголовка всплывающего окна |
|
| ruiPopupTitleColor | Цвет фона заголовка всплывающего окна |
|
||||||
| ruiPopupTitleTextColor | Цвет текста заголовка всплывающего окна |
|
| 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 |
|
| 18 | "blockquote" | Quote. Changes the style of the text |
|
||||||
| 19 | "code" | Program code. 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
|
### Text properties
|
||||||
|
|
||||||
All properties listed in this section are inherited, i.e. the property will apply
|
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 |
|
| ruiPopupTextColor | Popup text color |
|
||||||
| ruiPopupTitleColor | Popup title background color |
|
| ruiPopupTitleColor | Popup title background color |
|
||||||
| ruiPopupTitleTextColor | Popup Title Text Color |
|
| ruiPopupTitleTextColor | Popup Title Text Color |
|
||||||
|
| ruiTooltipBackground | Tooltip background color |
|
||||||
|
| ruiTooltipTextColor | Tooltip text color |
|
||||||
|
| ruiTooltipShadowColor | Tooltip shadow color |
|
||||||
|
|
||||||
Constants that you can override:
|
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 + "`}")
|
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;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--tooltip-arrow-size: 6px;
|
||||||
|
--tooltip-background: white;
|
||||||
|
--tooltip-text-color: black;
|
||||||
|
--tooltip-shadow-color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
|
@ -76,7 +83,54 @@ ul:focus {
|
||||||
left: 0px;
|
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 {
|
.ruiView {
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ruiAbsoluteLayout {
|
.ruiAbsoluteLayout {
|
||||||
|
|
|
@ -76,6 +76,12 @@ func getStartPage(buffer *strings.Builder, params AppParams, addScripts string)
|
||||||
<body>
|
<body>
|
||||||
<div class="ruiRoot" id="ruiRootView"></div>
|
<div class="ruiRoot" id="ruiRootView"></div>
|
||||||
<div class="ruiPopupLayer" id="ruiPopupLayer" style="visibility: hidden; isolation: isolate;" onclick="clickOutsidePopup(event)"></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>
|
<a id="ruiDownloader" download style="display: none;"></a>
|
||||||
</body>`)
|
</body>`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ theme {
|
||||||
ruiTabTextColor = #FF404040,
|
ruiTabTextColor = #FF404040,
|
||||||
ruiCurrentTabColor = #FFFFFFFF,
|
ruiCurrentTabColor = #FFFFFFFF,
|
||||||
ruiCurrentTabTextColor = #FF000000,
|
ruiCurrentTabTextColor = #FF000000,
|
||||||
|
ruiTooltipBackground = #FFFFFFFF,
|
||||||
|
ruiTooltipTextColor = #FF000000,
|
||||||
|
ruiTooltipShadowColor = #FF808080,
|
||||||
},
|
},
|
||||||
colors:dark = _{
|
colors:dark = _{
|
||||||
ruiTextColor = #FFE0E0E0,
|
ruiTextColor = #FFE0E0E0,
|
||||||
|
@ -43,6 +46,9 @@ theme {
|
||||||
ruiTabTextColor = #FFE0E0E0,
|
ruiTabTextColor = #FFE0E0E0,
|
||||||
ruiCurrentTabColor = #FF000000,
|
ruiCurrentTabColor = #FF000000,
|
||||||
ruiCurrentTabTextColor = #FFFFFFFF,
|
ruiCurrentTabTextColor = #FFFFFFFF,
|
||||||
|
ruiTooltipBackground = #FF303030,
|
||||||
|
ruiTooltipTextColor = #FFDDDDDD,
|
||||||
|
ruiTooltipShadowColor = #FFDDDDDD,
|
||||||
},
|
},
|
||||||
constants = _{
|
constants = _{
|
||||||
ruiButtonHorizontalPadding = 16px,
|
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 {
|
for tag, js := range mouseEvents {
|
||||||
if value := view.getRaw(tag); value != nil {
|
if value := view.getRaw(tag); value != nil {
|
||||||
if listeners, ok := value.([]func(View, MouseEvent)); ok && len(listeners) > 0 {
|
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 {
|
func getTimeStamp(data DataObject) uint64 {
|
||||||
|
|
1
popup.go
1
popup.go
|
@ -637,6 +637,7 @@ func (manager *popupManager) showPopup(popup Popup) {
|
||||||
|
|
||||||
session.callFunc("blurCurrent")
|
session.callFunc("blurCurrent")
|
||||||
manager.updatePopupLayerInnerHTML(session)
|
manager.updatePopupLayerInnerHTML(session)
|
||||||
|
session.updateCSSProperty("ruiTooltipLayer", "visibility", "hidden")
|
||||||
session.updateCSSProperty("ruiPopupLayer", "visibility", "visible")
|
session.updateCSSProperty("ruiPopupLayer", "visibility", "visible")
|
||||||
session.updateCSSProperty("ruiRoot", "pointer-events", "none")
|
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.
|
// * 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.
|
// * A positive value means View should be focusable in sequential keyboard navigation, with its order defined by the value of the number.
|
||||||
TabIndex = "tabindex"
|
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(text)
|
||||||
writer.WriteString("';\nscanElementsSize();")
|
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() {
|
func (session *sessionData) reload() {
|
||||||
|
@ -323,6 +338,7 @@ func (session *sessionData) reload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
session.bridge.writeMessage(buffer.String())
|
session.bridge.writeMessage(buffer.String())
|
||||||
|
session.updateTooltipConstants()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *sessionData) ignoreViewUpdates() bool {
|
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`)
|
session.updateCSSProperty(htmlID, `column-span`, `none`)
|
||||||
}
|
}
|
||||||
return
|
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 {
|
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)" `)
|
buffer.WriteString(`onscroll="scrollEvent(this, event)" `)
|
||||||
|
|
||||||
keyEventsHtml(view, buffer)
|
keyEventsHtml(view, buffer)
|
||||||
mouseEventsHtml(view, buffer)
|
mouseEventsHtml(view, buffer, hasTooltip)
|
||||||
pointerEventsHtml(view, buffer)
|
pointerEventsHtml(view, buffer)
|
||||||
touchEventsHtml(view, buffer)
|
touchEventsHtml(view, buffer)
|
||||||
focusEventsHtml(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 {
|
func GetBackgroundBlendMode(view View, subviewID ...string) int {
|
||||||
return enumStyledProperty(view, subviewID, BackgroundBlendMode, BlendNormal, true)
|
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