APEX开发实践(23):鼠标悬停浮窗(Tooltip)的实现

前两天,有朋友找到我,想实现一个APEX的鼠标悬停浮窗(Tooltip)的功能。一个典型的应用案例就是:有一张部门信息的交互报表,当鼠标放在部门ID上时,页面浮窗显示该部门的人员信息。当鼠标移开后,浮窗随之消失。

本案例中,通过两种方式实现。第一种方式是通过JS代码调用AJAX处理实现;第二种方式是直接使用一个免费的Tooltip插件。这里感谢APEX中国社区的不忘初心,风华正茂两位同学给的启示和帮助。下面分享一下实现方式。

1、JS + AJAX回调

1.1、在页面上加载/执行3个JS事件

在页级属性的加载页时执行中创建3个JS事件:
  • 处理鼠标悬停;
  • 发送ajax处理请求;
  • 当鼠标移开时销毁浮窗。

具体JS代码如下:
// 鼠标悬停事件
$(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做列格式化设置

记住,这里定义的类id-col,以及pk会在后面的动态操作中被引用。表达式中总共可以设置3个参数pk,sk,tk,用于动态操作中的参数传递。
代码如下,如果有第2,3个参数,跟在pk后面,sk="......" tk="......"
<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语句必须输出两个字段,TOOLTIPBACKGROUNDCOLORTOOLTIP用于浮窗中显示的信息,本案例是制表输出的员工号和姓名;BACKGROUNDCOLOR用于设置浮窗的底色。

另外,原插件中,把浮窗的宽度设死为400px。在Option JSON里,把maxwidth设置为100%,浮窗就可以自适应宽度。

 

以上分享了鼠标悬停浮窗的两种实现方式,第一种更灵活,但需要一定的JS,CSS的编程经验;第二种更方便易用。大家根据具体应用场景选择使用。

posted @ 2025-06-27 14:40  搬砖的徐大爷  阅读(8)  评论(0)    收藏  举报