/* * 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.wicket.ajax.attributes; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.wicket.ajax.AjaxChannel; import org.apache.wicket.util.lang.Args; import org.apache.wicket.util.time.Duration; /** * Attributes of an Ajax Request. * * @author Matej Knopp */ public final class AjaxRequestAttributes { /** * The method to be used when submitting a form */ public enum Method { /** get */ GET, /** post */ POST; @Override public String toString() { return name(); } } /** * The JavaScript event propagation type */ public enum EventPropagation { /** * Stops the propagation of the JavaScript event to the parent of its target */ STOP, /** * Stops the propagation of the JavaScript event to the parent of its target and all other * event listeners registered on the same target */ STOP_IMMEDIATE, /** * Do not stop the propagation of the JavaScript event */ BUBBLE } public static final String XML_DATA_TYPE = "xml"; private boolean multipart = false; private Method method = Method.GET; private Duration requestTimeout; private boolean preventDefault = false; private EventPropagation eventPropagation = EventPropagation.BUBBLE; /** * The names of the events which will trigger the Ajax call */ private String[] eventNames = new String[0]; /** * The id of the for that should be submitted */ private String formId; /** * The id of the button/link that submitted the form */ private String submittingComponentName; /** * Indicates whether or not this AjaxBehavior will produce <ajax-response>. By default it will * produce it but some behaviors may need to return their own response which shouldn't be * processed by wicket-ajax.js */ private boolean wicketAjaxResponse = true; private String dataType = XML_DATA_TYPE; private List<IAjaxCallListener> ajaxCallListeners; private Map<String, Object> extraParameters; private List<CharSequence> dynamicExtraParameters; private AjaxChannel channel; /** * Whether or not to use asynchronous XMLHttpRequest */ private boolean async = true; /** * The settings to use if the Ajax call should be throttled. Throttled behaviors only execute * once within the given delay even though they are triggered multiple times. * <p> * For example, this is useful when attaching a behavior to the keypress event. It is not * desirable to have an ajax call made every time the user types so we throttle that call to a * desirable delay, such as once per second. This gives us a near real time ability to provide * feedback without overloading the server with ajax calls. */ private ThrottlingSettings throttlingSettings; /** * A selector string to filter the descendants of the selected * elements that trigger the event. If the selector is null or empty, * the event is always triggered when it reaches the selected HTML element. * * @see <a href="http://api.jquery.com/on/">jQuery#on's selector</a> */ private CharSequence childSelector; /** * A flag indicating whether to collect (submit) the name/value pairs for all HTML form elements * children of the HTML element with the JavaScript listener */ private boolean serializeRecursively; /** * @see #childSelector * @return The selector string that filters the descendants */ public CharSequence getChildSelector() { return childSelector; } /** * @see #childSelector * @param childSelector * The selector string that filters the descendants */ public void setChildSelector(CharSequence childSelector) { this.childSelector = childSelector; } /** * Returns whether the form submit is multipart. * <p> * Note that for multipart AJAX requests a hidden IFRAME will be used and that can have negative * impact on error detection. * * @return <code>true</code> if the form submit should be multipart, <code>false</code> * otherwise */ public boolean isMultipart() { return multipart; } /** * Determines whether the form submit is multipart. * * <p> * Note that for multipart AJAX requests a hidden IFRAME will be used and that can have negative * impact on error detection. * * @param multipart * @return this object */ public AjaxRequestAttributes setMultipart(boolean multipart) { this.multipart = multipart; return this; } /** * Returns the type of the Ajax request: <code>GET</code> or <code>POST</code>. * <p> * For a <code>POST</code>request all URL arguments are submitted as body. This can be useful if * the URL parameters are longer than maximal URL length. * * @return the type of the Ajax request. Default: {@linkplain Method#GET} */ public Method getMethod() { return method; } /** * Sets the type of the Ajax request: <code>GET</code> or <code>POST</code>. * <p> * For a <code>POST</code>request all URL arguments are submitted as body. This can be useful if * the URL parameters are longer than maximal URL length. * * @param method * the type of the Ajax request * @return {@code this} object for chaining */ public AjaxRequestAttributes setMethod(final Method method) { this.method = Args.notNull(method, "method"); return this; } /** * Returns the timeout in milliseconds for the AJAX request. This only involves the actual * communication and not the processing afterwards. Can be <code>null</code> in which case the * default request timeout will be used. * * @return request timeout or <code>null<code> for default timeout. Default: no timeout. */ public Duration getRequestTimeout() { return requestTimeout; } /** * Sets the timeout in milliseconds for the AJAX request. This only involves the actual * communication and not the processing afterwards. Can be <code>null</code> in which case the * default request timeout will be used. * * @param requestTimeout * @return this object */ public AjaxRequestAttributes setRequestTimeout(final Duration requestTimeout) { this.requestTimeout = requestTimeout; return this; } /** * @return a list of {@link IAjaxCallListener}s which will be notified during the the execution * of the Ajax call. */ public List<IAjaxCallListener> getAjaxCallListeners() { if (ajaxCallListeners == null) { ajaxCallListeners = new ArrayList<>(); } return ajaxCallListeners; } /** * Map that contains additional (static) URL parameters. These will be appended to the request * URL. If you need more than one value for a key then use a java.util.List or an Object[] as a * value of that key. * * @return a map with additional URL arguments * @see #getDynamicExtraParameters() */ public Map<String, Object> getExtraParameters() { if (extraParameters == null) { extraParameters = new HashMap<>(); } return extraParameters; } /** * Array of JavaScript functions that produce additional URL arguments. * * <p> * If there are no multivalued parameters then the function can return a simple JavaScript * object. Example: * * <pre> * return { * 'param1': document.body.tagName, * 'param2': calculateParam2() * } * </pre> * * </p> * <p> * If there are multivalued parameters then an array of objects may be used. Example: * * <pre> * return [ * { name: 'param1', value: document.body.tagName }, * { name: 'param1', value: calculateSecondValueForParam1() }, * { name: 'param2', value: calculateParam2() } * ] * * </pre> * * </p> * * @return a list of functions that produce additional URL arguments. * @see #getExtraParameters() */ public List<CharSequence> getDynamicExtraParameters() { if (dynamicExtraParameters == null) { dynamicExtraParameters = new ArrayList<>(); } return dynamicExtraParameters; } /** * Only applies for event behaviors. Returns whether the behavior should prevent the default event * handler to be invoked. For example if the behavior is attached to a link and * isPreventDefault() returns <code>true</code>, the link's * URL will not be followed. If the Ajax behavior is attached to a checkbox or a radio button * then the default behavior should be allowed to actually check the box or radio button, i.e. * this method should return <code>false</code>. * * @return {@code false} if the default event handler should be invoked */ public boolean isPreventDefault() { return preventDefault; } /** * Only applies for event behaviors. Determines whether the behavior should prevent the default * event handler to be invoked. * * @see #isPreventDefault() * * @param preventDefault * @return {@code this} object for chaining * @see #isPreventDefault() */ public AjaxRequestAttributes setPreventDefault(boolean preventDefault) { this.preventDefault = preventDefault; return this; } /** * Only applies for event behaviors. Returns whether the behavior should allow the JavaScript * event to propagate to the parent of its target. */ public EventPropagation getEventPropagation() { return eventPropagation; } /** * Only applies to event behaviors. Determines whether the behavior should allow the JavaScript * event to propagate to the parent of its target. * * @param eventPropagation * the type of the stop * @return {@code this} object, for chaining */ public AjaxRequestAttributes setEventPropagation(EventPropagation eventPropagation) { this.eventPropagation = Args.notNull(eventPropagation, "eventPropagation"); return this; } /** * @param async * a flag whether to do asynchronous Ajax call or not * @return {@code this} object for chaining */ public AjaxRequestAttributes setAsynchronous(final boolean async) { this.async = async; return this; } /** * @return whether to do asynchronous Ajax call */ public boolean isAsynchronous() { return async; } /** * @return the channel to use */ public AjaxChannel getChannel() { return channel; } /** * @param channel * the Ajax channel to use. Pass {@code null} to use the default channel with name * <em>0</em> and queueing type. * @return {@code this} object for chaining */ public AjaxRequestAttributes setChannel(final AjaxChannel channel) { this.channel = channel; return this; } /** * @return the name(s) of the event(s) which will trigger the Ajax call */ public String[] getEventNames() { return eventNames; } /** * @param eventNames * the names of the events which will trigger the Ajax call * @return {@code this} object for chaining */ public AjaxRequestAttributes setEventNames(String... eventNames) { Args.notNull(eventNames, "eventNames"); this.eventNames = eventNames; return this; } /** * @return the id of the for that should be submitted */ public String getFormId() { return formId; } /** * @param formId * the id of the for that should be submitted * @return {@code this} object for chaining */ public AjaxRequestAttributes setFormId(final String formId) { this.formId = formId; return this; } /** * @return the input name of the button/link that submits the form */ public String getSubmittingComponentName() { return submittingComponentName; } /** * @param submittingComponentName * the input name of the button/link that submits the form * @return {@code this} object for chaining */ public AjaxRequestAttributes setSubmittingComponentName(String submittingComponentName) { this.submittingComponentName = submittingComponentName; return this; } /** * @return a flag indicating whether the Ajax response should be processed by Wicket (i.e. to * replace components, execute scripts, etc.). Default: {@code true}. */ public boolean isWicketAjaxResponse() { return wicketAjaxResponse; } /** * @param wicketAjaxResponse * a flag indicating whether the Ajax response should be processed by Wicket (i.e. to * replace components, execute scripts, etc.). * @return {@code this} object for chaining */ public AjaxRequestAttributes setWicketAjaxResponse(final boolean wicketAjaxResponse) { this.wicketAjaxResponse = wicketAjaxResponse; return this; } /** * Returns the type of the data in the Ajax response. For example: 'xml', 'json', 'html', etc. * See the documentation of jQuery.ajax() method for more information. * * @return the type of the data in the Ajax response. */ public String getDataType() { return dataType; } /** * @param dataType * the type of the data in the Ajax response. * @return {@code this} object for chaining */ public AjaxRequestAttributes setDataType(final String dataType) { this.dataType = Args.notEmpty(dataType, "dataType"); return this; } /** * @return the settings to use when throttling is needed. */ public ThrottlingSettings getThrottlingSettings() { return throttlingSettings; } /** * @param throttlingSettings * the settings to use when throttling is needed. Pass {@code null} to disable * throttling. * @return {@code this} object for chaining */ public AjaxRequestAttributes setThrottlingSettings(ThrottlingSettings throttlingSettings) { this.throttlingSettings = throttlingSettings; return this; } /** * @return whether to collect (submit) the name/value pairs for all HTML form elements * children of the HTML element with the JavaScript listener */ public boolean isSerializeRecursively() { return serializeRecursively; } /** * @param serializeRecursively * a flag indicating whether to collect (submit) the name/value pairs for all HTML form elements * children of the HTML element with the JavaScript listener */ public AjaxRequestAttributes setSerializeRecursively(final boolean serializeRecursively) { this.serializeRecursively = serializeRecursively; return this; } }