The current implementation of tooltip has a lot of flaws:
- The tooltip doesn’t calculate the correct position according to it’s size. For example when the tooltip is shown right at the edge of the screen, the tooltip isn’t visible.
- The tooltip hasn’t got a delay or cancels when the mouse leaves the target.
- For a lot of webix components, there are no suitable webix events to trigger the tooltip to show and/or hide.
- You cannot set the width or height to recalculate the tooltip position so, it doesn’t flow over.
The following code tries to fix these issues:
webix.ui({
id: id,
view: 'tooltip',
template: '#text#'
}).attachEvent('onAfterRender', function () {
// webix does not set width and height to tooltip
tip = $$(id).getNode();
style = tip.getAttribute('style') + " max-width: 200px; height: 200px;";
tip.setAttribute('style', style);
});
// hack to make onAfterRender work, otherwise the div has no style
$$(id).show({ text: ''}, { x: 0, y: 0});
$$(id).hide();
This makes sure that you get a tooltip with a fixed size.
module.exports = function (args) {
var tabs = args.tabs,
app = args.app,
debug = app.debug;
_.forEach(tabs, function (id) {
var tab = app.util.elly.$$('[button_id="'+ id +'"]')[0];
webix.event(tab, 'mouseenter', function (e) {
var evt = id + '.mouseenter';
debug('publish', evt);
app.bus.view.publish(id + '.mouseenter', { e: e, node: tab });
});
webix.event(tab, 'mouseleave', function () {
var evt = id + '.mouseleave';
debug('publish', evt);
app.bus.view.publish(id + '.mouseleave', { node: tab });
});
});
};
This code uses elly to get the tab divs of a tabview (don’t know how to do it with regular webix code). Then is attaches mouseenter events an mouseleave events to functions that publishes these events.
var tooltipId = 'tooltip',
debug = app.debug('client:controllers:tooltip');
app.bus.view.subscribe('*.*.mouseenter', function (data, envelope) {
var showTooltip = function () {
var text = tooltips[envelope.topic] ? tooltips[envelope.topic] : envelope.topic,
// calculate x pos
uiWidth = $$('ui').getNode().clientWidth,
tipWidth = 200,
totWidth = data.e.clientX + tipWidth,
x = totWidth > uiWidth ? (data.e.clientX - tipWidth) : data.e.clientX,
// calculate y pos
uiHeight = $$('ui').getNode().clientHeight,
tipHeight = 200,
totHeight = data.e.clientY + tipHeight,
y = totHeight > uiHeight ? (data.e.clientY - tipHeight) : data.e.clientY;
$$('tooltip').show({ text: text }, { x: x, y: y });
};
debug(envelope);
app.tooltip = _.delay(showTooltip, 1000);
});
app.bus.view.subscribe('*.*.mouseleave', function (data, envelope) {
debug(envelope);
clearTimeout(app.tooltip);
$$(tooltipId).hide();
});
This code listens to mouseenter and leave publications and then recalculate the position of the tooltip so it doesn’t flow over. It also delays showing the tooltip and destroys the showing when mouseleave occurs earlier.
Still this has issues as the tab button divs seem to get destroyed when a non selected tab is clicked. After that the mouse events get not triggered anymore.