So it turns out there were a couple of issues preventing the yui context menu from working correctly after an ajax request.
Even though there was a call to clearContent on the context menu during the on show event yui seemed to ignore this. This resulted in a doubling up of some menu items especially sub menu items. I fixed this by calling clearContent during the menu hide event. The even worse problem was yui totally ignoring the menu updates if the menu was not first destroyed. I fixed this by calling destroy on the menu before calling all the javascript to create the menu. This really seems like overkill to me but was the only way I could get it to work. I'm not sure why calling clearContent after a destroy was necessary but this fixes all my problems. Also I did not see any reason to make the add method protected in org.wicketstuff.yui.markup.html.menu2.contextMenu.Menu. So I opened that up and made it public. This allows the caller to add menu items and then refresh the panel via ajax and it all seems to work fine. I have tested these changes in a simple app with one page and one panel. I have also tested in a much more complicated app that contains a panel with popup and over a dozen context menus each with two sub menus and so far I have not found any problems. I have attached a patch. Please let me know what you think. If you have any suggestions please let me know. I am happy to help out where I can... On Mon, Jan 18, 2010 at 6:16 PM, Dave Kallstrom <dave.kallst...@gmail.com>wrote: > Interesting... I'll give that a try.. Thanks... > > > On Mon, Jan 18, 2010 at 6:06 PM, Alexander Elsholz < > alexander.elsh...@widas.de> wrote: > >> for my problem with dojo this works: >> >> public void refreshMenu(AjaxRequestTarget pTarget) { >> >> String js = "dojo.addOnLoad(function(){\n + menu.generateJS() >> + "\n});" ; >> pTarget.appendJavascript(sss); >> } >> >> >> and i know the same stuff works for jquery and yui. the problem is that >> the >> header javascript brokes after rerendering the component (i think its a >> problem >> with object references because most browsers replace the object by >> creating a >> new one and the javascript stuff bind on the dom-bject). What seems to >> work is >> to put the javascript stuff into the <body> tag using the >> onComponentRendered() >> to "reactivate" the behavior. >> >> the ugly is you have to reload the menu in every ajax-event reredering the >> component with menu. >> >> hth >> alex >> >> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org >> For additional commands, e-mail: users-h...@wicket.apache.org >> >> > > > -- > Dave Kallstrom > -- Dave Kallstrom
Index: src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/YuiContextMenuBehavior.java =================================================================== --- src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/YuiContextMenuBehavior.java (revision 5131) +++ src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/YuiContextMenuBehavior.java (working copy) @@ -17,6 +17,8 @@ public class YuiContextMenuBehavior extends AbstractDefaultAjaxBehavior { + private static final long serialVersionUID = -2453827056594475980L; + private static final String CONTEXT_MENU = "ContextMenu"; private List<YuiContextMenu> menus = new ArrayList<YuiContextMenu>(); private YuiContextMenu defaultMenu; @@ -30,24 +32,24 @@ for (int i = 0; i < menus.length; i++) { this.menus.add(menus[i]); } - this.defaultMenu = this.menus.get( 0 );; + this.defaultMenu = this.menus.get(0); } - - public void applyAttributes( Component comp, String menuId, IModel targetId ) { - YuiContextMenu menu = getMenuById( menuId ); - assert( menu != null); - applyAttributes( comp, menu, targetId ); + + public void applyAttributes(Component comp, String menuId, IModel<String> targetId) { + YuiContextMenu menu = getMenuById(menuId); + assert (menu != null); + applyAttributes(comp, menu, targetId); } - - public void applyAttributes( Component comp, YuiContextMenu menu, IModel targetId ) { + + public void applyAttributes(Component comp, YuiContextMenu menu, IModel<String> targetId) { comp.add(new AttributeModifier("targetId", true, targetId)); - comp.add(new AttributeModifier("contextMenuId", true, new Model( menu.getMenuId()))); + comp.add(new AttributeModifier("contextMenuId", true, new Model<String>(menu.getMenuId()))); } + @Override protected void respond(AjaxRequestTarget target) { String action = RequestCycle.get().getRequest().getParameter("action"); - String targetId = RequestCycle.get().getRequest().getParameter( - "targetId"); + String targetId = RequestCycle.get().getRequest().getParameter("targetId"); String menuId = RequestCycle.get().getRequest().getParameter("contextMenuId"); YuiContextMenu menu = getMenuById(menuId); @@ -79,43 +81,88 @@ } public CharSequence getCallBackScriptForMenu(String action) { - return generateCallbackScript("wicketAjaxGet('" + getCallbackUrl() - + "&action=" + action + "&targetId=' + targetId + '&contextMenuId=' + contextMenuId"); + return generateCallbackScript("wicketAjaxGet('" + getCallbackUrl() + "&action=" + action + "&targetId=' + targetId + '&contextMenuId=' + contextMenuId"); } + @Override public void renderHead(IHeaderResponse response) { super.renderHead(response); - YuiHeaderContributor.forModule("menu", null, false, "2.5.2") - .renderHead(response); - response.renderJavascriptReference(new ResourceReference( - YuiContextMenuBehavior.class, "contextMenu.js")); + YuiHeaderContributor.forModule("menu", null, false, "2.5.2").renderHead(response); + response.renderJavascriptReference(new ResourceReference(YuiContextMenuBehavior.class, "contextMenu.js")); + + String script = getMenuDestroyScript() + getMenuCreationScript() + getMenuInitializationScript(); + response.renderOnDomReadyJavascript(script); + } + + /** + * Method to destroy the context menu item if it exists. This really helps yui rebuild the menu after an ajax + * request + * + * @return + */ + private String getMenuDestroyScript() { StringBuffer buf = new StringBuffer(); - - - buf.append( getMenuCreationScript() ); - response.renderOnDomReadyJavascript(buf.toString() ); + String menuGetter = getYuiMenuScript(); + + buf.append("if( " + menuGetter + "){ "); + buf.append(menuGetter).append(".destroy(); \n } \n"); + + return buf.toString(); + } + + /** + * + * base start of scripts + */ + private String getYuiMenuScript() { + String menuName = getComponent().getMarkupId() + CONTEXT_MENU; + return "YAHOO.widget.MenuManager.getMenu(\"" + menuName + "\")"; } - - public String getMenuCreationScript() { + + /** + * Creates the menu initialization script. + * + * @return + */ + private StringBuffer getMenuInitializationScript() { StringBuffer buf = new StringBuffer(); - + + String menuGetter = getYuiMenuScript(); + + buf.append(menuGetter).append(".render( document.getElementById(\"").append(getComponent().getMarkupId()).append("\"));\n"); + buf.append(menuGetter).append(".beforeShowEvent.subscribe(onContextMenuBeforeShow);\n"); + buf.append(menuGetter).append(".hideEvent.subscribe(onContextMenuHideEvent);\n"); + + return buf; + + } + + /** + * Creates the menu definition script + * + * @return + */ + private String getMenuCreationScript() { + + StringBuffer buf = new StringBuffer(); + for (YuiContextMenu menu : menus) { List<MenuItem> items = menu.getAllMenuItems(); for (MenuItem mi : items) { - buf.append("function ").append(mi.getPathToRoot()).append( - "() {\n"); + buf.append("function ").append(mi.getPathToRoot()).append("() {\n"); buf.append(getCallBackScriptForMenu(mi.getMenuId())); buf.append("\n}\n"); } } StringBuffer menuDefn = new StringBuffer(); - menuDefn.append("var oContextMenuItems = {"); + String contextMenuItems = " oContextMenuItems" + getComponent().getMarkupId(); + menuDefn.append("var " + contextMenuItems + " = {"); Iterator<YuiContextMenu> menuIter = menus.iterator(); while (menuIter.hasNext()) { @@ -124,8 +171,7 @@ defaultMenu = menu; } - menuDefn.append("\"").append(menu.getMenuId()).append("\": [") - .append(menu.getItemData(this)); + menuDefn.append("\"").append(menu.getMenuId()).append("\": [").append(menu.getItemData(this)); menuDefn.append("]"); if (menuIter.hasNext()) { menuDefn.append(",\n"); @@ -135,26 +181,13 @@ buf.append(menuDefn.toString()); - String menuName = getComponent().getMarkupId() + "ContextMenu"; - - buf.append("\nvar ").append(menuName).append( - " = new YAHOO.widget.ContextMenu(\"").append(menuName).append( - "\",\n").append("{ trigger: document.getElementById(\"").append( - getComponent().getMarkupId()).append("\"), lazyload: true }") - .append(");\n"); - - buf.append(menuName).append(".menus = ").append("oContextMenuItems;\n"); + String menuName = getComponent().getMarkupId() + CONTEXT_MENU; - buf.append(menuName).append(".render( document.getElementById(\"").append( - getComponent().getMarkupId()).append("\"));\n"); + buf.append("\nvar ").append(menuName).append(" = new YAHOO.widget.ContextMenu(\"").append(menuName).append("\",\n").append("{ trigger: document.getElementById(\"").append(getComponent().getMarkupId()).append("\"), lazyload: true }").append(");\n"); - buf.append(menuName).append( - ".beforeShowEvent.subscribe(onContextMenuBeforeShow);\n"); + buf.append(menuName).append(".menus = ").append(contextMenuItems + ";\n"); - - return buf.toString(); } - } Index: src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/contextMenu.js =================================================================== --- src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/contextMenu.js (revision 5131) +++ src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/contextMenu.js (working copy) @@ -72,6 +72,16 @@ return id == null ? null : menus[id]; } + +/** + * Clearing the content on the hideEvent helps yui rebuild the menu + * correctly when it is displayed post ajax call. + */ + +function onContextMenuHideEvent(p_sType, p_aArgs){ + + this.clearContent(); +} function onContextMenuBeforeShow(p_sType, p_aArgs) { @@ -79,7 +89,7 @@ contextMenuId = GetMenuIdFromEventTarget(this.contextEventTarget); var aMenuItems = GetMenuFromEventTarget( this.contextEventTarget, this.menus ); - + this.clearContent(); if ( aMenuItems != null ) { Index: src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/Menu.java =================================================================== --- src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/Menu.java (revision 5131) +++ src/main/java/org/wicketstuff/yui/markup/html/menu2/contextMenu/Menu.java (working copy) @@ -22,12 +22,12 @@ private String className; private boolean clickToHide = true; private boolean disabled; - - public Menu( String id ) { - this( id, id ); + + public Menu(String id) { + this(id, id); } - public Menu(String id, String text ) { + public Menu(String id, String text) { super(id, text); } @@ -127,10 +127,12 @@ this.clickToHide = clickToHide; } + @Override public boolean isDisabled() { return disabled; } + @Override public void setDisabled(boolean disabled) { this.disabled = disabled; } @@ -150,10 +152,9 @@ /** * Add an item to the menu * - * @param child - * menu Item + * @param child menu Item */ - protected void add(AbstractMenuItem child) { + public void add(AbstractMenuItem child) { menuItems.add(child); child.parent = this; } @@ -165,8 +166,7 @@ /** * Return the {...@link MenuItem} according to its action * - * @param action - * action of a {...@link MenuItem} + * @param action action of a {...@link MenuItem} * @return the {...@link MenuItem} according to its action */ public MenuItem getMenuItem(String action) { @@ -180,27 +180,26 @@ if (ret != null) { break; } - } else if (item instanceof MenuItem - && item.getMenuId().equals(action)) { + } else if (item instanceof MenuItem && item.getMenuId().equals(action)) { ret = (MenuItem) item; } } return ret; } - + public List<MenuItem> getAllMenuItems() { List<MenuItem> items = new ArrayList<MenuItem>(); - - for ( AbstractMenuItem item : menuItems ) { + + for (AbstractMenuItem item : menuItems) { if (item instanceof Menu) { Menu menu = (Menu) item; - items.addAll( menu.getAllMenuItems() ); + items.addAll(menu.getAllMenuItems()); } else if (item instanceof MenuItem) { - items.add((MenuItem)item ); + items.add((MenuItem) item); } } - + return items; } @@ -217,10 +216,8 @@ props.put("y", y.toString()); } - props.put("fixedcenter", String.valueOf(fixedCenter)); - if (width != null) { props.put("width", width); } @@ -264,6 +261,7 @@ return props; } + @Override public String getItemData(YuiContextMenuBehavior behavior) { StringBuffer buf = new StringBuffer(); @@ -276,9 +274,8 @@ buf.append("\"").append(props.get(key)).append("\""); if (keys.hasNext()) { buf.append(",\n"); - } - else if ( menuItems.size() > 0 ) { - buf.append( ",\n" ); + } else if (menuItems.size() > 0) { + buf.append(",\n"); } } @@ -291,8 +288,8 @@ while (miIter.hasNext()) { AbstractMenuItem mi = miIter.next(); buf.append(mi.getItemData(behavior)); - if ( miIter.hasNext() ) { - buf.append( ",\n" ); + if (miIter.hasNext()) { + buf.append(",\n"); } }
--------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org