This menu was designed to support 4 levels, and almost 900 different options items. One of the problems that I faced was that some options of the menu opens a af:popup with an af:dialog inside. That options needs to be opened when user clicks, and self-closed when user moves out of dialog.
In summary, I need the mix of "mouseHover" and "action" types on my <af:showPopupBehavior> tag.
Check the following video to see the menu in action.
To modify the expected behavior of <af:showPopupBehavior> type "action" I've created this simple JavaScript function to overwrite ADF JS library.
AdfShowPopupBehavior.prototype.fire = function (a)
{
a.cancel();
var b = AdfPage.PAGE, c = this._type, d = a.getSource(), e = d.getClientId(), f = d.findComponent(this._popupId);
if (AdfPage.PAGE.isScreenReaderMode() && (c == "mouseHover" || c == "mouseMove" || c == "mouseOver" || c == "mouseOut"))
AdfLogger.LOGGER.fine("showPopupBehavior trigger type " + c + " suppressed in screen reader mode for launch source id: " + e);
else if (f)
{
var g = f._delayedActivationState;
if (g)
if (g.launchSourceId == e)
return;
else
b.cancelTimer(g.timerId),
delete f._delayedActivationState;
if (f.isPopupVisible())
{
var h = this._getPopupWindow(f);
if (h == null)
return;
g = this._isInlinePopupSelector(h);
h = this._wasOpendedFromSameSource(h, e);
if (g)
{
if (f.hide(), h)
return
}
else
h || f.hide()
}
var k = this._align, h = this._alignId, g =
{
};
g[AdfRichPopup.HINT_LAUNCH_ID] = e;
var l = this._type == AdfComponentEvent.CONTEXT_MENU_EVENT_TYPE;
if (h || k || l)
{
k && (g[AdfRichPopup.HINT_ALIGN] = k, h || (h = d.getClientId(), k = h.lastIndexOf(":"), k != - 1 && (h = h.substring(k + 1))));
h && ((k = d.findComponent(h)) ? g[AdfRichPopup.HINT_ALIGN_ID] = k.getClientId() : AdfLogger.LOGGER.warning("Unable to find align component: ", h));
if (l)
g[AdfDhtmlPopupWindow.HINT_TYPE] = AdfDhtmlPopupWindow.HINT_TYPE_MENU, g[AdfDhtmlPopupWindow.HINT_AUTODISMISS] = AdfDhtmlPopupWindow.HINT_AUTODISMISS_MENU, h || (h = AdfAgent.AGENT.getMousePosition(a.getNativeEvent()), g[AdfDhtmlPopupWindow.HINT_MOUSEPOSITION] = h);
if (c == "mouseHover" || c == "action")
g[AdfDhtmlPopupWindow.HINT_AUTODISMISS] = AdfDhtmlPopupWindow.HINT_AUTODISMISS_MOUSEOUT, g[AdfDhtmlPopupWindow.HINT_AUTODISMISS_MOUSEOUT_ID] = g[AdfRichPopup.HINT_ALIGN_ID] ? g[AdfRichPopup.HINT_ALIGN_ID] : g[AdfRichPopup.HINT_LAUNCH_ID]
}
a.getType() == AdfUIInputEvent.MOUSE_IN_EVENT_TYPE ? (a = b.scheduleTimer(this, this._onMouseOverTimeout,
{
hints : g, popup : f, source : d
},
500), f._delayedActivationState =
{
timerId : a, launchSourceId : e
},
d.addEventListener(AdfUIInputEvent.MOUSE_OUT_EVENT_TYPE, this._fireCancel, this)) : f.show(g)
}
else
AdfLogger.LOGGER.severe("Could not find popup ", this._popupId, " from component ", d)
};
The line that changes the expected behavior is this one:
if (c == "mouseHover" || c == "action")
Include that JS fragment in a JS file and later import to your pageTemplate or JSPX page:
<af:resource type="javascript" source="../js/popbehavior.js"/>
Also, you can modify the delay time of mouse-out event modifiying the "500ms" value in the JS code.