基本上,我附上了 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();
}
}
});
上面的检查可以防止工具提示出现,除非元素水平溢出,这是流体布局的一部分。正如您在此 jsBin 中所见,它在 Chrome 中运行良好.
但是,在 Firefox 中,
event.toElement
是 undefined
.通过阅读 SO 周围的线程,我认为 event.relatedTarget
将是一个合适的替代品,但它不是。而event.toElement
引用当前悬停的项目 event.relatedTarget
在 mouseover
引用指针设备退出的元素,这是根据 W3C spec 的正确行为(类似于 Chrome 的 event.fromTarget
)。我也试过
event.target
, event.currentTarget
和 this
引用,但这些指向 document
因为它是绑定(bind)了工具提示事件处理程序的节点。通过Tooltip API页面也没有帮助。我不确定我是否忽略了一些非常基本的东西,或者我是否应该尝试更少的正统方法。
有没有办法获得对从工具提示的
open
内部触发的元素的引用?在 Firefox 中工作的处理程序?或者是否有一些神奇的 jQuery UI 工具提示选项/方法可以以更简单/类似的方式实现这种期望的行为?
最佳答案
这是一个相当骇人听闻的解决方案,但这是我刚刚找到的临时修复。 编辑:在完成了下面的第一个跨浏览器解决方案之后,它根本就不那么骇人听闻了。 #1 , #4 和 #2 下面列出的解决方案应该是可用的。
jQuery 事件对象有一个隐藏的 originalEvent
属性,在问题的情况下是引用 native mouseover
事件。因此event.originalEvent.target
可用于 Chrome 和 Firefox。
open: function(e, ui) {
var el = e.originalEvent.target;
if (el.offsetWidth === el.scrollWidth) {
ui.tooltip.hide();
}
}
Bin
当涉及到旧的 IE 支持时,您将不得不使用
event.srcElement
当 event.target
不存在。var el = e.originalEvent.target || e.originalEvent.srcElement;
Bin
#1 跨浏览器解决方案
最后,当触发工具提示的元素内部有嵌套元素时,您必须使用
.closest()
对其进行猴子补丁。传递与工具提示的委托(delegate)选择器相同的过滤器的方法( items
option ,默认为 [title]:not([disabled])
从 UI 1.10.2 开始):var el = $(e.originalEvent.target || e.originalEvent.srcElement).closest($(this).tooltip('option', 'items'))[0];
Bin
这基本上是 Tooltip Widget 在内部执行的操作,如图所示 here .
#2 替代的跨浏览器解决方案
通过使用简单的 DOM 查询不需要这么多变通方法的替代解决方案:
var el = $('[aria-describedby="'+ui.tooltip[0].id+'"]')[0];
Bin
#3 内部方法滥用
这不应该被使用,而是通过覆盖内部
_open
访问 target
的方法包含作为参数传递给它的事件的目标元素的 jQuery 对象。问题是,那么您无权访问它的 tooltip
小部件甚至没有通过.tooltip('widget')
因为它“尚未创建”,但已经存在于 DOM 中。您可以使用内部 _find
来解决它。将执行 DOM query by ID 的方法因此你可以hide
它就在 show
之后动画将启动,而其生命周期不受影响 - 它将在那里并在 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();
Bin
带有
_find
的 DOM 查询是相当不必要的,所以我们也可以扩展内部的_tooltip
方法返回一个包含 tooltip
的 jQuery 对象元素,所以我们可以使用 JS 的词法范围在我们被覆盖的 _open
之前保存对工具提示元素的引用执行: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();
Bin
当然,作为
_tooltip
内部方法接收 target
作为参数并返回 tooltip
,一个人可以只覆盖这个方法来完成整个操作,但是作为 tooltip
是 show
n 在此方法返回后,这将需要 setTimeout(fn, 0)
可能会导致不希望的闪烁效果。对于如此简单的事情来说,这过于hackish、繁琐和冗长。
#4 清洁解决方案
“干净”,即不使用未记录的方法、属性、原型(prototype)覆盖或 DOM 查询。回到第一个片段,我们所需要的只是对触发工具提示的元素的引用。此元素由
this
引用content
内部在 open
之前调用的函数处理程序,因此我们可以使用词法范围来存储该引用的上一级:var el;
$(document).tooltip({
content: function() {
el = this;
return this.title;
},
open: function(e, ui) {
if (el.offsetWidth === el.scrollWidth) {
ui.tooltip.hide();
}
}
});
Bin
请注意,我的自定义
content
上面代码片段中的函数删除了 jQuery 的 default HTML tags stripping (因为我喜欢在工具提示中使用 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();
}
}
});
Bin
我将在 jQuery UI bugtracker 上开一张票,要求同时实现此功能。这是它:
Tooltip: Expose element which triggered the tooltip inside open/close handlers
关于javascript - 在 jQuery UI 工具提示中获取对悬停元素的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16138869/