对单击的 MenuButton 作出反应

React to a MenuButton being clicked

我们有定期刷新文档的代码。作为 JSF 页面的一部分,我们还有 menuButtons(primefaces),最初作为列中 dataTable cell/s 的一部分。我们希望在单击 menuButton 时禁用刷新(菜单展开),并在关闭 menuButton 时重新启用它(以防止页面刷新关闭菜单)。

我尝试使用 java 脚本捕获 menuButton 事件,但无济于事。部分问题是我不知道如何从 java 脚本中唯一地识别 JSF 组件,因为在尝试捕获事件时 ID 似乎不起作用。也没有任何令人满意的事件属性(作为 Primefaces menuButton 的一部分)我可以连接到 javascript.

下面是我可以提取的最少代码。为简单起见,我已将菜单单独提取(不是 dataTable 的一部分),因为问题仍然存在。我可能在那里引用了一个 bean 和字典文件,但你应该明白了:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:p="http://primefaces.org/ui"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:ui="http://java.sun.com/jsf/facelets">

   <h:form id="virtualMachineTableForm">

      <!-- Lazy load table -->
      <p:remoteCommand name="lazyload" 
                       update=":vmGroupTabs:virtualMachineTableForm:testMenu" 
                       actionListener="#{backupGroupController.refreshHard()}" />

      <!-- Refresh hard button -->
      <p:commandButton id="refreshButton" 
                       update=":vmGroupTabs:virtualMachineTableForm:testMenu" 
                       icon="ui-icon-refresh" 
                       immediate="true" 
                       title="#{msg.action_refresh}" 
                       actionListener="#{backupGroupController.refreshHard()}"/>

      <p:menuButton
         id="testMenu"
         value="#{msg.menuButton_SelectItem}">
         <p:menuitem
            value="Toggle refresh"
            onclick="toggleRefreshState()">
         </p:menuitem>
      </p:menuButton>

      <!-- Poller -->
      <p:poll interval="5" listener="#{backupGroupController.refreshSoft()}" 
              update=":vmGroupTabs:virtualMachineTableForm:testMenu" widgetVar="poll" />
   </h:form>

   <script type="text/javascript">

      var toggleRefreshState = function(){
         if (poll.isActive()) {
            poll.stop();
            alert("Poller stopped" );
         }
         else {
            poll.start();
            alert("Poller started" );
         }
      };

      $(document).ready(function(){
         poll.start();
         setTimeout("lazyload();", 100);
      });
//
//      $("???SomeWayToIdentifyMenu???").on({
//            onMenuOpen???: function(){
//               alert("Opening menu - stopping refresh");
//            }
//            onMenuClose???: function(){
//               alert("Closing menu - starting refresh");
//            }
//      });
</script>

</ui:composition>

感谢您的帮助,谢谢,

维尔纳

实现此目的的最简单方法是将 javascript 添加到 menuButtons 以更改全局变量并让定期刷新读取该全局变量并相应地执行操作。由于您没有代码或指示您正在使用哪些组件,因此我无法获得更具体的信息。这是我希望看到的 javascript 代码

window.preventRefresh = false;

function doPeriodicRefresh() {
  if(!preventRefresh) {
    window.location.reload();
  }
} 

setInterval(doPeriodicRefresh, 60000);

function showMenu() {
  window.preventRefresh = true;
  menu.show();
}

function hideMenu() {
  window.preventRefresh = false;
  menu.hide();
}

你的 mouseovers/mouseout 菜单应该调用 showMenu 和 hideMenu,任何参数都必须通过代理。

这也取决于您如何进行定期刷新。如果您使用的是 refresh header 或元标记,我认为您无法从 javascript 中阻止这些。

最后都是html、javascript和css。 PF 中的 Javascript 主要是 jquery,所有组件背后都有 javascript 代码以在客户端运行。

有几种方法可以插入。将纯 jquery 事件处理程序附加到正确的元素(可通过浏览器开发工具 and/or 检查 PrimeFaces javascript 的作用)是一种选择,但您必须一遍又一遍地重新应用它们当例如ajax 调用发生。另一种选择是在不更改 PF 原始源的情况下覆盖基本菜单按钮功能。

由于代码是开源的,您可以尝试找到PrimeFaces MenuButton的javascript源码。在这种情况下,所有内容都在 menu.js 中定义,并且可以很容易地查看(并且写得很清楚)

在那里你可以看到添加到组件的所有事件,如果有,例如是否有 onBeforeShow 处理程序(PrimeFaces 中的某些组件有那些,MenuButton 没有,这对你来说很不幸,但到目前为止我还没有看到这样的用例)。

不幸的是,覆盖基本功能的缺点是 所有 菜单按钮都是如此。所以你必须实现一些逻辑来决定你是否真的需要执行一些自定义操作。有几种方法可以做到这一点,但我认为最简单的方法是检查是否存在特定样式 class(例如 'stopPoll')。

现在开始实际的覆盖:

var oldPFShow = PrimeFaces.widget.MenuButton.prototype.show
PrimeFaces.widget.MenuButton.prototype.show = function() {
  alert("before show");
  oldPFShow.apply(this, arguments);
}

var oldPFHide = PrimeFaces.widget.MenuButton.prototype.hide
PrimeFaces.widget.MenuButton.prototype.hide = function() {
  oldPFHide.apply(this, arguments);
  alert("after hide");
}

(别忘了调用原来的函数)

在我放置警报的地方,您必须实施检查 class 的存在,或者如果您在该页面上有一个菜单按钮或想要所有菜单按钮的行为,则将其忽略

一些一般性的评论:(稍后会删除,但很难在评论中格式化)

I've attempted to catch menuButton events using java script, but to no avail.

发布尝试会有所帮助,因为有时您很接近并且只是有一些小的疏忽)。在这些情况下,为试图提供支持的人写一个答案会更容易

Part of the problem is that I do not know how to identify the JSF component uniquely from javascript,

这是一个通用的 PrimeFaces 事物(不同于组件集)。应用 widgetVar 属性并使用 PF('') 您可以处理特定组件。

如您所见,您使用 PrimeFaces menuButton 的明确事实是最重要的。有一小段代码(比你现在拥有的要小,但对 mcve 的赞美)是对这一点的确认(假设是一切之母......)添加 'javascript' 作为一个非常通用的标签,通常会吸引 'wrong' 人,和 'java' 一样,所以下次请将这些排除在外