APEX开发实践(23):鼠标悬停浮窗(Tooltip)的实现
前两天,有朋友找到我,想实现一个APEX的鼠标悬停浮窗(Tooltip)的功能。一个典型的应用案例就是:有一张部门信息的交互报表,当鼠标放在部门ID上时,页面浮窗显示该部门的人员信息。当鼠标移开后,浮窗随之消失。
1、JS + AJAX回调
1.1、在页面上加载/执行3个JS事件
- 处理鼠标悬停;
- 发送ajax处理请求;
- 当鼠标移开时销毁浮窗。
// 鼠标悬停事件
$(document).on("mouseenter", ".dynamic-tooltip", function (e) {
var $this = $(this);
var tooltip = $('<div class="custom-tooltip"><span class="loading-indicator">Loading...</span></div>');
if ($this.data("loaded") === "true") return;
tooltip.appendTo("body").css({
top: e.pageY + 10,
left: e.pageX + 10
});
const deptno = $this[0].innerText;
// 发送AJAX请求
apex.server.process("GET_DETAIL_DATA", {
x01: deptno // 确保属性名一致
}, {
dataType: "html", // 明确指定类型
success: function (pData) {
console.log(pData);
tooltip.html(pData); // 直接插入HTML
$this.data("loaded", "true");
},
error: function () {
tooltip.html('<span style="color:red">Error loading data</span>');
}
});
});
// 鼠标移出时销毁
$(document).on("mouseleave", ".dynamic-tooltip", function () {
$(".custom-tooltip").remove();
$(this).data("loaded", "false");
});
另外,可以在页属性的内嵌CSS中增加CSS定义。
具体CSS代码如下:
.custom-tooltip {
position: absolute; /* 绝对定位 */
background: #fff; /* 白色背景 */
border: 1px solid #ddd;
border-radius: 4px;
padding: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
z-index: 10000; /* 确保悬浮在最上层 */
max-width: 600px; /* 最大宽度限制 */
font-size: 12px;
}
.loading-indicator {
color: #666;
font-style: italic;
}
1.2、在交互报表对应的字段进行列格式化设置
在本案例中,取DEPTNO字段。在DEPTNO字段的属性的列格式化设置如下:
代码如下:
<a href="#" style="cursor:pointer;"
class="dynamic-tooltip"
data-id="#DEPTNO#"
data-loaded="false">#DEPTNO#</a>
3、最后创建一个AJAX回调的处理
代码如下:
DECLARE
l_html VARCHAR2(4000);
BEGIN
SELECT '<table class="detail-table">' ||
LISTAGG('<tr><td>' || EMPNO || '</td><td>' || ENAME || '</td></tr>') ||
'</table>'
INTO l_html
FROM emp
WHERE deptno = TO_NUMBER(apex_application.g_x01);
htp.prn(l_html);
EXCEPTION
WHEN NO_DATA_FOUND THEN
htp.prn('<div>No records found</div>');
END;
2、Tooltip插件
做完第一种方式之后,我就想apex.world上有没有现成的插件可以使用呢。然后我在apex.world上就找到牛人Ronny Weiss开发的免费的插件Dynamic Tooltip。
赶紧下载,导入重新把这个鼠标悬停浮窗的功能又做了一遍。不得不承认插件的方便和强大。所需要做的仅仅是创建一个隐藏的APEX页项和创建并配置一个动态操作。
2.1、与上面第一种方式的第2步相似,对DEPTNO做列格式化设置

<span class="id-col" pk="#DEPTNO#" style="cursor:pointer">#DEPTNO#</span>
2.2、创建一个隐藏的页项
这个页项P4_ID也会在Tooltip动态操作中被使用,在本案例中,通过这个页项传递上面第1步设置的pk参数。
2.3、配置Tooltip动态操作
-
注意Element Selector的设置,是上面第1步的DEPTNO列表达式的定义好的类的名称;
-
注意Primary Key(pk)的设置,是上面第2步创建的隐藏页项。如果有更多的参数需要传参,可以设置到后面的Secondary Key(sk),Tertiary Key(tk)中;
-
如果要把隐藏页项传递到SQL中,那需要设置到Items to Submit中;
-
浮窗通过两种方式激发,鼠标悬停(Mouseover),鼠标点击(Click);
-
如果浮窗显示的信息是H5代码(如本案例中会用到H5制表标识符<tr><td>输出),必须关闭Escape special Characters并打开旁路HTML(Sanitize HTML);
- 打开初始化时触发的开关。
最后讲解一下动态操作中使用的SQL代码。代码如下:
SELECT
'<table>' ||
LISTAGG(
'<tr><td>' || empno || '</td><td>' || ename || '</td></tr>',
''
) WITHIN GROUP (ORDER BY empno) ||
'</table>' AS TOOLTIP,
'rgba(240, 240, 240, 1)' AS BACKGROUNDCOLOR
FROM emp
WHERE deptno = :P4_ID
SELECT语句必须输出两个字段,TOOLTIP和BACKGROUNDCOLOR。TOOLTIP用于浮窗中显示的信息,本案例是制表输出的员工号和姓名;BACKGROUNDCOLOR用于设置浮窗的底色。
另外,原插件中,把浮窗的宽度设死为400px。在Option JSON里,把maxwidth设置为100%,浮窗就可以自适应宽度。
以上分享了鼠标悬停浮窗的两种实现方式,第一种更灵活,但需要一定的JS,CSS的编程经验;第二种更方便易用。大家根据具体应用场景选择使用。