Package org.ajax4jsf.renderkit.html

Source Code of org.ajax4jsf.renderkit.html.AjaxFormRenderer

/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
*/

package org.ajax4jsf.renderkit.html;

import java.io.IOException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIViewRoot;
import javax.faces.component.html.HtmlForm;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.ajax4jsf.component.UIAjaxForm;
import org.ajax4jsf.event.AjaxEvent;
import org.ajax4jsf.javascript.JSFunction;
import org.ajax4jsf.javascript.ScriptUtils;
import org.ajax4jsf.renderkit.AjaxComponentRendererBase;
import org.ajax4jsf.renderkit.AjaxRendererUtils;
import org.ajax4jsf.renderkit.RendererUtils.HTML;
import org.ajax4jsf.resource.InternetResource;

/**
* @author shura
*
*/
public class AjaxFormRenderer extends AjaxComponentRendererBase {

  public static final String FORM_SUBMIT_FUNCTION_NAME = "_JSFFormSubmit";

  public static final String FORM_CLEAR_FUNCTION_NAME = "_clearJSFFormParameters";

  private static final String FORM_HAS_COMMAND_LINK_ATTR = "com.sun.faces.FORM_HAS_COMMAND_LINK_ATTR";

  private static final String NO_COMMAND_LINK_FOUND_VALUE = "com.sun.faces.NO_COMMAND_LINK_FOUND";

  public static final String CONTENT_TYPE_IS_XHTML = "com.sun.faces"
      + "ContentTypeIsXHTML";

  public static final String HIDDEN_FIELD_SUFFIX = NamingContainer.SEPARATOR_CHAR
      + UIViewRoot.UNIQUE_ID_PREFIX + "cl";

  private static final String HIDDEN_COMMAND_INPUTS_SET_ATTR = UIForm.class
      .getName()
      + ".org.apache.myfaces.HIDDEN_COMMAND_INPUTS_SET";

  private static final String MYFACES_HIDDEN_FIELD_SUFFIX = NamingContainer.SEPARATOR_CHAR
      + "_link_hidden_";

  private InternetResource[] _scripts = { getResource("/org/ajax4jsf/javascript/scripts/form.js") };

  private static final String[] exclusions = { "onsubmit" };

  public static final String AJAX_FORM_FUNCTION_NAME = "A4J.AJAX.SubmitForm";

  /*
   * (non-Javadoc)
   *  
   * @see org.ajax4jsf.renderkit.RendererBase#doDecode(javax.faces.context.FacesContext,
   *      javax.faces.component.UIComponent)
   */
  protected void doDecode(FacesContext context, UIComponent component) {
    UIForm form = (UIForm) component;
    boolean submitted = context.getExternalContext()
        .getRequestParameterMap().containsKey(
            component.getClientId(context));
    form.setSubmitted(submitted);
    if (component instanceof UIAjaxForm) {
        UIAjaxForm ajaxForm = (UIAjaxForm) component;
      if (submitted && ajaxForm.isAjaxSubmit()) {
        component.queueEvent(new AjaxEvent(component));
      }       
    }
  }

  /*
   * (non-Javadoc)
   *
   * @see org.ajax4jsf.renderkit.HeaderResourcesRendererBase#getScripts()
   */
  protected InternetResource[] getAdditionalScripts() {
    // TODO Auto-generated method stub
    return _scripts;
  }

