001: /*
002: * $Id: AjaxEventBehavior.java 4838 2006-03-08 15:59:03 -0800 (Wed, 08 Mar 2006)
003: * eelco12 $ $Revision: 461166 $ $Date: 2006-03-08 15:59:03 -0800 (Wed, 08 Mar
004: * 2006) $
005: *
006: * ==============================================================================
007: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
008: * use this file except in compliance with the License. You may obtain a copy of
009: * the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
015: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
016: * License for the specific language governing permissions and limitations under
017: * the License.
018: */
019: package wicket.ajax;
020:
021: import java.io.Serializable;
022:
023: import wicket.markup.ComponentTag;
024: import wicket.util.string.Strings;
025: import wicket.util.time.Duration;
026:
027: /**
028: * An ajax behavior that is attached to a certain client-side (usually
029: * javascript) event, such as onClick, onChange, onKeyDown, etc.
030: * <p>
031: * Example:
032: *
033: * <pre>
034: * DropDownChoice choice=new DropDownChoice(...);
035: * choice.add(new AjaxEventBehavior("onchange") {
036: * protected void onEvent(AjaxRequestTarget target) {
037: * System.out.println("ajax here!");
038: * }
039: * }
040: * </pre>
041: *
042: * This behavior will be linked to the onChange javascript event of the select
043: * box this DropDownChoice represents, and so anytime a new option is selected
044: * we will get the System.out message
045: *
046: * @since 1.2
047: *
048: * @author Igor Vaynberg (ivaynberg)
049: */
050: public abstract class AjaxEventBehavior extends
051: AbstractDefaultAjaxBehavior {
052: private static long sequence = 0;
053:
054: private static final long serialVersionUID = 1L;
055:
056: private String event;
057:
058: private ThrottlingSettings throttlingSettings;
059:
060: /**
061: * Construct.
062: *
063: * @param event
064: * event this behavior will be attached to
065: */
066: public AjaxEventBehavior(final String event) {
067: if (Strings.isEmpty(event)) {
068: throw new IllegalArgumentException(
069: "argument [event] cannot be null or empty");
070: }
071:
072: onCheckEvent(event);
073:
074: this .event = event;
075: }
076:
077: /**
078: * Sets the throttle delay for this behavior. Throttled behaviors only
079: * execute once withing the given delay even though they are triggered
080: * multiple times.
081: * <p>
082: * For example, this is useful when attaching this behavior to the
083: * onkeypress event. It is not desirable to have an ajax call made every
084: * time the user types so we throttle that call to a desirable delay, such
085: * as once per second. This gives us a near real time ability to provide
086: * feedback without overloading the server with ajax calls.
087: *
088: *
089: * @param throttleDelay
090: * throttle delay
091: * @return this for chaining
092: */
093: public final AjaxEventBehavior setThrottleDelay(
094: Duration throttleDelay) {
095: throttlingSettings = new ThrottlingSettings(
096: "th" + (++sequence), throttleDelay);
097: return this ;
098: }
099:
100: /**
101: *
102: * @see wicket.behavior.AbstractAjaxBehavior#onComponentTag(wicket.markup.ComponentTag)
103: */
104: protected void onComponentTag(final ComponentTag tag) {
105: super .onComponentTag(tag);
106:
107: // only add the event handler when the component is enabled.
108: if (this .getComponent().isEnabled()) {
109: tag.put(event, getEventHandler());
110: }
111: }
112:
113: /**
114: *
115: * @return event handler
116: */
117: protected CharSequence getEventHandler() {
118: CharSequence handler = getCallbackScript();
119: if (event.equalsIgnoreCase("href")) {
120: handler = "javascript:" + handler;
121: }
122: return handler;
123: }
124:
125: protected CharSequence getCallbackScript(CharSequence partialCall,
126: CharSequence onSuccessScript, CharSequence onFailureScript) {
127: CharSequence script = super .getCallbackScript(partialCall,
128: onSuccessScript, onFailureScript);
129: final ThrottlingSettings ts = throttlingSettings;
130:
131: if (ts != null) {
132: script = AbstractDefaultAjaxBehavior.throttleScript(script,
133: ts.getId(), ts.getDelay());
134: }
135: return script;
136: }
137:
138: /**
139: *
140: * @param event
141: */
142: protected void onCheckEvent(final String event) {
143: }
144:
145: /**
146: *
147: * @return event
148: */
149: public final String getEvent() {
150: return event;
151: }
152:
153: /**
154: *
155: * @see wicket.ajax.AbstractDefaultAjaxBehavior#respond(wicket.ajax.AjaxRequestTarget)
156: */
157: protected final void respond(final AjaxRequestTarget target) {
158: onEvent(target);
159: }
160:
161: /**
162: * Listener method for the ajax event
163: *
164: * @param target
165: */
166: protected abstract void onEvent(final AjaxRequestTarget target);
167:
168: /**
169: * Class to keep track of throttling settings.
170: *
171: * @author ivaynberg
172: */
173: private static class ThrottlingSettings implements Serializable {
174: private static final long serialVersionUID = 1L;
175:
176: private final Duration delay;
177: private final String id;
178:
179: /**
180: * Construct.
181: *
182: * @param id
183: * throttle id
184: * @param delay
185: * throttle delay
186: */
187: public ThrottlingSettings(final String id, final Duration delay) {
188: super ();
189: this .id = id;
190: this .delay = delay;
191: }
192:
193: /**
194: * @return throttle delay
195: */
196: public Duration getDelay() {
197: return delay;
198: }
199:
200: /**
201: * @return throttle id
202: */
203: public String getId() {
204: return id;
205: }
206:
207: }
208: }
|