在jQuery UI Tooltip中获取对hovered元素的引用

Fab*_*tté 3 javascript firefox jquery jquery-ui jquery-ui-tooltip

基本上,我将一个open处理程序附加到我的jQuery UI工具提示,该工具提示对触发工具提示的元素执行一些检查.到目前为止我得到了什么:

$(document).tooltip({
  open: function(e, ui) {
    var el = e.toElement/* || e.relatedTarget*/;
    console.log(el.offsetWidth, el.scrollWidth);
    if (el.offsetWidth === el.scrollWidth) {
      ui.tooltip.hide();
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

上面的检查可防止工具提示出现,除非元素水平溢出,这是流体布局的一部分.它可以很好地在Chrome中运行,你可以在这个jsBin中看到.

但是,在Firefox中,event.toElementundefined.从阅读SO周围的线索,我认为这event.relatedTarget将是一个合适的替代品,但事实并非如此.在event.toElement引用当前悬停的项目时,event.relatedTargetmouseover引用中指向设备退出的元素,这是根据W3C规范的正确行为(类似于Chrome的event.fromTarget).

我也试过event.target,event.currentTargetthis参考,但这些点document,因为它是具有结合到工具提示的事件处理程序的节点.通过Tooltip API页面也没有帮助.

我不确定我是否忽略了一些非常基本的东西,或者我是否应该尝试更少的正统方法.

有没有办法获得对open在Firefox中工作的工具提示处理程序内部触发的元素的引用?或者是否有一些神奇的jQuery UI Tooltip选项/方法可以以更简单/类似的方式实现这种期望的行为?

Fab*_*tté 7

这是一个相当hackish的解决方案,但这是我刚刚发现的临时修复.编辑:在完成下面的第一个跨浏览器解决方案后,它根本不是那么hackish.下面列出的#1,#4#2解决方案应该可用.

jQuery Event对象有一个隐藏originalEvent属性,在问题的例子中是一个引用本机mouseover事件.因此event.originalEvent.target可以用于Chrome和Firefox.

open: function(e, ui) {
  var el = e.originalEvent.target;
  if (el.offsetWidth === el.scrollWidth) {
    ui.tooltip.hide();
  }
}
Run Code Online (Sandbox Code Playgroud)

箱子

当涉及旧的IE支持时,您将不得不event.srcElementevent.target不存在时使用.

var el = e.originalEvent.target || e.originalEvent.srcElement;
Run Code Online (Sandbox Code Playgroud)

箱子


#1跨浏览器解决方案

最后,当触发工具提示的元素中有嵌套元素时,您必须使用.closest()传递与工具提示的委托选择器相同的过滤器的方法对其进行monkeypatch (items选项,默认[title]:not([disabled])为UI 1.10.2):

var el = $(e.originalEvent.target || e.originalEvent.srcElement).closest($(this).tooltip('option', 'items'))[0];
Run Code Online (Sandbox Code Playgroud)

箱子

这基本上是什么工具提示部件内部确实如图所示这里.


#2替代的跨浏览器解决方案

通过使用简单的DOM查询不需要这么多变通办法的替代解决方案:

var el = $('[aria-describedby="'+ui.tooltip[0].id+'"]')[0];
Run Code Online (Sandbox Code Playgroud)

箱子


#3滥用内部方法

这不应该使用,但是通过覆盖内部_open方法,您可以访问targetjQuery对象,该对象包含作为参数传递给它的事件的目标元素.问题是,然后你甚至没有访问它的tooltip小部件,.tooltip('widget')因为它虽然已经存在于DOM中,但尚未"创建".您可以使用内部_find方法解决它,它将通过ID执行DOM查询,因此您可以hideshow动画启动后立即启动它,而它的实时周期不受影响 - 它将在那里并mouseleave照常删除,但是有display:none沿着这一切周期.

var bk_open = $.ui.tooltip.prototype._open;
$.ui.tooltip.prototype._open = function(event, target, content) {
  bk_open.apply(this, arguments);
  if (target[0].offsetWidth === target[0].scrollWidth) {
    this._find(target).hide();
  }
};

$(document).tooltip();
Run Code Online (Sandbox Code Playgroud)

箱子

那个DOM查询_find是不必要的,所以我们也可以扩展内部_tooltip方法,它返回一个包含该tooltip元素的jQuery对象,这样我们就可以使用JS的词法范围在我们重写_open执行之前保存对tooltip元素的引用:

var tooltipproto = $.ui.tooltip.prototype,
    bk_open = tooltipproto._open,
    bk_tooltip = tooltipproto._tooltip,
    $tooltip;
tooltipproto._open = function(event, target, content) {
  bk_open.apply(this, arguments);
  if (target[0].offsetWidth === target[0].scrollWidth) {
    $tooltip.hide();
  }
};
tooltipproto._tooltip = function(element) {
  return ($tooltip = bk_tooltip.apply(this, arguments));
};
$(document).tooltip();
Run Code Online (Sandbox Code Playgroud)

箱子

当然,当_tooltip内部方法接收targetas参数并返回时tooltip,可以完全覆盖此方法进行整个操作,但是当此方法返回后tooltipshown时,这将需要setTimeout(fn, 0)可能导致不希望的闪烁效应.

对于这么简单的事情来说,这是过于苛刻,笨拙和冗长.


#4清洁解决方案

"清理",如不使用未记录的方法,也不使用属性,也不使用原型覆盖或DOM查询.回到第一个片段,所有我们需要的是触发提示元素的引用.此元素由在处理程序之前调用thiscontent函数内部引用open,因此我们可以使用词法范围将该引用存储在上面的级别:

var el;
$(document).tooltip({
  content: function() {
    el = this;
    return this.title;
  },
  open: function(e, ui) {
    if (el.offsetWidth === el.scrollWidth) {
      ui.tooltip.hide();
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

箱子

请注意,content上面代码片段中的自定义函数删除了jQuery的默认HTML标记剥离(因为我喜欢在工具提示中使用HTML),但如果您使用用户输入的数据动态填充title属性,则可能会出现问题,以防万一你想保持原始content处理程序的功能:

var el,
    bk_content = $.ui.tooltip.prototype.options.content;
$(document).tooltip({
  content: function() {
    el = this;
    return bk_content.apply(this, arguments);
  },
  open: function(e, ui) {
    if (el.offsetWidth === el.scrollWidth) {
      ui.tooltip.hide();
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

箱子


我将在jQuery UI bugtracker上打开一张票,要求同时实现此功能.这是它:

工具提示:暴露在打开/关闭处理程序内触发工具提示的元素