  /*
   * (non-Javadoc)
   *
   * @see org.ajax4jsf.renderkit.RendererBase#doEncodeBegin(javax.faces.context.ResponseWriter,
   *      javax.faces.context.FacesContext, javax.faces.component.UIComponent)
   */
  protected void doEncodeBegin(ResponseWriter writer, FacesContext context,
      UIComponent component) throws IOException {
    String clientId = component.getClientId(context);
    writer.startElement(HTML.FORM_ELEMENT, component);
    writer.writeAttribute(HTML.id_ATTRIBUTE, clientId, null);
    writer.writeAttribute(HTML.NAME_ATTRIBUTE, clientId, null);
    writer.writeAttribute(HTML.METHOD_ATTRIBUTE, "post", null);
    getUtils().encodeAttribute(context, component, "style");
    getUtils().encodeAttribute(context, component, "class");
    getUtils().encodePassThru(context, component);
    context.getExternalContext().getRequestMap().put(
        FORM_HAS_COMMAND_LINK_ATTR, clientId);
    if (component instanceof UIAjaxForm) {
      UIAjaxForm form = (UIAjaxForm) component;
      if (form.isAjaxSubmit()) {
        StringBuffer onSubmit = new StringBuffer("javascript:");
        JSFunction ajaxFunction = AjaxRendererUtils.buildAjaxFunction(
            component, context,
            AJAX_FORM_FUNCTION_NAME);
        ajaxFunction.addParameter(AjaxRendererUtils.buildEventOptions(
            context, component));
        ajaxFunction.appendScript(onSubmit);
        writer.writeURIAttribute("action", onSubmit, "action");
      } else {
        encodeSubmitAction(writer, context);
      }
    } else {
      encodeSubmitAction(writer, context);
    }
  }

  /**
   * @param writer
   * @param context
   * @throws IOException
   */
  private void encodeSubmitAction(ResponseWriter writer, FacesContext context)
      throws IOException {
    String actionURL = getUtils().getActionUrl(context);
    String encodedActionURL = context.getExternalContext().encodeActionURL(
        actionURL);
    writer.writeURIAttribute("action", encodedActionURL, "action");
  }

  /*
   * (non-Javadoc)
   *
   * @see org.ajax4jsf.renderkit.RendererBase#doEncodeEnd(javax.faces.context.ResponseWriter,
   *      javax.faces.context.FacesContext, javax.faces.component.UIComponent)
   */
  protected void doEncodeEnd(ResponseWriter writer, FacesContext context,
      UIComponent component) throws IOException {
    // Encode form submitting flag hidden field.
    String clientId = component.getClientId(context);
    renderHiddenInputField(writer, clientId, clientId);
    renderHiddenInputField(writer, "autoScroll", null);
    // MyFaces compability - render hidden field and Script.
    // render hidden command inputs
    Set hiddenFields = new HashSet();
    hiddenFields.add(clientId + HIDDEN_FIELD_SUFFIX);
    hiddenFields.add(clientId + MYFACES_HIDDEN_FIELD_SUFFIX);
    Set set = (Set) component.getAttributes().get(
        HIDDEN_COMMAND_INPUTS_SET_ATTR);
    if (set != null) {
      hiddenFields.addAll(set);
    }
    set = (Set) context.getExternalContext().getRequestMap().get(
        getHiddenCommandInputsSetName(context, component));
    if (set != null) {
      hiddenFields.addAll(set);
    }
    renderHiddenCommandFormParams(writer, hiddenFields);
    String target;
    if (component instanceof HtmlForm) {
      target = ((HtmlForm) component).getTarget();
    } else {
      target = (String) component.getAttributes().get(
          HTML.target_ATTRIBUTE);
    }
    renderClearHiddenCommandFormParamsFunction(writer, clientId, hiddenFields, target);
    // Script
    if (component instanceof UIAjaxForm) {
      UIAjaxForm form = (UIAjaxForm) component;
      if (form.isAjaxSubmit()) {
        renderAjaxFormSetupScript(writer, clientId);
      }
    }
    // writeFormSubmitScript(context, writer);
    getUtils().encodeEndForm(context, writer);
    context.getExternalContext().getRequestMap().put(
        FORM_HAS_COMMAND_LINK_ATTR, NO_COMMAND_LINK_FOUND_VALUE);
  }

  private static String getHiddenCommandInputsSetName(
      FacesContext facesContext, UIComponent form) {
    StringBuffer buf = new StringBuffer();
    buf.append(HIDDEN_COMMAND_INPUTS_SET_ATTR);
    buf.append("_");
    buf.append(form.getClientId(facesContext));
    return buf.toString();
  }

  /*
   * (non-Javadoc)
   *
   * @see org.ajax4jsf.renderkit.RendererBase#getComponentClass()
   */
  protected Class getComponentClass() {
    // TODO Auto-generated method stub
    return UIForm.class;
  }

