001 // Copyright 2004, 2005 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014 package org.apache.tapestry.dojo.html;
015
016 import org.apache.hivemind.ApplicationRuntimeException;
017 import org.apache.tapestry.*;
018 import org.apache.tapestry.dojo.AbstractWidget;
019 import org.apache.tapestry.engine.DirectServiceParameter;
020 import org.apache.tapestry.engine.IEngineService;
021 import org.apache.tapestry.json.JSONObject;
022 import org.apache.tapestry.link.DirectLink;
023 import org.apache.tapestry.listener.ListenerInvoker;
024
025 import java.util.Collections;
026 import java.util.HashMap;
027 import java.util.List;
028 import java.util.Map;
029
030
031 /**
032 * Wraps a dojo InlineEditBox widget.
033 *
034 * <p>
035 * Manages a single string value that when hovered over can be edited "inline" in the document
036 * wherever it is referenced. Supports various modes of operation (ie disable/enabled), as well as
037 * textarea or single line style edits.
038 * </p>
039 *
040 *
041 * <p>
042 * Some of the commonly used widget functions to listen to are:<br/>
043 * <ul>
044 * <li><b>onSave - </b>When the save button is clicked. Default function listened to when updating
045 * server side managed value.
046 * </li>
047 * <li><b>onUndo - </b>When cancel button is clicked.</li>
048 * <li><b>onMouseOver - </b>Mouse moved over editable region.</li>
049 * <li><b>onMouseOut - </b>Mouse moved away from editable region.</li>
050 * </ul>
051 * </p>
052 *
053 */
054 public abstract class InlineEditBox extends AbstractWidget implements IDirect
055 {
056 /**
057 * Default single line editing text mode. Use as one of two possible
058 * parameters to the <code>mode</code> parameter.
059 */
060 public static final String TEXT_MODE = "text";
061
062 /**
063 * Multi line editing text mode. Use as one of two possible
064 * parameters to the <code>mode</code> parameter.
065 */
066 public static final String TEXT_AREA_MODE = "textarea";
067
068 public abstract String getValue();
069 public abstract void setValue(String value);
070
071 public abstract String getMode();
072
073 public abstract int getMinWidth();
074
075 public abstract int getMinHeight();
076
077 public abstract boolean getDoFade();
078
079 public abstract boolean isDisabled();
080
081 public abstract IActionListener getListener();
082
083 public abstract Object getParameters();
084
085 public abstract void setStateful(boolean value);
086
087 /**
088 * {@inheritDoc}
089 */
090 public void renderWidget(IMarkupWriter writer, IRequestCycle cycle)
091 {
092 if (!cycle.isRewinding())
093 {
094 writer.begin(getTemplateTagName()); // use whatever template tag they specified
095 renderInformalParameters(writer, cycle);
096 renderIdAttribute(writer, cycle);
097 }
098
099 renderBody(writer, cycle);
100
101 if (!cycle.isRewinding())
102 {
103 writer.end();
104 }
105
106 if(getMode() == null || (!TEXT_MODE.equals(getMode()) && !TEXT_AREA_MODE.equals(getMode())))
107 throw new ApplicationRuntimeException(WidgetMessages.invalidTextMode(getMode()));
108
109 if (cycle.isRewinding())
110 return;
111
112 JSONObject prop = new JSONObject();
113 prop.put("widgetId", getClientId());
114 prop.put("value", getValue());
115 prop.put("mode", getMode());
116 prop.put("minWidth", getMinWidth());
117 prop.put("minHeight", getMinHeight());
118 prop.put("doFade", getDoFade());
119
120 Map parms = new HashMap();
121 parms.put("component", this);
122 parms.put("props", prop.toString());
123
124 PageRenderSupport prs = TapestryUtils.getPageRenderSupport(cycle, this);
125 getScript().execute(this, cycle, prs, parms);
126 }
127
128 /**
129 * Callback url used by client side widget to update server component.
130 *
131 * @return The url string to be used by the client side js function to notify
132 * this component that an update has been made.
133 */
134 public String getUpdateUrl()
135 {
136 Object[] parameters = DirectLink.constructServiceParameters(getParameters());
137
138 DirectServiceParameter dsp = new DirectServiceParameter(this, parameters);
139
140 return getEngine().getLink(isStateful(), dsp).getURL();
141 }
142
143 /**
144 * {@inheritDoc}
145 */
146 public List getUpdateComponents()
147 {
148 return Collections.EMPTY_LIST;
149 }
150
151 /**
152 * {@inheritDoc}
153 */
154 public boolean isAsync()
155 {
156 return true;
157 }
158
159 /**
160 * {@inheritDoc}
161 */
162 public boolean isJson()
163 {
164 return false;
165 }
166
167 /**
168 * {@inheritDoc}
169 */
170 public void trigger(IRequestCycle cycle)
171 {
172 String newValue = cycle.getParameter(getClientId());
173
174 setValue(newValue);
175
176 if (getListener() != null)
177 {
178 getListenerInvoker().invokeListener(getListener(), this, cycle);
179 }
180 }
181
182 /** Injected. */
183 public abstract IEngineService getEngine();
184
185 /** Injected. */
186 public abstract IScript getScript();
187
188 /** Injected. */
189 public abstract ListenerInvoker getListenerInvoker();
190 }