org.apache.myfaces.custom.ajaxchildcombobox.HtmlAjaxChildComboBoxRenderer.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.myfaces.custom.ajaxchildcombobox.HtmlAjaxChildComboBoxRenderer.java

Source

/*
 * 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.ajaxchildcombobox;

import java.io.IOException;
import java.io.PrintWriter;

import javax.el.MethodExpression;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.model.SelectItem;
import javax.servlet.ServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.myfaces.custom.ajax.api.AjaxRenderer;
import org.apache.myfaces.custom.dojo.DojoConfig;
import org.apache.myfaces.custom.dojo.DojoUtils;
import org.apache.myfaces.renderkit.html.ext.HtmlMenuRenderer;
import org.apache.myfaces.renderkit.html.util.AddResource;
import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
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;

/**
 * Renderer for component HtmlAjaxChildComboBox
 * 
 * @JSFRenderer
 *   renderKitId = "HTML_BASIC" 
 *   family = "javax.faces.SelectOne"
 *   type = "org.apache.myfaces.AjaxChildComboBox"
 *
 * @author Sharath Reddy
 */
public class HtmlAjaxChildComboBoxRenderer extends HtmlMenuRenderer implements AjaxRenderer {
    private static final String BEGIN_OPTION = "<option>";
    private static final String END_OPTION = "</option>";
    private static final String BEGIN_OPTION_TEXT = "<optionText>";
    private static final String END_OPTION_TEXT = "</optionText>";
    private static final String BEGIN_OPTION_VALUE = "<optionValue>";
    private static final String END_OPTION_VALUE = "</optionValue>";

    public static final int DEFAULT_MAX_SUGGESTED_ITEMS = 200;

    private static Log log = LogFactory.getLog(HtmlAjaxChildComboBoxRenderer.class);

    // Adds the javascript files needed by Dojo and the custom javascript for
    // this
    // component
    private void encodeJavascript(FacesContext context, UIComponent component) throws IOException {
        String javascriptLocation = (String) component.getAttributes().get(JSFAttr.JAVASCRIPT_LOCATION);
        DojoUtils.addMainInclude(context, component, javascriptLocation, new DojoConfig());
        DojoUtils.addRequire(context, component, "dojo.event.*");
        // not required - and results in an error
        // DojoUtils.addRequire(context, component, "dojo.io.bind");

        AddResource addResource = AddResourceFactory.getInstance(context);

        addResource.addJavaScriptAtPosition(context, AddResource.HEADER_BEGIN, AjaxChildComboBox.class,
                "javascript/ajaxChildComboBox.js");
    }

    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        RendererUtils.checkParamValidity(context, component, AjaxChildComboBox.class);

        AjaxChildComboBox childComboBox = (AjaxChildComboBox) component;

        super.encodeEnd(context, component);

        String clientId = component.getClientId(context);

        UIComponent parentComboBox = this.getParentComboBox(childComboBox);
        if (parentComboBox == null) {
            log.error(
                    "Could not find parent combo box for AjaxChildComboBox " + childComboBox.getClientId(context));
            return;
        }

        encodeJavascript(context, component);

        ResponseWriter writer = context.getResponseWriter();

        // Begin: Write out the javascript that hooks up this component with the
        // parent combo-box
        writer.startElement(HTML.SCRIPT_ELEM, component);
        writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);

        writer.write("var parentCombo = document.getElementById('" + parentComboBox.getClientId(context) + "');");
        HtmlRendererUtils.writePrettyLineSeparator(context);
        writer.write("dojo.event.connect(parentCombo, 'onchange', function(evt) { ");
        HtmlRendererUtils.writePrettyLineSeparator(context);
        writer.write("var targetElement = evt.target;");
        writer.write("var targetValue = targetElement.options[targetElement.selectedIndex].value;");
        HtmlRendererUtils.writePrettyLineSeparator(context);
        writer.write("reloadChildComboBox('" + clientId + "', targetValue);");
        HtmlRendererUtils.writePrettyLineSeparator(context);
        writer.write("});");
        writer.endElement(HTML.SCRIPT_ELEM);
        // End: Javascript
    }

    // creates the XML response that is sent back to the browser
    public void encodeAjax(FacesContext context, UIComponent uiComponent) throws IOException {

        String parentValue = (String) context.getExternalContext().getRequestParameterMap().get("parentValue");

        ServletResponse response = (ServletResponse) context.getExternalContext().getResponse();
        PrintWriter writer = response.getWriter();

        StringBuffer xml = new StringBuffer();

        MethodExpression mb = ((AjaxChildComboBox) uiComponent).getAjaxSelectItemsMethod();
        SelectItem[] options = (SelectItem[]) mb.invoke(context.getELContext(), new Object[] { parentValue });

        xml.append("<?xml version=\"1.0\"?>\n");
        xml.append("<response>\n");
        for (int i = 0; i < options.length; i++) {
            xml.append(BEGIN_OPTION);
            xml.append(BEGIN_OPTION_TEXT).append(options[i].getLabel()).append(END_OPTION_TEXT);
            xml.append(BEGIN_OPTION_VALUE).append(options[i].getValue()).append(END_OPTION_VALUE);
            xml.append(END_OPTION);
        }
        xml.append("</response>");

        writer.write(xml.toString());

    }

    private UIComponent getParentComboBox(AjaxChildComboBox comboBox) {
        String parentId = comboBox.getParentComboBox();

        UIComponent parentComboBox = comboBox.findComponent(parentId);
        if (parentComboBox != null) {
            return parentComboBox;
        }

        // try searching from the very root of the component tree
        return comboBox.findComponent(UINamingContainer.SEPARATOR_CHAR + parentId);
    }
}