  // For MyFaces compability - create hidden firlds and script. Code got from
  // project to simulate same functionality.
  public void renderHiddenCommandFormParams(ResponseWriter writer,
      Set formParams) throws IOException {
    for (Iterator it = formParams.iterator(); it.hasNext();) {
      Object name = it.next();
      renderHiddenInputField(writer, name, "");
    }
  }

  public void renderHiddenInputField(ResponseWriter writer, Object name,
      Object value) throws IOException {
    writer.startElement(HTML.INPUT_ELEM, null);
    writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_HIDDEN, null);
    writer.writeAttribute(HTML.NAME_ATTRIBUTE, name, null);
    writer.writeAttribute(HTML.value_ATTRIBUTE, value != null?value:"", null);
    writer.endElement(HTML.INPUT_ELEM);
  }
 
 
  public void renderAjaxFormSetupScript(ResponseWriter writer, String formName) throws IOException {
    writer.startElement(HTML.SCRIPT_ELEM, null);
    writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);
    writer.writeText("A4J.setupForm('"+formName+"');", null);
    writer.endElement(HTML.SCRIPT_ELEM);
  }

  /**
   * Render the javascript function that is called on a click on a commandLink
   * to clear the hidden inputs. This is necessary because on a browser back,
   * each hidden input still has it's old value (browser cache!) and therefore
   * a new submit would cause the according action once more!
   *
   * @param writer
   * @param formName
   * @param dummyFormParams
   * @param formTarget
   * @throws IOException
   */
  public void renderClearHiddenCommandFormParamsFunction(
      ResponseWriter writer, String formName, Set dummyFormParams,
      String formTarget) throws IOException {
    // render the clear hidden inputs javascript function
    String functionName = getClearHiddenCommandFormParamsFunctionName(formName);
    writer.startElement(HTML.SCRIPT_ELEM, null);
    writer.writeAttribute(HTML.TYPE_ATTR, "text/javascript", null);

    // Using writeComment instead of write with <!-- tag
    StringBuffer script = new StringBuffer();
    script.append("function ");
    script.append(functionName);
    script.append("() {\n");
    script.append(FORM_CLEAR_FUNCTION_NAME);
    script.append("('");
    script.append(formName);
    script.append("','");
    if (formTarget != null && formTarget.length() > 0) {
      script.append(formTarget);
    }
    script.append("'");
    if (dummyFormParams != null) {
      script.append(",[");
      for (Iterator it = dummyFormParams.iterator(); it.hasNext();) {
        script.append('\'');
        script.append((String) it.next());
        script.append('\'');
        if (it.hasNext()) {
          script.append(',');
        }
      }
      script.append("]");
    }
    script.append(");");
    script.append("\n}");
    script.append("\n");
    script.append("function ").append("clearFormHiddenParams_").append(
        ScriptUtils.getValidJavascriptName(formName));
    script.append("(){").append(functionName).append("();}\n");
    // MyFaces 1.1.5 clear form function name
   
    //equivalent for formName.replace("-", "$_")
    StringBuffer formNameReplaceBuffer = new StringBuffer(formName.length());
    int idx = -1;
    int idxA = 0;
    while ((idx = formName.indexOf('-', idxA)) != -1) {
      formNameReplaceBuffer.append(formName.substring(idxA, idx));
      formNameReplaceBuffer.append("$_");
      idxA = idx + 1;
    }
    formNameReplaceBuffer.append(formName.substring(idxA));
   
    script.append("function ").append("clearFormHiddenParams_").append(formNameReplaceBuffer.toString().
      replace(':', '_'));
    script.append("(){").append(functionName).append("();}\n");
    // Just to be sure we call this clear method on each load.
    // Otherwise in the case, that someone submits a form by pressing Enter
    // within a text input, the hidden inputs won't be cleared!
    script.append(functionName);
    script.append("();");

    writer.writeText(script.toString(), null);
    writer.endElement(HTML.SCRIPT_ELEM);
  }

  /**
   * Prefixes the given String with "clear_" and removes special characters
   *
   * @param formName
   * @return String
   */
  public String getClearHiddenCommandFormParamsFunctionName(String formName) {
    return "clear_" + ScriptUtils.getValidJavascriptName(formName);
  }

}
TOP

Related Classes of org.ajax4jsf.renderkit.html.AjaxFormRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.