All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ajax4jsf.renderers.ajax.FormRenderer Maven / Gradle / Ivy

Go to download

Ajax4jsf is an open source extension to the JavaServer Faces standard that adds AJAX capability to JSF applications without requiring the writing of any JavaScript.

The newest version!
/**
 * 
 */
package org.ajax4jsf.renderers.ajax;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
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.ajax.UIAjaxForm;
import org.ajax4jsf.framework.ajax.AjaxEvent;
import org.ajax4jsf.framework.renderer.AjaxComponentRendererBase;
import org.ajax4jsf.framework.renderer.AjaxRendererUtils;
import org.ajax4jsf.framework.renderer.HeaderResourcesRendererBase;
import org.ajax4jsf.framework.renderer.RendererUtils.HTML;
import org.ajax4jsf.framework.resource.InternetResource;
import org.ajax4jsf.framework.util.javascript.JSFunction;
import org.ajax4jsf.framework.util.javascript.JSReference;

/**
 * @author shura
 * 
 */
public class FormRenderer 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("scripts/form.js") };

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

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

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

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.ajax4jsf.framework.renderer.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,
						AjaxRendererUtils.AJAX_FUNCTION_NAME);
				ajaxFunction.addParameter(JSReference.NULL);// in form action
															// event is null
				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.framework.renderer.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, component
				.getClientId(context), hiddenFields, target);
		// Script
		// 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.framework.renderer.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, null);
		}
	}

	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);
		if (value != null) {
			writer.writeAttribute(HTML.value_ATTRIBUTE, value, null);
		}
		writer.endElement(HTML.INPUT_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 
            
    
            


© 2015 - 2024 Weber Informatics LLC | Privacy Policy