You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2010/03/29 03:18:22 UTC

svn commit: r928556 [3/5] - in /myfaces/tomahawk/trunk/core20: ./ src/main/conf/META-INF/ src/main/java/org/apache/myfaces/custom/calendar/ src/main/java/org/apache/myfaces/custom/inputHtml/ src/main/java/org/apache/myfaces/custom/inputTextHelp/ src/ma...

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/inputTextHelp/HtmlTextHelpRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/inputTextHelp/HtmlTextHelpRenderer.java?rev=928556&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/inputTextHelp/HtmlTextHelpRenderer.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/inputTextHelp/HtmlTextHelpRenderer.java Mon Mar 29 01:18:21 2010
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.inputTextHelp;
+
+import java.io.IOException;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.convert.ConverterException;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+
+import org.apache.myfaces.renderkit.html.ext.HtmlTextRenderer;
+import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.tomahawk.application.PreRenderViewAddResourceEvent;
+import org.apache.myfaces.tomahawk.util.TomahawkResourceUtils;
+
+/**
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC"
+ *   family = "javax.faces.Input"
+ *   type = "org.apache.myfaces.TextHelp"
+ * 
+ * @author Thomas Obereder
+ * @version Date: 09.06.2005, 22:50:48
+ */
+@ListenerFor(systemEventClass=PreRenderViewAddResourceEvent.class)
+public class HtmlTextHelpRenderer extends HtmlTextRenderer  implements ComponentSystemEventListener
+{
+    private static final String JAVASCRIPT_ENCODED = "org.apache.myfaces.inputTextHelp.JAVASCRIPT_ENCODED";
+
+    public void processEvent(ComponentSystemEvent event)
+    {
+        if(event.getComponent() instanceof HtmlInputTextHelp)
+        {
+            TomahawkResourceUtils.addOutputScriptResource(FacesContext.getCurrentInstance(),
+                    "oam.custom.inputTextHelp", 
+                    "inputTextHelp.js");
+        }
+    }
+    
+    protected void renderNormal(FacesContext facesContext, UIComponent component) throws IOException
+    {
+        if(component instanceof HtmlInputTextHelp)
+        {
+            HtmlInputTextHelp helpTextComp = (HtmlInputTextHelp) component;
+            //addJavaScriptResources(facesContext);
+            renderInputTextHelp(facesContext, helpTextComp);
+        }
+        else
+        {
+            super.renderNormal(facesContext, component);
+        }
+    }
+
+    public static boolean isSelectText(UIComponent component)
+    {
+        if(component instanceof HtmlInputTextHelp)
+        {
+            HtmlInputTextHelp helpTextComp = (HtmlInputTextHelp) component;
+            return helpTextComp.isSelectText();
+        }
+        return false;
+    }
+
+    public static String getHelpText(UIComponent component)
+    {
+        if(component instanceof HtmlInputTextHelp)
+        {
+            HtmlInputTextHelp helpTextComp = (HtmlInputTextHelp) component;
+            if(helpTextComp.getHelpText() != null)
+                return helpTextComp.getHelpText();
+        }
+        return null;
+    }
+
+    public void renderInputTextHelp(FacesContext facesContext, UIInput input)
+            throws IOException
+    {
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        writer.startElement(HTML.INPUT_ELEM, input);
+
+        writer.writeAttribute(HTML.ID_ATTR, input.getClientId(facesContext), null);
+        writer.writeAttribute(HTML.NAME_ATTR, input.getClientId(facesContext), null);
+        writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_TEXT, null);
+
+        renderHelpTextAttributes(input, writer, facesContext);
+
+        String value = RendererUtils.getStringValue(facesContext, input);
+        value = (value==null || value.length()==0) ? getHelpText(input) : value;
+
+        if (value != null)
+        {
+            writer.writeAttribute(HTML.VALUE_ATTR, value, JSFAttr.VALUE_ATTR);
+        }
+
+        writer.endElement(HTML.INPUT_ELEM);
+    }
+
+    private void renderHelpTextAttributes(UIComponent component,
+                                          ResponseWriter writer,
+                                          FacesContext facesContext)
+            throws IOException
+    {
+        if(!(component instanceof HtmlInputTextHelp) || getHelpText(component) == null || ("").equals(getHelpText(component).trim()))
+        {
+            HtmlRendererUtils.renderHTMLAttributes(writer, component, HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
+        }
+        else
+        {
+            String id = component.getClientId(facesContext);
+            HtmlInputTextHelp textHelp = (HtmlInputTextHelp)component;
+            
+            HtmlRendererUtils.renderHTMLAttributes(writer, component,
+                                                   HTML.INPUT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_ONFOCUS_AND_ONCLICK);
+            writer.writeAttribute(HTML.ONFOCUS_ATTR,
+                                  buildJavascriptFunction(component, id, textHelp.getOnfocus()), null);
+            writer.writeAttribute(HTML.ONCLICK_ATTR,
+                                  buildJavascriptFunction(component, id, textHelp.getOnclick()), null);
+        }
+
+        if (isDisabled(facesContext, component))
+        {
+            writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, null);
+        }
+    }
+    
+    private String buildJavascriptFunction(UIComponent component, String id, String componentScript) 
+    {
+        StringBuffer jsFunction = new StringBuffer();
+        if(isSelectText(component))
+        {
+            jsFunction.append(HtmlInputTextHelp.JS_FUNCTION_SELECT_TEXT);
+            jsFunction.append("('");
+            jsFunction.append(    getHelpText(component)).append("', '");
+            jsFunction.append(    id);
+            jsFunction.append("')");
+        }
+        else
+        {
+            jsFunction.append(HtmlInputTextHelp.JS_FUNCTION_RESET_HELP );
+            jsFunction.append("('");
+            jsFunction.append(    getHelpText(component)).append("', '");
+            jsFunction.append(    id);
+            jsFunction.append("')");
+        }
+        
+        if(componentScript != null && !("").equals(componentScript.trim())) {
+            jsFunction.append(";");
+            jsFunction.append(componentScript);
+        }
+        
+        return jsFunction.toString();
+    }
+
+    public void decode(FacesContext facesContext, UIComponent component)
+    {
+        super.decode(facesContext, component);
+    }
+
+    public Object getConvertedValue(FacesContext facesContext, UIComponent component, Object submittedValue) throws ConverterException
+    {
+        if(submittedValue!=null && component instanceof HtmlInputTextHelp &&
+           ((HtmlInputTextHelp) component).getHelpText()!=null &&
+           submittedValue.equals(((HtmlInputTextHelp) component).getHelpText()))
+        {
+            submittedValue = "";
+        }
+
+        return super.getConvertedValue(facesContext, component, submittedValue);
+    }
+
+    /*public static void addJavaScriptResources(FacesContext facesContext)
+    {
+        // check to see if javascript has already been written (which could happen if more than one calendar on the same page)
+        if (facesContext.getExternalContext().getRequestMap().containsKey(JAVASCRIPT_ENCODED))
+        {
+            return;
+        }
+
+        AddResourceFactory.getInstance(facesContext).addJavaScriptAtPosition(
+                facesContext, AddResource.HEADER_BEGIN, HtmlTextHelpRenderer.class, "inputTextHelp.js");
+
+        facesContext.getExternalContext().getRequestMap().put(JAVASCRIPT_ENCODED, Boolean.TRUE);
+    }*/
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/jslistener/JsValueChangeListenerRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/jslistener/JsValueChangeListenerRenderer.java?rev=928556&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/jslistener/JsValueChangeListenerRenderer.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/jslistener/JsValueChangeListenerRenderer.java Mon Mar 29 01:18:21 2010
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.jslistener;
+
+import java.io.IOException;
+
+import javax.faces.application.Application;
+import javax.faces.application.ResourceDependency;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.context.FacesContext;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
+
+/**
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC" 
+ *   family = "javax.faces.Output"
+ *   type = "org.apache.myfaces.JsValueChangeListener"
+ * 
+ * @author Martin Marinschek (latest modification by $Author: skitching $)
+ * @version $Revision: 673833 $ $Date: 2008-07-03 16:58:05 -0500 (jue, 03 jul 2008) $
+ */
+@ResourceDependency(library="oam.custom.jslistener",name="JSListener.js")
+public class JsValueChangeListenerRenderer
+        extends HtmlRenderer
+{
+    private static Log log = LogFactory.getLog(JsValueChangeListenerRenderer.class);
+
+    public void encodeEnd(FacesContext facesContext, UIComponent component)
+            throws IOException
+    {
+        RendererUtils.checkParamValidity(facesContext, component, JsValueChangeListener.class);
+
+        UIComponent parent = component.getParent();
+
+        JsValueChangeListener jsValueChangeListener = (JsValueChangeListener) component;
+
+
+        String aFor = jsValueChangeListener.getFor();
+        String expressionValue = jsValueChangeListener.getExpressionValue();
+        String property = jsValueChangeListener.getProperty();
+
+        //AddResourceFactory.getInstance(facesContext).addJavaScriptAtPosition(
+        //        facesContext, AddResource.HEADER_BEGIN, JsValueChangeListenerRenderer.class,
+        //        "JSListener.js");
+
+        if(aFor!=null)
+        {
+            UIComponent forComponent = component.findComponent(aFor);
+
+            String forComponentId = null;
+
+            if (forComponent == null)
+            {
+                if (log.isInfoEnabled())
+                {
+                    log.info("Unable to find component '" + aFor + "' (calling findComponent on component '" + component.getClientId(getFacesContext()) + "') - will try to render component id based on the parent-id (on same level)");
+                }
+                if (aFor.length() > 0 && aFor.charAt(0) == UINamingContainer.SEPARATOR_CHAR)
+                {
+                    //absolute id path
+                    forComponentId = aFor.substring(1);
+                }
+                else
+                {
+                    //relative id path, we assume a component on the same level as the label component
+                    String labelClientId = component.getClientId(getFacesContext());
+                    int colon = labelClientId.lastIndexOf(UINamingContainer.SEPARATOR_CHAR);
+                    if (colon == -1)
+                    {
+                        forComponentId = aFor;
+                    }
+                    else
+                    {
+                        forComponentId = labelClientId.substring(0, colon + 1) + aFor;
+                    }
+                }
+            }
+            else
+            {
+                forComponentId = forComponent.getClientId(getFacesContext());
+            }
+
+            expressionValue = expressionValue.replaceAll("\\'","\\\\'");
+            expressionValue = expressionValue.replaceAll("\"","\\\"");
+
+
+            String methodCall = "orgApacheMyfacesJsListenerSetExpressionProperty('"+
+                    parent.getClientId(getFacesContext())+"','"+
+                    forComponentId+"',"+
+                    (property==null?"null":"'"+property+"'")+
+                    ",'"+expressionValue+"');";
+
+
+            callMethod(facesContext, jsValueChangeListener, "onchange",methodCall);
+
+            if (jsValueChangeListener.getBodyTagEvent() != null)
+            {
+                callMethod(facesContext, jsValueChangeListener, jsValueChangeListener.getBodyTagEvent(), methodCall);
+            }
+
+        }
+    }
+
+    private void callMethod(FacesContext context, JsValueChangeListener jsValueChangeListener, String propName, String value)
+    {
+        UIComponent parent = jsValueChangeListener.getParent();
+
+        Object oldValue = parent.getAttributes().get(propName);
+        
+        if(oldValue != null)
+        {
+            String oldValueStr = oldValue.toString().trim();
+
+            // render the jsValueChangeListener script only for each parent component 
+            if(oldValueStr.indexOf(parent.getClientId(FacesContext.getCurrentInstance())) < 0
+                    && oldValueStr.length() > 0)
+            {
+                oldValueStr = "";
+            }
+
+            if(oldValueStr.length()>0 && !oldValueStr.endsWith(";"))
+                oldValueStr +=";";
+
+            value = oldValueStr + value;
+
+        }
+
+        if (!propName.equals("onchange") && value != null)
+        {
+            //TODO: this should be refactored to register a javascript-event-wrapper the java-script way
+            //in the current version of AddResource, this would not work anymore
+            /*AddResourceFactory.getInstance(context).
+                    addJavaScriptToBodyTag(context,jsValueChangeListener.getBodyTagEvent(), value);*/
+        }
+        else if(value != null)
+        {
+            parent.getAttributes().put(propName, value);
+        }
+        else
+        {
+            try
+            {
+                parent.getAttributes().remove(propName);
+            }
+            catch(Exception ex)
+            {
+                log.error("the value could not be removed : ",ex);
+            }
+        }
+    }
+
+
+    protected Application getApplication()
+    {
+        return getFacesContext().getApplication();
+    }
+
+    protected FacesContext getFacesContext()
+    {
+        return FacesContext.getCurrentInstance();
+    }
+
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/navmenu/htmlnavmenu/HtmlNavigationMenuRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/navmenu/htmlnavmenu/HtmlNavigationMenuRenderer.java?rev=928556&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/navmenu/htmlnavmenu/HtmlNavigationMenuRenderer.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/navmenu/htmlnavmenu/HtmlNavigationMenuRenderer.java Mon Mar 29 01:18:21 2010
@@ -0,0 +1,593 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.navmenu.htmlnavmenu;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIGraphic;
+import javax.faces.component.UIOutput;
+import javax.faces.component.UISelectItems;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.el.ValueBinding;
+import javax.faces.event.ActionListener;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.custom.navmenu.NavigationMenuItem;
+import org.apache.myfaces.custom.navmenu.NavigationMenuUtils;
+import org.apache.myfaces.custom.navmenu.UINavigationMenuItem;
+import org.apache.myfaces.renderkit.html.ext.HtmlLinkRenderer;
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
+import org.apache.myfaces.tomahawk.application.PreRenderViewAddResourceEvent;
+import org.apache.myfaces.tomahawk.util.TomahawkResourceUtils;
+
+/**
+ * Many thanks to the guys from Swiss Federal Institute of Intellectual Property & Marc Bouquet
+ * for helping to develop this component.
+ *
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC" 
+ *   family = "javax.faces.Panel"
+ *   type = "org.apache.myfaces.NavigationMenu"
+ *   
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC" 
+ *   family = "javax.faces.Command"
+ *   type = "org.apache.myfaces.NavigationMenu"
+ *
+ * @author Thomas Spiegl
+ * @author Manfred Geiler
+ */
+@ListenerFor(systemEventClass=PreRenderViewAddResourceEvent.class)
+public class HtmlNavigationMenuRenderer extends HtmlLinkRenderer
+    implements ComponentSystemEventListener
+{
+    private static final Log log = LogFactory.getLog(HtmlNavigationMenuRenderer.class);
+
+    public static final String RENDERER_TYPE = "org.apache.myfaces.NavigationMenu";
+
+    private static final Integer ZERO_INTEGER = new Integer(0);
+
+    private static final String HORIZ_MENU_SCRIPT = "HMenuIEHover.js";
+
+    public void processEvent(ComponentSystemEvent event)
+    {
+        HtmlPanelNavigationMenu panelNav = (HtmlPanelNavigationMenu) event.getComponent();
+        if (HtmlNavigationMenuRendererUtils.isListLayout(panelNav))
+        {
+            if (panelNav.isRenderAll())
+            {
+                addResourcesToHeader(FacesContext.getCurrentInstance());
+            }
+        }
+    }
+
+    public boolean getRendersChildren() {
+        return true;
+    }
+
+    public void decode(FacesContext facesContext, UIComponent component) {
+        if (component instanceof HtmlCommandNavigationItem) {
+            //HtmlCommandNavigation
+            super.decode(facesContext, component);
+        }
+    }
+
+    public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+        if (component instanceof HtmlCommandNavigationItem) {
+            //HtmlCommandNavigationItem
+            super.encodeBegin(facesContext, component);
+        }
+    }
+
+    public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException {
+        if (component instanceof HtmlCommandNavigationItem) {
+            //HtmlCommandNavigationItem
+            super.encodeChildren(facesContext, component);
+        }
+    }
+
+    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+        if (component instanceof HtmlCommandNavigationItem) {
+            //HtmlCommandNavigationItem
+            super.encodeEnd(facesContext, component);
+            return;
+        }
+        RendererUtils.checkParamValidity(facesContext, component, HtmlPanelNavigationMenu.class);
+        HtmlPanelNavigationMenu panelNav = (HtmlPanelNavigationMenu) component;
+
+        if (HtmlNavigationMenuRendererUtils.isListLayout(panelNav)) {
+            boolean preprocess = true;
+            boolean clientStateSaving = facesContext.getApplication().getStateManager().isSavingStateInClient(facesContext);
+            if (clientStateSaving) {
+                // client statesaving
+                HtmlPanelNavigationMenu panelNavPrev = findPreviousPanelNav(facesContext, panelNav);
+                if (panelNavPrev != null) {
+                    preprocess = false;
+                    if (!panelNavPrev.equals(panelNav)) {
+                        // substitute panelnav
+                        UIComponent parent = panelNav.getParent();
+                        int insertPos = parent.getChildren().indexOf(panelNav);
+                        parent.getChildren().set(insertPos, panelNavPrev);
+                        panelNavPrev.setParent(parent);
+                        panelNav.setParent(null);
+                        panelNav = panelNavPrev;
+                    }
+                }
+            }
+            else {
+                // server statesaving
+                if (panelNav.getPreprocessed() != null && panelNav.getPreprocessed().booleanValue())
+                    preprocess = false;
+            }
+            if (preprocess) {
+                panelNav.setPreprocessed(Boolean.TRUE);
+                preprocessNavigationItems(facesContext, panelNav, panelNav.getChildren(), new UniqueId());
+                if (!clientStateSaving) {
+                    HtmlPanelNavigationMenu panelNavPrev = findPreviousPanelNav(facesContext, panelNav);
+                    if (panelNavPrev != null) {
+                        restoreOpenActiveStates(facesContext, panelNav, panelNavPrev.getChildren());
+                    }
+                }
+            }
+            // render list
+            if (log.isDebugEnabled())
+                HtmlNavigationMenuRendererUtils.debugTree(log, facesContext, panelNav.getChildren(), 0);
+            renderListLayout(facesContext, panelNav);
+        }
+        else {
+            renderTableLayout(facesContext, panelNav);
+        }
+    }
+
+    private void restoreOpenActiveStates(FacesContext facesContext,
+                                         HtmlPanelNavigationMenu panelNav, List children) {
+        for (int i = 0, size = children.size(); i < size; i++) {
+            UIComponent uiComponent = (UIComponent) children.get(i);
+            if (uiComponent instanceof HtmlCommandNavigationItem) {
+                HtmlCommandNavigationItem prevItem = (HtmlCommandNavigationItem) uiComponent;
+                if (prevItem.isOpen() || prevItem.isActive()) {
+                    HtmlCommandNavigationItem item = (HtmlCommandNavigationItem) panelNav.findComponent(uiComponent.getClientId(facesContext));
+                    if (item != null) {
+                        if (item.getActiveDirectly() != null && item.getActiveDirectly().booleanValue()) {
+                            item.setActive(prevItem.isActive());
+                        }
+                        else {
+                            copyValueBinding(prevItem, item, "active");
+                        }
+
+                        if (item.getOpenDirectly() != null && item.getOpenDirectly().booleanValue()) {
+                            item.setOpen(prevItem.isOpen());
+                        }
+                        else {
+                            copyValueBinding(prevItem, item, "open");
+                        }
+                        if (!panelNav.isExpandAll() || prevItem.isActive())
+                            item.toggleOpen();
+                        if (prevItem.isOpen())
+                            restoreOpenActiveStates(facesContext, panelNav, prevItem.getChildren());
+                    }
+                }
+            }
+        }
+    }
+
+    private HtmlPanelNavigationMenu findPreviousPanelNav(FacesContext facesContext, HtmlPanelNavigationMenu panelNav) {
+        UIViewRoot previousViewRoot = findPreviousRoot(facesContext);
+        if (previousViewRoot != null) {
+            return (HtmlPanelNavigationMenu) previousViewRoot.findComponent(panelNav.getClientId(facesContext));
+        }
+        return null;
+    }
+
+    private UIViewRoot findPreviousRoot(FacesContext facesContext) {
+        return (UIViewRoot) facesContext.getExternalContext().getRequestMap().get(HtmlPanelNavigationMenu.PREVIOUS_VIEW_ROOT);
+    }
+
+    protected void renderListLayout(FacesContext facesContext, HtmlPanelNavigationMenu panelNav) throws IOException {
+        //if (panelNav.isRenderAll())
+        //    addResourcesToHeader(facesContext);
+
+        ResponseWriter writer = facesContext.getResponseWriter();
+        if (panelNav.getChildCount() > 0) {
+            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+            writer.startElement(HTML.UL_ELEM, panelNav);
+
+            HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.UL_PASSTHROUGH_ATTRIBUTES);
+
+            //iterate over the tree and toggleOpen if viewId in item.getActiveOnVieIds()
+            activeOnViewId(panelNav, facesContext.getViewRoot().getViewId());
+            //iterate over the tree and set every item open if expandAll
+            if (panelNav.isExpandAll()) {
+                expandAll(panelNav);
+            }
+
+            HtmlNavigationMenuRendererUtils.renderChildrenListLayout(facesContext, writer, panelNav, panelNav.getChildren(), 0);
+
+            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+            writer.endElement(HTML.UL_ELEM);
+        }
+        else {
+            if (log.isWarnEnabled()) log.warn("PanelNavaigationMenu without children.");
+        }
+    }
+
+    private void renderTableLayout(FacesContext facesContext, HtmlPanelNavigationMenu panelNav) throws IOException {
+        ResponseWriter writer = facesContext.getResponseWriter();
+
+        if (panelNav.getChildCount() > 0) {
+            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+            writer.startElement(HTML.TABLE_ELEM, panelNav);
+            HtmlRendererUtils.renderHTMLAttributes(writer, panelNav, HTML.TABLE_PASSTHROUGH_ATTRIBUTES);
+            if (panelNav.getStyle() == null && panelNav.getStyleClass() == null) {
+                writer.writeAttribute(HTML.BORDER_ATTR, ZERO_INTEGER, null);
+            }
+
+            HtmlNavigationMenuRendererUtils.renderChildrenTableLayout(facesContext, writer, panelNav, panelNav.getChildren(), 0);
+
+            HtmlRendererUtils.writePrettyLineSeparator(facesContext);
+            writer.endElement(HTML.TABLE_ELEM);
+        }
+        else {
+            if (log.isWarnEnabled()) log.warn("PanelNavaigationMenu without children.");
+        }
+    }
+
+    private void addResourcesToHeader(FacesContext context) {
+        //AddResource addResource = AddResourceFactory.getInstance(context);
+        //addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, HtmlPanelNavigationMenu.class, HORIZ_MENU_SCRIPT);
+        TomahawkResourceUtils.addOutputScriptResource(context,
+                "oam.custom.navmenu.htmlnavmenu", HORIZ_MENU_SCRIPT);
+    }
+
+    /**
+     * look for UINavigationMenuItem && UISelectItems & create components
+     */
+    private void preprocessNavigationItems(FacesContext facesContext, UIComponent parent,
+                                           List children, UniqueId uniqueId) {
+        for (int i = 0; i < children.size(); i++) {
+            UIComponent child = (UIComponent) children.get(i);
+
+            if (child instanceof HtmlCommandNavigationItem) {
+                HtmlCommandNavigationItem navMenuItem = (HtmlCommandNavigationItem) child;
+                preprocessNavigationItems(facesContext, navMenuItem, navMenuItem.getChildren(), uniqueId);
+            }
+            else if (child instanceof UINavigationMenuItem) {
+                UINavigationMenuItem uiNavMenuItem = (UINavigationMenuItem) child;
+                createHtmlCommandNavigationItem(facesContext, parent, i, uiNavMenuItem, uniqueId);
+            }
+            else if (child instanceof UISelectItems) {
+                List list = new ArrayList();
+                if (child.getId() == null) {
+                    child.setId("testit");
+                }
+                NavigationMenuUtils.addNavigationMenuItems((UISelectItems) child, list);
+                addUINavigationMenuItems(facesContext, parent, children, i + 1, list);
+            }
+        }
+    }
+
+    private void addUINavigationMenuItems(FacesContext facesContext, UIComponent parent, List children, int startIndex, List menuItems) {
+        String clientId = parent.getClientId(facesContext);
+        clientId = clientId.replaceAll(":", "_");
+        for (int j = 0, sizej = menuItems.size(); j < sizej; j++) {
+            NavigationMenuItem navigationMenuItem = (NavigationMenuItem) menuItems.get(j);
+            UINavigationMenuItem uiNavigationMenuItem =
+                (UINavigationMenuItem) facesContext.getApplication().createComponent(UINavigationMenuItem.COMPONENT_TYPE);
+            uiNavigationMenuItem.setId(clientId + "_uinavmitem" + (startIndex + j));
+            uiNavigationMenuItem.getClientId(facesContext); // create clientid
+            children.add(startIndex++, uiNavigationMenuItem);
+            uiNavigationMenuItem.setParent(parent);
+            if (navigationMenuItem.getAction() != null) {
+                uiNavigationMenuItem.setAction(HtmlNavigationMenuRendererUtils.getMethodBinding(facesContext, navigationMenuItem.getAction(), false));
+            }
+            if (navigationMenuItem.getActionListener() != null) {
+                uiNavigationMenuItem.setActionListener(HtmlNavigationMenuRendererUtils.getMethodBinding(facesContext,
+                                                                                                        navigationMenuItem.getActionListener(), true));
+            }
+            uiNavigationMenuItem.setIcon(navigationMenuItem.getIcon());
+            uiNavigationMenuItem.setRendered(navigationMenuItem.isRendered());
+            uiNavigationMenuItem.setActiveOnViewIds(navigationMenuItem.getActiveOnViewIds());
+            uiNavigationMenuItem.setSplit(navigationMenuItem.isSplit());
+            uiNavigationMenuItem.setItemLabel(navigationMenuItem.getLabel());
+            uiNavigationMenuItem.setOpen(navigationMenuItem.isOpen());
+            uiNavigationMenuItem.setActive(navigationMenuItem.isActive());
+            uiNavigationMenuItem.setValue(navigationMenuItem.getValue());
+            HtmlNavigationMenuRendererUtils.setAttributeValue(facesContext, uiNavigationMenuItem,
+                                                              "externalLink", navigationMenuItem.getExternalLink());
+            //uiNavigationMenuItem.setExternalLink(navigationMenuItem.getExternalLink());
+            uiNavigationMenuItem.setTransient(false);
+            uiNavigationMenuItem.setTarget(navigationMenuItem.getTarget());
+            uiNavigationMenuItem.setDisabled(navigationMenuItem.isDisabled());
+            uiNavigationMenuItem.setDisabledStyle(navigationMenuItem.getDisabledStyle());
+            uiNavigationMenuItem.setDisabledStyleClass(navigationMenuItem.getDisabledStyleClass());
+
+            if (navigationMenuItem.getNavigationMenuItems() != null && navigationMenuItem.getNavigationMenuItems().length > 0)
+            {
+                addUINavigationMenuItems(facesContext, uiNavigationMenuItem, uiNavigationMenuItem.getChildren(), 0,
+                                         Arrays.asList(navigationMenuItem.getNavigationMenuItems()));
+            }
+        }
+    }
+
+    private HtmlPanelNavigationMenu getParentPanelNavigation(UIComponent uiComponent) {
+        if (uiComponent instanceof HtmlPanelNavigationMenu) {
+            return (HtmlPanelNavigationMenu) uiComponent;
+        }
+        UIComponent parent = uiComponent.getParent();
+
+        // search HtmlPanelNavigation
+        UIComponent p = parent;
+        while (p != null && !(p instanceof HtmlPanelNavigationMenu)) {
+            p = p.getParent();
+        }
+        // p is now the HtmlPanelNavigation
+        if (p == null) {
+            log.error("HtmlCommandNavigation without parent HtmlPanelNavigation ?!");
+            return null;
+        }
+        return (HtmlPanelNavigationMenu) p;
+    }
+
+    private void createHtmlCommandNavigationItem(FacesContext facesContext, UIComponent parent, int i,
+                                                 UINavigationMenuItem uiNavMenuItem, UniqueId uniqueId) {
+        HtmlPanelNavigationMenu menu = getParentPanelNavigation(parent);
+        // Create HtmlCommandNavigationItem
+        HtmlCommandNavigationItem newItem = (HtmlCommandNavigationItem)
+            facesContext.getApplication().createComponent(HtmlCommandNavigationItem.COMPONENT_TYPE);
+        String parentId = parent.getClientId(facesContext);
+        parentId = parentId.replaceAll(":", "_");
+        int id = uniqueId.next();
+        newItem.setId(parentId + "_item" + id);
+        newItem.getClientId(facesContext); // create clientid
+        newItem.setRendererType(RENDERER_TYPE);
+        parent.getChildren().add(i + 1, newItem);
+        newItem.setParent(parent);
+        // set action & actionListner
+        newItem.setAction(uiNavMenuItem.getAction());
+        newItem.setActionListener(uiNavMenuItem.getActionListener());
+        ActionListener[] listeners = uiNavMenuItem.getActionListeners();
+        for (int j = 0; j < listeners.length; j++) {
+            newItem.addActionListener(listeners[j]);
+        }
+        // value
+        newItem.setValue(uiNavMenuItem.getValue());
+        // immeditate
+        if (!copyValueBinding(uiNavMenuItem, newItem, "immediate"))
+            newItem.setImmediate(uiNavMenuItem.isImmediate());
+        // transient, rendered
+        if (!copyValueBinding(uiNavMenuItem, newItem, "transient"))
+            newItem.setTransient(uiNavMenuItem.isTransient());
+        if (!copyValueBinding(uiNavMenuItem, newItem, "rendered"))
+            newItem.setRendered(uiNavMenuItem.isRendered());
+        if (!copyValueBinding(uiNavMenuItem, newItem, "externalLink"))
+            newItem.setExternalLink(uiNavMenuItem.getExternalLink());
+        if (!copyValueBinding(uiNavMenuItem, newItem, "activeOnViewIds"))
+            newItem.setActiveOnViewIds(uiNavMenuItem.getActiveOnViewIds());
+
+        if (uiNavMenuItem.isOpen() && ! menu.isExpandAll())
+            newItem.toggleOpen();
+
+        if (uiNavMenuItem.getActiveDirectly() != null) {
+            newItem.setActive(uiNavMenuItem.isActive());
+        }
+        else {
+            newItem.setValueBinding("active", uiNavMenuItem.getValueBinding("active"));
+        }
+
+        if (!copyValueBinding(uiNavMenuItem, newItem, "target"))
+            newItem.setTarget(uiNavMenuItem.getTarget());
+        if (!copyValueBinding(uiNavMenuItem, newItem, "disabled"))
+            newItem.setDisabled(uiNavMenuItem.isDisabled());
+        if (!copyValueBinding(uiNavMenuItem, newItem, "disabledStyle"))
+            newItem.setDisabledStyle(uiNavMenuItem.getDisabledStyle());
+        if (!copyValueBinding(uiNavMenuItem, newItem, "disabledStyleClass"))
+            newItem.setDisabledStyleClass(uiNavMenuItem.getDisabledStyleClass());
+
+        if (uiNavMenuItem.getActiveOnViewIdsDirectly() != null) {
+            newItem.setActiveOnViewIds(uiNavMenuItem.getActiveOnViewIdsDirectly());
+        }
+
+        // If the parent-Element is disabled the child is disabled as well
+        if (parent instanceof HtmlPanelNavigationMenu) {
+            if (newItem.getDisabledStyle() == null) {
+                newItem.setDisabledStyle(
+                    ((HtmlPanelNavigationMenu) parent).getDisabledStyle()
+                );
+            }
+            if (newItem.getDisabledStyleClass() == null) {
+                newItem.setDisabledStyleClass(
+                    ((HtmlPanelNavigationMenu) parent).getDisabledStyleClass()
+                );
+            }
+            if (((HtmlPanelNavigationMenu) parent).isDisabled()) {
+                newItem.setDisabled(true);
+            }
+        }
+        if (parent instanceof HtmlCommandNavigationItem) {
+            if (newItem.getDisabledStyle() == null) {
+                newItem.setDisabledStyle(
+                    ((HtmlCommandNavigationItem) parent).getDisabledStyle()
+                );
+            }
+            if (newItem.getDisabledStyleClass() == null) {
+                newItem.setDisabledStyleClass(
+                    ((HtmlCommandNavigationItem) parent).getDisabledStyleClass()
+                );
+            }
+            if (((HtmlCommandNavigationItem) parent).isDisabled()) {
+                newItem.setDisabled(true);
+            }
+        }
+
+        if (uiNavMenuItem.getIcon() != null) {
+            UIGraphic uiGraphic = (UIGraphic) facesContext.getApplication().createComponent(UIGraphic.COMPONENT_TYPE);
+            uiGraphic.setId(parentId + "_img" + id);
+            uiGraphic.getClientId(facesContext);
+            newItem.getChildren().add(uiGraphic);
+            uiGraphic.setParent(newItem);
+            if (NavigationMenuUtils.isValueReference(uiNavMenuItem.getIcon())) {
+                uiGraphic.setValueBinding("value",
+                                          facesContext.getApplication().createValueBinding(uiNavMenuItem.getIcon()));
+            }
+            else {
+                uiGraphic.setValue(uiNavMenuItem.getIcon());
+            }
+        }
+
+        else {
+            // Create and add UIOutput
+            UIOutput uiOutput = (UIOutput) facesContext.getApplication().createComponent(UIOutput.COMPONENT_TYPE);
+            uiOutput.setId(parentId + "_txt" + id);
+            uiOutput.getClientId(facesContext); // create clientid
+            newItem.getChildren().add(uiOutput);
+            uiOutput.setParent(newItem);
+            if (uiNavMenuItem.getItemLabel() != null) {
+                if (NavigationMenuUtils.isValueReference(uiNavMenuItem.getItemLabel())) {
+                    uiOutput.setValueBinding("value",
+                                             facesContext.getApplication().createValueBinding(uiNavMenuItem.getItemLabel()));
+                }
+                else {
+                    uiOutput.setValue(uiNavMenuItem.getItemLabel());
+                }
+            }
+            else {
+                Object value = uiNavMenuItem.getValue();
+                if (value != null &&
+                    NavigationMenuUtils.isValueReference(value.toString())) {
+                    uiOutput.setValueBinding("value",
+                                             facesContext.getApplication().createValueBinding(value.toString()));
+                }
+                else {
+                    uiOutput.setValue(uiNavMenuItem.getValue());
+                }
+            }
+        }
+        // process next level
+        log.debug("Instance of UINavigationMenuItem, preprocess childrens");
+        preprocessNavigationItems(facesContext, newItem, uiNavMenuItem.getChildren(), uniqueId);
+    }
+
+    private boolean copyValueBinding(UIComponent source, UIComponent target, String binding) {
+        ValueBinding valueBinding = source.getValueBinding(binding);
+        if (valueBinding == null)
+            return false;
+        target.setValueBinding(binding, valueBinding);
+        return true;
+    }
+
+// protected
+
+    protected String getStyle(FacesContext facesContext, UIComponent link) {
+        if (!(link instanceof HtmlCommandNavigationItem)) {
+            throw new IllegalArgumentException("expected instance of " + HtmlCommandNavigationItem.class.getName());
+        }
+
+        UIComponent navPanel = HtmlNavigationMenuRendererUtils.getPanel(link);
+
+        HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) link;
+        if (navItem.isActive()) {
+            return ((HtmlPanelNavigationMenu) navPanel).getActiveItemStyle();
+        }
+        else if (navItem.isOpen()) {
+            return ((HtmlPanelNavigationMenu) navPanel).getOpenItemStyle();
+        }
+        else {
+            return ((HtmlPanelNavigationMenu) navPanel).getItemStyle();
+        }
+    }
+
+    protected String getStyleClass(FacesContext facesContext, UIComponent link) {
+        if (!(link instanceof HtmlCommandNavigationItem)) {
+            throw new IllegalArgumentException();
+        }
+
+        UIComponent navPanel = HtmlNavigationMenuRendererUtils.getPanel(link);
+
+        HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) link;
+        if (navItem.isActive()) {
+            return ((HtmlPanelNavigationMenu) navPanel).getActiveItemClass();
+        }
+        else if (navItem.isOpen()) {
+            return ((HtmlPanelNavigationMenu) navPanel).getOpenItemClass();
+        }
+        else {
+            return ((HtmlPanelNavigationMenu) navPanel).getItemClass();
+        }
+    }
+
+    private static class UniqueId {
+        private int _id;
+
+        public int next() {
+            return _id++;
+        }
+
+        public void decrease() {
+            _id--;
+        }
+    }
+
+    private void expandAll(UIComponent parent) {
+        //Recurse over all Children setOpen if child is HtmlCommandNavigationItem
+        if (parent instanceof HtmlCommandNavigationItem) {
+            HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) parent;
+            navItem.setOpen(true);
+        }
+        List children = parent.getChildren();
+        UIComponent child;
+        for (int i = 0; i < children.size(); i++) {
+            child = (UIComponent) children.get(i);
+            expandAll(child);
+        }
+    }
+
+    private void activeOnViewId(UIComponent parent, String viewId) {
+        //Recurse over all Children setOpen if child is HtmlCommandNavigationItem
+        if (parent instanceof HtmlCommandNavigationItem) {
+            HtmlCommandNavigationItem navItem = (HtmlCommandNavigationItem) parent;
+            String[] viewIds = navItem.getActiveOnVieIds();
+            for (int i = 0; i < viewIds.length; i++) {
+                if (viewId.equals(viewIds[i])) {
+                    navItem.toggleOpen();
+                    navItem.setActive(true);
+                    return;
+                }
+            }
+            ;
+        }
+        List children = parent.getChildren();
+        UIComponent child;
+        for (int i = 0; i < children.size(); i++) {
+            child = (UIComponent) children.get(i);
+            activeOnViewId(child, viewId);
+        }
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/navmenu/jscookmenu/HtmlJSCookMenuRenderer.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/navmenu/jscookmenu/HtmlJSCookMenuRenderer.java?rev=928556&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/navmenu/jscookmenu/HtmlJSCookMenuRenderer.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/navmenu/jscookmenu/HtmlJSCookMenuRenderer.java Mon Mar 29 01:18:21 2010
@@ -0,0 +1,573 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.navmenu.jscookmenu;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.faces.FacesException;
+import javax.faces.application.Resource;
+import javax.faces.application.ResourceHandler;
+import javax.faces.component.UIComponent;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.el.MethodBinding;
+import javax.faces.el.ValueBinding;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.custom.navmenu.NavigationMenuItem;
+import org.apache.myfaces.custom.navmenu.NavigationMenuUtils;
+import org.apache.myfaces.custom.navmenu.UINavigationMenuItem;
+import org.apache.myfaces.renderkit.html.util.AddResource;
+import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
+import org.apache.myfaces.shared_tomahawk.el.SimpleActionMethodBinding;
+import org.apache.myfaces.shared_tomahawk.renderkit.JSFAttr;
+import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlFormRendererBase;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRenderer;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.util.FormInfo;
+import org.apache.myfaces.shared_tomahawk.renderkit.html.util.JavascriptUtils;
+import org.apache.myfaces.tomahawk.application.PreRenderViewAddResourceEvent;
+import org.apache.myfaces.tomahawk.util.TomahawkResourceUtils;
+
+/**
+ * @JSFRenderer
+ *   renderKitId = "HTML_BASIC" 
+ *   family = "javax.faces.Command"
+ *   type = "org.apache.myfaces.JSCookMenu"
+ * 
+ * @author Thomas Spiegl
+ * @version $Revision: 698742 $ $Date: 2008-09-24 16:25:46 -0500 (mié, 24 sep 2008) $
+ */
+@ListenerFor(systemEventClass=PreRenderViewAddResourceEvent.class)
+public class HtmlJSCookMenuRenderer
+    extends HtmlRenderer implements ComponentSystemEventListener
+{
+    private static final String MYFACES_HACK_SCRIPT = "MyFacesHack.js";
+
+    private static final String JSCOOK_MENU_SCRIPT = "JSCookMenu.js";
+    
+    private static final String JSCOOK_EFFECT_SCRIPT = "effect.js";    
+
+    private static final Log log = LogFactory.getLog(HtmlJSCookMenuRenderer.class);
+
+    private static final String JSCOOK_ACTION_PARAM = "jscook_action";
+    private static final Class[] ACTION_LISTENER_ARGS = {ActionEvent.class};
+
+    private static final Map builtInThemes = new java.util.HashMap();
+
+    static {
+        builtInThemes.put("ThemeOffice", "ThemeOffice/");
+        builtInThemes.put("ThemeMiniBlack", "ThemeMiniBlack/");
+        builtInThemes.put("ThemeIE", "ThemeIE/");
+        builtInThemes.put("ThemePanel", "ThemePanel/");
+        builtInThemes.put("ThemeGray", "ThemeGray/");        
+    }
+
+    public void processEvent(ComponentSystemEvent event)
+    {
+        HtmlCommandJSCookMenu menu = (HtmlCommandJSCookMenu) event.getComponent();
+        String theme = menu.getTheme();
+        if (theme == null) {
+            // should never happen; theme is a required attribute in the jsp tag definition
+            throw new IllegalArgumentException("theme name is mandatory for a jscookmenu.");
+        }
+
+        addResourcesToHeader(theme, menu, FacesContext.getCurrentInstance());
+    }
+
+    public void decode(FacesContext context, UIComponent component) {
+        RendererUtils.checkParamValidity(context, component, HtmlCommandJSCookMenu.class);
+
+        Map parameter = context.getExternalContext().getRequestParameterMap();
+        String actionParam = (String) parameter.get(JSCOOK_ACTION_PARAM);
+        if (actionParam != null && !actionParam.trim().equals("") &&
+            !actionParam.trim().equals("null")) {
+            String compId = getMenuId(context, component);
+            StringTokenizer tokenizer = new StringTokenizer(actionParam, ":");
+            if (tokenizer.countTokens() > 1) {
+                String actionId = tokenizer.nextToken();
+                if (! compId.equals(actionId)) {
+                    return;
+                }
+                while (tokenizer.hasMoreTokens()) {
+                    String action = tokenizer.nextToken();
+                    if (action.startsWith("A]")) {
+                        action = action.substring(2, action.length());
+                        action = decodeValueBinding(action, context);
+                        MethodBinding mb;
+                        if (NavigationMenuUtils.isValueReference(action)) {
+                            mb = context.getApplication().createMethodBinding(action, null);
+                        }
+                        else {
+                            mb = new SimpleActionMethodBinding(action);
+                        }
+                        ((HtmlCommandJSCookMenu) component).setAction(mb);
+                    }
+                    else if (action.startsWith("L]")) {
+                        action = action.substring(2, action.length());
+                        String value = null;
+                        int idx = action.indexOf(";");
+                        if (idx > 0 && idx < action.length() - 1) {
+                            value = action.substring(idx + 1, action.length());
+                            action = action.substring(0, idx);
+                            ((HtmlCommandJSCookMenu) component).setValue(value);
+                        }
+                        else if (idx == action.length() - 1)
+                        {
+                            value = null; //No Value found, so set it to null as expected
+                            action = action.substring(0, idx);
+                        }
+                        MethodBinding mb;
+                        if (NavigationMenuUtils.isValueReference(action)) {
+                            mb = context.getApplication().createMethodBinding(action, ACTION_LISTENER_ARGS);
+                            ((HtmlCommandJSCookMenu) component).setActionListener(mb);
+                            if (value != null)
+                                ((HtmlCommandJSCookMenu) component).setValue(value);
+                        }
+                    }
+                }
+            }
+            component.queueEvent(new ActionEvent(component));
+        }
+    }
+
+    private String decodeValueBinding(String actionParam, FacesContext context) {
+        int idx = actionParam.indexOf(";#{");
+        if (idx == -1) {
+            return actionParam;
+        }
+
+        String newActionParam = actionParam.substring(0, idx);
+        String vbParam = actionParam.substring(idx + 1);
+
+        idx = vbParam.indexOf('=');
+        if (idx == -1) {
+            return newActionParam;
+        }
+        String vbExpressionString = vbParam.substring(0, idx);
+        String vbValue = vbParam.substring(idx + 1);
+
+        ValueBinding vb =
+            context.getApplication().createValueBinding(vbExpressionString);
+        vb.setValue(context, vbValue);
+
+        return newActionParam;
+    }
+
+    public boolean getRendersChildren() {
+        return true;
+    }
+
+    public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
+        RendererUtils.checkParamValidity(context, component, HtmlCommandJSCookMenu.class);
+
+        List list = NavigationMenuUtils.getNavigationMenuItemList(component);
+        if (list.size() > 0) {
+            FormInfo parentFormInfo = RendererUtils.findNestingForm(component, context);
+            ResponseWriter writer = context.getResponseWriter();
+
+            if (parentFormInfo == null)
+                throw new FacesException("jscook menu is not embedded in a form.");
+            String formName = parentFormInfo.getFormName();
+            List uiNavMenuItemList = component.getChildren();
+            /* todo: disabled for now. Check if dummy form stuff is still needed/desired
+                if( formName == null ) {
+                DummyFormUtils.setWriteDummyForm(context,true);
+                DummyFormUtils.addDummyFormParameter(context,JSCOOK_ACTION_PARAM);
+
+                formName = DummyFormUtils.getDummyFormName();
+            }
+            else {*/
+            if (RendererUtils.isAdfOrTrinidadForm(parentFormInfo.getForm())) {
+                // need to add hidden input, cause MyFaces form is missing hence will not render hidden inputs
+                writer.write("<input type=\"hidden\" name=\"");
+                writer.write(JSCOOK_ACTION_PARAM);
+                writer.write("\" />");
+            }
+            else {
+                HtmlFormRendererBase.addHiddenCommandParameter(context, parentFormInfo.getForm(), JSCOOK_ACTION_PARAM);
+            }
+
+            //}
+
+            String myId = getMenuId(context, component);
+
+            writer.startElement(HTML.SCRIPT_ELEM, component);
+            writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
+            StringBuffer script = new StringBuffer();
+            script.append("var ").append(getMenuId(context, component)).append(" =\n[");
+            encodeNavigationMenuItems(context, script,
+                                      (NavigationMenuItem[]) list.toArray(new NavigationMenuItem[list.size()]),
+                                      uiNavMenuItemList,
+                                      myId, formName);
+
+            script.append("];");
+            writer.writeText(script.toString(), null);
+            writer.endElement(HTML.SCRIPT_ELEM);
+        }
+    }
+
+    private void encodeNavigationMenuItems(FacesContext context,
+                                           StringBuffer writer,
+                                           NavigationMenuItem[] items,
+                                           List uiNavMenuItemList,
+                                           String menuId, String formName)
+        throws IOException {
+        for (int i = 0; i < items.length; i++) {
+            NavigationMenuItem item = items[i];
+            Object tempObj = null;
+            UINavigationMenuItem uiNavMenuItem = null;
+            if (i < uiNavMenuItemList.size()) {
+                tempObj = uiNavMenuItemList.get(i);
+            }
+            if (tempObj != null) {
+                if (tempObj instanceof UINavigationMenuItem) {
+                    uiNavMenuItem = (UINavigationMenuItem) tempObj;
+                }
+            }
+
+            if (! item.isRendered()) {
+                continue;
+            }
+
+            if (i > 0) {
+                writer.append(",\n");
+            }
+
+            if (item.isSplit()) {
+                writer.append("_cmSplit,");
+
+                if (item.getLabel().equals("0")) {
+                    continue;
+                }
+            }
+
+            writer.append("[");
+            if (item.getIcon() != null) {
+                String iconSrc = context.getApplication().getViewHandler().getResourceURL(context, item.getIcon());
+                writer.append("'<img src=\"");
+                writer.append(context.getExternalContext().encodeResourceURL(iconSrc));
+                writer.append("\"/>'");
+            }
+            else {
+                writer.append("null");
+            }
+            writer.append(", '");
+            if (item.getLabel() != null) {
+                writer.append(getString(context, item.getLabel()));
+            }
+            writer.append("', ");
+            StringBuffer actionStr = new StringBuffer();
+            if ((item.getAction() != null || item.getActionListener() != null) && ! item.isDisabled()) {
+                actionStr.append("'");
+                actionStr.append(menuId);
+                if (item.getActionListener() != null) {
+                    actionStr.append(":L]");
+                    actionStr.append(item.getActionListener());
+                    if (uiNavMenuItem != null && uiNavMenuItem.getItemValue() != null) {
+                        actionStr.append(';');
+                        actionStr.append(getString(context, uiNavMenuItem.getItemValue()));
+                    }
+                    else if (item.getValue() != null) {
+                        actionStr.append(';');
+                        actionStr.append(getString(context, item.getValue()));
+                    }
+                }
+                if (item.getAction() != null) {
+                    actionStr.append(":A]");
+                    actionStr.append(item.getAction());
+                    if (uiNavMenuItem != null) {
+                        encodeValueBinding(actionStr, uiNavMenuItem, item);
+                    }
+                }
+                actionStr.append("'");
+                writer.append(actionStr.toString());
+            }
+            else {
+                writer.append("null");
+            }
+            writer.append(", '");
+            // Change here to allow the use of non dummy form.
+            writer.append(formName);
+            writer.append("', null");
+
+            if (item.isRendered() && ! item.isDisabled()) {
+                // render children only if parent is visible/enabled
+                NavigationMenuItem[] menuItems = item.getNavigationMenuItems();
+                if (menuItems != null && menuItems.length > 0) {
+                    writer.append(",");
+                    if (uiNavMenuItem != null) {
+                        encodeNavigationMenuItems(context, writer, menuItems,
+                                                  uiNavMenuItem.getChildren(), menuId, formName);
+                    }
+                    else {
+                        encodeNavigationMenuItems(context, writer, menuItems,
+                                                  new ArrayList(1), menuId, formName);
+                    }
+                }
+            }
+            writer.append("]");
+        }
+    }
+
+    private String getString(FacesContext facesContext, Object value) {
+        String str = "";
+
+        if (value != null) {
+            str = value.toString();
+        }
+
+        if (NavigationMenuUtils.isValueReference(str)) {
+            value = facesContext.getApplication().createValueBinding(str).getValue(facesContext);
+
+            if (value != null) {
+                str = value.toString();
+            }
+            else {
+                str = "";
+            }
+        }
+
+        return JavascriptUtils.encodeString(str);
+    }
+
+    private void encodeValueBinding(StringBuffer writer, UINavigationMenuItem uiNavMenuItem,
+                                    NavigationMenuItem item) {
+        ValueBinding vb = uiNavMenuItem.getValueBinding("NavMenuItemValue");
+        if (vb == null) {
+            return;
+        }
+        String vbExpression = vb.getExpressionString();
+        if (vbExpression == null) {
+            return;
+        }
+        Object tempObj = item.getValue();
+        if (tempObj == null) {
+            return;
+        }
+
+        writer.append(";");
+        writer.append(vbExpression);
+        writer.append("=");
+        writer.append(tempObj.toString());
+    }
+
+    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
+        /*
+        HtmlCommandJSCookMenu menu = (HtmlCommandJSCookMenu) component;
+        String theme = menu.getTheme();
+        if (theme == null) {
+            // should never happen; theme is a required attribute in the jsp tag definition
+            throw new IllegalArgumentException("theme name is mandatory for a jscookmenu.");
+        }
+
+        addResourcesToHeader(theme, menu, context);
+        */
+    }
+
+    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
+        RendererUtils.checkParamValidity(context, component, HtmlCommandJSCookMenu.class);
+        HtmlCommandJSCookMenu menu = (HtmlCommandJSCookMenu) component;
+        String theme = menu.getTheme();
+
+
+        ResponseWriter writer = context.getResponseWriter();
+
+        String menuId = getMenuId(context, component);
+
+        writer.write("<div id=\"");
+        writer.write(menuId);
+        writer.write("\"></div>\n");
+        writer.startElement(HTML.SCRIPT_ELEM, menu);
+        writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
+
+        StringBuffer buf = new StringBuffer();
+        buf.append("\tif(window.cmDraw!=undefined) { cmDraw ('").
+            append(menuId).
+            append("', ").
+            append(menuId).
+            append(", '").
+            append(menu.getLayout()).
+            append("', cm").
+            append(theme).
+            append(", '").
+            append(theme).
+            append("');}");
+
+        writer.writeText(buf.toString(), null);
+        writer.endElement(HTML.SCRIPT_ELEM);
+    }
+
+    private void addResourcesToHeader(String themeName, HtmlCommandJSCookMenu menu, FacesContext context) {
+        String javascriptLocation = (String) menu.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION);
+        String imageLocation = (String) menu.getAttributes().get(JSFAttr.IMAGE_LOCATION);
+        String styleLocation = (String) menu.getAttributes().get(JSFAttr.STYLE_LOCATION);
+
+        AddResource addResource = AddResourceFactory.getInstance(context);
+
+        if (javascriptLocation != null) {
+            addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/" + JSCOOK_MENU_SCRIPT);
+            addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/" + JSCOOK_EFFECT_SCRIPT);            
+            addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/" + MYFACES_HACK_SCRIPT);
+        }
+        else {
+            //addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, HtmlJSCookMenuRenderer.class, JSCOOK_MENU_SCRIPT);
+            TomahawkResourceUtils.addOutputScriptResource(context, "oam.custom.navmenu.jscookmenu", JSCOOK_MENU_SCRIPT);
+            //addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, HtmlJSCookMenuRenderer.class, JSCOOK_EFFECT_SCRIPT);
+            TomahawkResourceUtils.addOutputScriptResource(context, "oam.custom.navmenu.jscookmenu", JSCOOK_EFFECT_SCRIPT);
+            //addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, HtmlJSCookMenuRenderer.class, MYFACES_HACK_SCRIPT);
+            TomahawkResourceUtils.addOutputScriptResource(context, "oam.custom.navmenu.jscookmenu", MYFACES_HACK_SCRIPT);
+        }
+
+        addThemeSpecificResources(themeName, styleLocation, javascriptLocation, imageLocation, context);
+    }
+
+    /**
+     * A theme for a menu requires a number of external files; this method
+     * outputs those into the page head section.
+     *
+     * @param themeName          is the name of the theme for this menu. It is never
+     *                           null. It may match one of the built-in theme names or may be a custom
+     *                           theme defined by the application.
+     * @param styleLocation      is the URL of a directory containing a
+     *                           "theme.css" file. A stylesheet link tag will be inserted into
+     *                           the page header referencing that file. If null then if the
+     *                           themeName is a built-in one then a reference to the appropriate
+     *                           built-in stylesheet is generated (requires the ExtensionsFilter).
+     *                           If null and a custom theme is used then no stylesheet link will be
+     *                           generated here.
+     * @param javascriptLocation is the URL of a directory containing a
+     *                           "theme.js" file. A script tag will be inserted into the page header
+     *                           referencing that file. If null then if the themeName is a built-in
+     *                           one then a reference to the built-in stylesheet is generated (requires
+     *                           the ExtensionsFilter). If null and a custom theme is used then no
+     *                           stylesheet link will be generated here.
+     * @param imageLocation      is the URL of a directory containing files
+     *                           (esp. image files) used by the theme.js file to define the menu
+     *                           theme. A javascript variable of name "my{themeName}Base" is
+     *                           generated in the page header containing this URL, so that the
+     *                           theme.js script can locate the files. If null then if the themeName
+     *                           is a built-in one then the URL to the appropriate resource directory
+     *                           is generated (requires the ExtensionsFilter). If null and a custom
+     *                           theme is used then no javascript variable will be generated here.
+     * @param context            is the current faces context.
+     */
+    private void addThemeSpecificResources(String themeName, String styleLocation,
+                                           String javascriptLocation, String imageLocation, FacesContext context) {
+        String themeLocation = (String) builtInThemes.get(themeName);
+        if (themeLocation == null) {
+            log.debug("Unknown theme name '" + themeName + "' specified.");
+        }
+
+        AddResource addResource = AddResourceFactory.getInstance(context);
+
+        if ((imageLocation != null) || (themeLocation != null)) {
+            // Generate a javascript variable containing a reference to the
+            // directory containing theme image files, for use by the theme
+            // javascript file. If neither of these is defined (ie a custom
+            // theme was specified but no imageLocation) then presumably the
+            // theme.js file uses some other mechanism to determine where
+            // its image files are.
+            StringBuffer buf = new StringBuffer();
+            buf.append("var my");
+            buf.append(themeName);
+            buf.append("Base='");
+            ExternalContext externalContext = context.getExternalContext();
+            if (imageLocation != null) {
+                buf.append(externalContext.encodeResourceURL(addResource.getResourceUri(context,
+                                                                                        imageLocation + "/" + themeName)));
+            }
+            else {
+                //buf.append(externalContext.encodeResourceURL(addResource.getResourceUri(context,
+                //        HtmlJSCookMenuRenderer.class, themeLocation)));
+                Resource resource = context.getApplication().getResourceHandler().
+                    createResource(";j","oam.custom.navmenu.jscookmenu."+themeName);
+                buf.append(resource.getRequestPath());
+            }
+            buf.append("';");
+            addResource.addInlineScriptAtPosition(context, AddResource.HEADER_BEGIN, buf.toString());
+        }
+        else
+        {
+            
+        }
+
+
+        if ((javascriptLocation != null) || (themeLocation != null)) {
+            // Generate a <script> tag in the page header pointing to the
+            // theme.js file for this theme. If neither of these is defined
+            // then presumably the theme.js file is referenced by a <script>
+            // tag hard-wired into the page or inserted via some other means.
+            if (javascriptLocation != null) {
+                // For now, assume that if the user specified a location for a custom
+                // version of the jscookMenu.js file then the theme.js file can be found
+                // in the same location.
+                addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, javascriptLocation + "/" + themeName
+                    + "/theme.js");
+            }
+            else {
+                // Using a built-in theme, so we know where the theme.js file is.
+                //addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, HtmlJSCookMenuRenderer.class, themeName
+                //    + "/theme.js");
+                TomahawkResourceUtils.addOutputScriptResource(context, "oam.custom.navmenu.jscookmenu."+themeName, "theme.js");
+            }
+        }
+
+        if ((styleLocation != null) || (themeLocation != null)) {
+            // Generate a <link type="text/css"> tag in the page header pointing to
+            // the theme stylesheet. If neither of these is defined then presumably
+            // the stylesheet is referenced by a <link> tag hard-wired into the page
+            // or inserted via some other means.
+            if (styleLocation != null) {
+                addResource.addStyleSheet(context, AddResource.HEADER_BEGIN, styleLocation + "/" + themeName + "/theme.css");
+            }
+            else {
+                //addResource.addStyleSheet(context, AddResource.HEADER_BEGIN, HtmlJSCookMenuRenderer.class, themeName
+                //    + "/theme.css");
+                TomahawkResourceUtils.addOutputStylesheetResource(context, "oam.custom.navmenu.jscookmenu."+themeName, "theme.css");
+            }
+        }
+    }
+
+    /**
+     * Fetch the very last part of the menu id.
+     *
+     * @param context
+     * @param component
+     * @return String id of the menu
+     */
+    private String getMenuId(FacesContext context, UIComponent component) {
+        String menuId = component.getClientId(context).replaceAll(":", "_") + "_menu";
+        while (menuId.startsWith("_")) {
+            menuId = menuId.substring(1);
+        }
+        return menuId;
+    }
+}