001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.behavior; 018 019import org.apache.wicket.Component; 020import org.apache.wicket.IRequestListener; 021import org.apache.wicket.markup.ComponentTag; 022import org.apache.wicket.request.mapper.parameter.INamedParameters; 023import org.apache.wicket.request.mapper.parameter.PageParameters; 024import org.apache.wicket.util.lang.Args; 025 026import java.util.List; 027 028/** 029 * Abstract class for handling Ajax roundtrips. This class serves as a base for javascript specific 030 * implementations, like ones based on Dojo or Scriptaculous, or Wicket's default. 031 * 032 * @author Eelco Hillenius 033 * @author Ralf Ebert 034 * @author Igor Vaynberg 035 */ 036public abstract class AbstractAjaxBehavior extends Behavior implements IRequestListener 037{ 038 private static final long serialVersionUID = 1L; 039 040 /** the component that this handler is bound to. */ 041 private Component component; 042 043 /** 044 * Constructor. 045 */ 046 public AbstractAjaxBehavior() 047 { 048 } 049 050 /** 051 * Bind this handler to the given component. 052 * 053 * @param hostComponent 054 * the component to bind to 055 */ 056 @Override 057 public final void bind(final Component hostComponent) 058 { 059 Args.notNull(hostComponent, "hostComponent"); 060 061 if (component != null) 062 { 063 throw new IllegalStateException("this kind of handler cannot be attached to " + 064 "multiple components; it is already attached to component " + component + 065 ", but component " + hostComponent + " wants to be attached too"); 066 } 067 068 component = hostComponent; 069 070 // call the callback 071 onBind(); 072 } 073 074 /** 075 * Gets the url that references this handler. 076 * 077 * @return the url that references this handler 078 */ 079 public CharSequence getCallbackUrl() 080 { 081 Component component = getComponent(); 082 if (component == null) 083 { 084 throw new IllegalArgumentException( 085 "Behavior must be bound to a component to create the URL"); 086 } 087 088 PageParameters parameters = new PageParameters(); 089 PageParameters pageParameters = component.getPage().getPageParameters(); 090 List<INamedParameters.NamedPair> allNamedInPath = pageParameters.getAllNamedByType(INamedParameters.Type.PATH); 091 for (INamedParameters.NamedPair namedPair : allNamedInPath) { 092 parameters.add(namedPair.getKey(), namedPair.getValue(), INamedParameters.Type.PATH); 093 } 094 return getComponent().urlForListener(this, parameters); 095 } 096 097 @Override 098 public final void onComponentTag(final Component component, final ComponentTag tag) 099 { 100 onComponentTag(tag); 101 } 102 103 @Override 104 public final void afterRender(final Component hostComponent) 105 { 106 onComponentRendered(); 107 } 108 109 /** 110 * Gets the component that this handler is bound to. 111 * 112 * @return the component that this handler is bound to 113 */ 114 protected final Component getComponent() 115 { 116 return component; 117 } 118 119 /** 120 * Called any time a component that has this handler registered is rendering the component tag. 121 * Use this method e.g. to bind to javascript event handlers of the tag 122 * 123 * @param tag 124 * the tag that is rendered 125 */ 126 protected void onComponentTag(final ComponentTag tag) 127 { 128 } 129 130 /** 131 * Called when the component was bound to it's host component. You can get the bound host 132 * component by calling getComponent. 133 */ 134 protected void onBind() 135 { 136 } 137 138 /** 139 * Called to indicate that the component that has this handler registered has been rendered. Use 140 * this method to do any cleaning up of temporary state 141 */ 142 protected void onComponentRendered() 143 { 144 } 145 146 @Override 147 public final void unbind(Component component) 148 { 149 onUnbind(); 150 151 this.component = null; 152 153 super.unbind(component); 154 } 155 156 /** 157 * Called when the behavior is removed from its component. The bound host component is 158 * still available through {@linkplain #getComponent()}. The relation to it will be removed 159 * right after the finish of the execution of this method. 160 */ 161 protected void onUnbind() 162 { 163 } 164}